openJiuwen实战:用AsyncCallbackFramework为Agent增强器添加可观测性
做 Agent 项目的时候经常遇到这些问题:Agent 调用之后就像个黑盒,不知道内部在干什么;想加个功能只能改核心代码,风险不小;想对接外部监控系统却找不到合适的接入点。
最近研究 openJiuwen Agent Core 框架时,发现里面有个叫 AsyncCallbackFramework 的东西------框架内置的异步回调系统。这个机制正好可以解决上面的痛点:在 Agent 生命周期的关键节点设置回调点,不用修改核心代码就能增强可观测性和扩展能力。
这篇文章记录我用这个机制开发 Agent 能力增强包装器的过程。
项目地址:https://atomgit.com/openJiuwen/agent-core?utm_source=csdn
一、为什么需要回调机制
开发 Agent 时经常会遇到几个头疼的问题:
- 可观测性差:Agent 执行时看不到内部状态,调试困难、排查问题慢
- 扩展性差:加功能要改核心代码,代码耦合、维护成本高
- 集成困难:缺乏标准接口对接外部系统,生产落地门槛高
openJiuwen 的 AsyncCallbackFramework 就是来解决这些问题的。它是一个内置的异步回调系统,位于 openjiuwen.core.runner.callback 模块,提供了这些能力:
|------|----------------------------------|-------------|
| 特性 | 框架组件 | 说明 |
| 事件注册 | @framework.on(event) | 装饰器风格注册回调 |
| 事件触发 | await framework.trigger(event) | 异步触发回调执行 |
| 事件发送 | @framework.emits(event) | 函数执行后自动发送事件 |
| 过滤器 | EventFilter | 事件过滤、参数修改 |
| 链式回调 | CallbackChain | 支持回滚的回调链 |
| 性能指标 | CallbackMetrics | 自动收集性能指标 |
一开始我也想过自己实现一套回调机制,但对比后发现框架已经把这些轮子造好了:
|--------|--------------|-----------------------------|
| 对比项 | 自己写 | openJiuwen 框架 |
| LLM 调用 | 直接用 openai 库 | 通过框架的 Model 类 |
| 回调注册 | 自己实现 Handler | @framework.on(event) |
| 事件触发 | 自己实现 trigger | await framework.trigger() |
| 过滤器 | 自己写过滤逻辑 | 继承 EventFilter 类 |
| 性能指标 | 无 | CallbackMetrics 自动收集 |
简单说:框架已经把基础设施做好了,直接用就行。
二、技术架构
2.1 框架导入
先导入需要用到的模块:
# 使用 openJiuwen 框架的统一回调机制
from openjiuwen.core.runner.callback import AsyncCallbackFramework
from openjiuwen.core.runner.callback.enums import FilterAction
from openjiuwen.core.runner.callback.filters import EventFilter
from openjiuwen.core.runner.callback.models import CallbackMetrics, FilterResult
2.2 AsyncCallbackFramework 类
这是框架的核心类:
# 框架源码位置:openjiuwen/core/runner/callback/framework.py
class AsyncCallbackFramework:
"""Production-ready async callback framework"""
def __init__(self, enable_metrics: bool = True, enable_logging: bool = True):
# 核心存储
self._callbacks: Dict[str, List[CallbackInfo]] = defaultdict(list)
self._chains: Dict[str, CallbackChain] = {}
self._filters: Dict[str, List[EventFilter]] = defaultdict(list)
# ... 更多功能
2.3 使用框架装饰器注册回调
注册回调很简单,用装饰器就行:
framework = AsyncCallbackFramework()
@framework.on("user_login", priority=10) # 使用框架的 on 装饰器
async def handle_login(username: str):
print(f"User logged in: {username}")
2.4 使用框架 trigger 方法触发事件
触发事件也只需要一行代码:
# 使用框架的 trigger 方法
await framework.trigger("user_login", username="alice")
2.5 整体架构
增强包装器的整体结构:

三、环境搭建
3.1 环境要求
|------------|--------|---------------------------------|
| 组件 | 版本要求 | 说明 |
| Python | 3.11+ | 框架要求 Python 3.11 及以上 |
| openJiuwen | Latest | 核心框架(包含 AsyncCallbackFramework) |
3.2 安装步骤
# 克隆项目
git clone https://atomgit.com/openJiuwen/agent-core.git
cd agent-core
# 创建虚拟环境
python -m venv venv
venv\Scripts\activate # Windows
# 安装框架依赖
uv pip install -e .
# 进入增强包装器目录
cd examples/agent_enhancer
3.3 模型配置
项目使用 ModelScope 提供的 Kimi-K2.5 模型:
API_BASE = "https://api-inference.modelscope.cn/v1"
API_KEY = "ms-de3c153b-5a19-41d1-bd3e-257a7eef7922"
MODEL_NAME = "moonshotai/Kimi-K2.5"
四、核心模块实现
4.1 创建框架实例
第一步是创建 AsyncCallbackFramework 实例:
from openjiuwen.core.runner.callback import AsyncCallbackFramework
# 创建框架实例
framework = AsyncCallbackFramework(
enable_metrics=True, # 启用性能指标收集
enable_logging=False # 使用自己的日志系统
)
4.2 定义事件类型
定义一组事件来标记 Agent 的生命周期:
class AgentEvents:
"""
Agent 生命周期事件类型
使用 openJiuwen AsyncCallbackFramework 的事件系统定义 Agent 核心事件
"""
# 初始化事件
AGENT_INIT = "agent_init"
# 规划事件
PLAN_START = "plan_start"
PLAN_END = "plan_end"
# 工具调用事件
TOOL_CALL_BEFORE = "tool_call_before"
TOOL_CALL_AFTER = "tool_call_after"
TOOL_CALL_ERROR = "tool_call_error"
# 消息事件
MESSAGE_BEFORE = "message_before"
MESSAGE_AFTER = "message_after"
# 错误和完成事件
ERROR_OCCURRED = "error_occurred"
AGENT_COMPLETE = "agent_complete"
4.3 使用框架的 EventFilter
EventFilter 是事件过滤的基础类:
# 框架源码:openjiuwen/core/runner/callback/filters.py
class EventFilter(ABC):
@abstractmethod
async def process(
self,
event: str,
data: Dict[str, Any],
context: Optional[Dict[str, Any]] = None
) -> FilterResult:
"""处理事件并返回过滤结果"""
继承它来实现内容过滤:
from openjiuwen.core.runner.callback.filters import EventFilter
from openjiuwen.core.runner.callback.models import FilterResult
from openjiuwen.core.runner.callback.enums import FilterAction
class ContentFilter(EventFilter):
"""
内容过滤过滤器 - 基于 openJiuwen 框架的 EventFilter
在消息分发前过滤敏感信息
"""
PATTERNS = {
'phone': r'1[3-9]\d{9}',
'email': r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}',
'id_card': r'\d{15}|\d{17}[\dXx]',
}
async def process(
self,
event: str,
data: Dict[str, Any],
context: Optional[Dict[str, Any]] = None
) -> FilterResult:
"""过滤处理 - 实现框架 EventFilter 的 process 方法"""
message = data.get("message", "")
# 检测敏感信息
detected = []
filtered_message = message
for name, pattern in self.PATTERNS.items():
import re
matches = re.findall(pattern, filtered_message)
if matches:
detected.extend([(name, m) for m in matches])
filtered_message = re.sub(
pattern,
lambda m: '*' * len(m.group()),
filtered_message
)
if detected:
# 返回 MODIFY 操作,告知框架修改数据
return FilterResult(
FilterAction.MODIFY,
modified_data={"message": filtered_message},
metadata={"detected": detected}
)
# 返回 ALLOW,放行事件
return FilterResult(FilterAction.ALLOW)
4.4 可观测性模块
用框架的 @framework.on() 装饰器注册回调:
from openjiuwen.core.runner.callback import AsyncCallbackFramework
class ObservabilityModule:
"""可观测性模块 - 使用框架的 @on 装饰器"""
def __init__(self, framework: AsyncCallbackFramework):
self.framework = framework
self._register_callbacks()
def _register_callbacks(self):
"""使用框架的 @framework.on 装饰器注册回调"""
@self.framework.on(AgentEvents.AGENT_INIT, priority=100)
async def _on_init(*args, **kwargs):
"""Agent 初始化回调 - 使用框架装饰器注册"""
agent_id = kwargs.get("agent_id", "unknown")
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"{'='*60}")
print(f"Agent 初始化")
print(f" Agent ID: {agent_id}")
print(f" 时间: {timestamp}")
print(f"{'='*60}")
@self.framework.on(AgentEvents.TOOL_CALL_AFTER, priority=100)
async def _on_tool_after(*args, **kwargs):
"""工具调用后回调"""
tool_name = kwargs.get("tool_name", "")
duration = kwargs.get("duration_ms", 0)
print(f"[工具] 工具返回: {tool_name}")
print(f" 耗时: {duration:.2f}ms")
4.5 增强 Agent 类
在 Agent 执行的关键节点用 trigger 触发事件:
# 导入事件类型
try:
from .enhancer_core import AgentEvents
except ImportError:
from enhancer_core import AgentEvents
class EnhancedAgent:
"""增强后的 Agent - 使用框架的 trigger 方法"""
async def invoke(self, inputs: Dict[str, Any], session_id: str = None):
"""调用 Agent(增强版)"""
query = inputs.get("query", "")
# 1. 使用框架的 trigger 触发规划开始事件
await self._framework.trigger(
AgentEvents.PLAN_START,
query=query,
agent_id=self._current_agent_id
)
# 2. 使用框架的 trigger 触发消息前事件
await self._framework.trigger(
AgentEvents.MESSAGE_BEFORE,
message=query,
agent_id=self._current_agent_id
)
# 3. 调用原始 Agent
session = Session(session_id=session_id or "default")
result = await self._agent.invoke(inputs, session=session)
# 4. 使用框架的 trigger 触发完成事件
await self._framework.trigger(
AgentEvents.AGENT_COMPLETE,
result=result,
agent_id=self._current_agent_id
)
return result
4.6 主包装器类
把所有模块组合起来:
from openjiuwen.core.runner.callback import AsyncCallbackFramework
class AgentEnhancer:
"""
Agent 能力增强包装器
基于 openJiuwen 框架的 AsyncCallbackFramework 实现
"""
def __init__(
self,
framework: Optional[AsyncCallbackFramework] = None,
enable_observability: bool = True,
enable_capability: bool = True,
enable_integration: bool = True,
...
):
# 创建或使用传入的框架实例
self.framework = framework or AsyncCallbackFramework(
enable_metrics=True,
enable_logging=False
)
# 创建并注册模块
if enable_observability:
self.observability = ObservabilityModule(self.framework, ...)
if enable_capability:
self.capability = CapabilityModule(self.framework, ...)
if enable_integration:
self.integration = IntegrationModule(self.framework, ...)
4.7 工作流程
用户调用增强包装器后,完整的执行流程如下:

整个流程的核心是:AsyncCallbackFramework 作为事件总线,连接各个功能模块。Agent 执行的每个关键节点都会触发相应事件,各个模块通过注册回调函数来响应这些事件。
五、效果展示
5.1 演示 1:基本使用
运行 demo 看看效果:
cd examples/agent_enhancer
python demo.py

5.2 演示 2:可观测性模块
可以看到 Agent 执行的完整追踪信息,包括工具调用、耗时统计等:

5.3 演示 3:内容过滤
当消息中包含敏感信息时,会自动过滤:

5.4 演示 4:集成能力
审计日志和通知推送:

55 演示5:完整执行报告

六、对比自己实现回调
6.1 架构对比
|------|------------------------|---------------------------------|
| 对比项 | 简单封装 | openJiuwen 框架方式 |
| 回调注册 | 自己实现 CallbackHandler | 框架的 @framework.on(event) 装饰器 |
| 事件触发 | 自己实现 trigger() 方法 | 框架的 await framework.trigger() |
| 过滤器 | 自己实现过滤逻辑 | 框架的 EventFilter 基类 |
| 性能指标 | 无自动收集 | 框架的 CallbackMetrics 自动收集 |
| 事件历史 | 需自己实现 | 框架内置事件历史(_event_history) |
| 链式回调 | 不支持 | 框架的 CallbackChain 支持 |
6.2 代码对比
简单封装方式:
# 自己实现回调处理器
class CallbackHandler:
def __init__(self):
self._callbacks = defaultdict(list)
def register(self, event_type, callback):
self._callbacks[event_type].append(callback)
async def trigger(self, event):
# 自己实现触发逻辑
...
使用框架的方式:
# 使用框架的 AsyncCallbackFramework
from openjiuwen.core.runner.callback import AsyncCallbackFramework
framework = AsyncCallbackFramework(enable_metrics=True)
@framework.on("event_name", priority=10) # 框架装饰器
async def callback_handler(*args, **kwargs):
...
await framework.trigger("event_name", data=value) # 框架触发器
6.3 过滤器对比
简单封装方式:
# 自己实现过滤逻辑
def check_filter(data):
if "敏感词" in data["message"]:
return {"allowed": False, "modified": "..."}
return {"allowed": True}
使用框架的方式:
# 使用框架的 EventFilter
from openjiuwen.core.runner.callback.filters import EventFilter
from openjiuwen.core.runner.callback.models import FilterResult
from openjiuwen.core.runner.callback.enums import FilterAction
class MyFilter(EventFilter):
async def process(self, event, data, context):
if "敏感词" in data.get("message", ""):
return FilterResult(FilterAction.DENY)
return FilterResult(FilterAction.ALLOW)
# 注册到框架
framework._filters["event_name"] = [MyFilter()]
七、总结
本项目用了 openJiuwen 框架的统一回调机制来增强 Agent 的能力:
|----------------------------|-----------------------------|
| 用到的框架能力 | 说明 |
| AsyncCallbackFramework | 框架内置的回调系统 |
| 装饰器风格注册 | @framework.on(event) |
| 异步触发器 | await framework.trigger() |
| EventFilter 过滤器 | 继承实现过滤逻辑 |
| CallbackMetrics 指标 | 自动收集性能数据 |
框架带来的好处:
- 生产级实现:框架内置的回调系统经过充分测试
- 统一接口:所有回调使用相同的注册和触发机制
- 可观测性:内置性能指标收集和事件历史
- 可扩展性:支持过滤器、链式回调等高级特性
- 异步优先:全异步设计,高性能处理
参考资源
- openJiuwen 官网:https://openJiuwen.com?utm_source=csdn
- 框架源码:https://atomgit.com/openJiuwen/agent-core?utm_source=csdn
- AsyncCallbackFramework 文档:
openjiuwen/core/runner/callback/ - 项目源码:
examples/agent_enhancer/