Problem Statement
NanoAgent 目前缺乏细粒度的 agent 执行生命周期追踪。只有 session 级别的 start_session/end_session,没有 turn、message、tool 三层的显式事件。这导致:
- 流式输出的中间状态无法追踪
- 外部系统(UI、日志、调试工具)无法感知 agent 执行进度
- observability 的记录分散在
llm/client.py 和 tools/registry.py 中,耦合在调用路径里
Solution
引入 Lifecycle 类作为 NanoAgent.run() 的局部实例,管理严格嵌套的三层事件:
agent_start
└─ turn_start (循环 N 次)
├─ message_start → message_update* → message_end
├─ tool_execution_start → tool_execution_update* → tool_execution_end (循环 N 次)
└─ turn_end
└─ agent_end
事件通过 emit(type, data) 同步分发,外部通过 subscribe(handler) 注册回调。
Commits
-
定义 LifecycleEvent 类型枚举和 dataclass — 新建 core/lifecycle.py,定义所有事件类型 (AgentEvent union) 和 TurnContext dataclass,不含任何 agent 逻辑
-
实现 Lifecycle 类骨架 — Lifecycle.subscribe(), emit(), flush() 方法,_handlers 列表存储回调,不含事件发射逻辑
-
集成 Lifecycle 到 NanoAgent.run() 主循环 — 在 run() 中创建 lifecycle = Lifecycle(),添加 agent_start/agent_end 事件包裹,不改现有逻辑
-
添加 turn 边界事件 — 在传统模式的 while True 循环中添加 turn_start/turn_end 包裹
-
添加 message 事件 — 在 llm.chat() 调用前后添加 message_start/message_end 包裹
-
添加 tool 事件 — 在 _execute_tool_invocations 中对每个工具调用添加 tool_execution_start/tool_execution_end
-
实现流式 update 事件 — 在 stream_chat 的 callback 中 emit message_update,在工具执行中间 emit tool_execution_update
-
集成 Tracer 为内置 subscriber — 将 Tracer 改为 lifecycle subscriber,record_llm/record_tool 内部改为 lifecycle.emit(),消除调用路径耦合
-
添加 Lifecycle 单元测试 — 测试事件嵌套合法性、handler 注册/注销、流式 update 顺序
Decision Document
- 发布机制:
Lifecycle.emit(type, data) 同步分发,handler 抛出则中断
- 生命周期:
Lifecycle 作为 NanoAgent.run() 的局部实例,每次 run 独立
- 嵌套保证: 通过
_depth 计数器验证 agent > turn > message/tool 严格嵌套
- Streaming:
message_update / tool_execution_update 支持流式中间状态
- 兼容: 保留
Tracer 单例 API,内部改为事件触发,不破坏现有调用方
- 持久化:
Tracer 作为 subscriber 接收所有事件,写入 SQLite
- 模块位置:
core/lifecycle.py — 新文件,不修改现有文件结构
Testing Decisions
- 单元测试:
Lifecycle 的嵌套合法性(深度验证)、handler 注册/注销、事件分发顺序
- 集成测试: 在 mock 模式下跑
agent.run(),验证事件顺序正确
- Prior art: 参考现有
tests/agent/ 测试框架风格
Out of Scope
chat() 交互模式的生命周期(仅 run() 方法)
- 异步版本的 agent
- 事件持久化 schema 变更
- LLM router/chain 模式的细粒度事件
Further Notes
参考 Anthropic SDK 的事件生命周期设计(agent > turn > message/tool 三层嵌套)。
Problem Statement
NanoAgent 目前缺乏细粒度的 agent 执行生命周期追踪。只有 session 级别的
start_session/end_session,没有 turn、message、tool 三层的显式事件。这导致:llm/client.py和tools/registry.py中,耦合在调用路径里Solution
引入
Lifecycle类作为NanoAgent.run()的局部实例,管理严格嵌套的三层事件:事件通过
emit(type, data)同步分发,外部通过subscribe(handler)注册回调。Commits
定义 LifecycleEvent 类型枚举和 dataclass — 新建
core/lifecycle.py,定义所有事件类型 (AgentEventunion) 和TurnContextdataclass,不含任何 agent 逻辑实现 Lifecycle 类骨架 —
Lifecycle.subscribe(),emit(),flush()方法,_handlers列表存储回调,不含事件发射逻辑集成 Lifecycle 到 NanoAgent.run() 主循环 — 在
run()中创建lifecycle = Lifecycle(),添加agent_start/agent_end事件包裹,不改现有逻辑添加 turn 边界事件 — 在传统模式的
while True循环中添加turn_start/turn_end包裹添加 message 事件 — 在
llm.chat()调用前后添加message_start/message_end包裹添加 tool 事件 — 在
_execute_tool_invocations中对每个工具调用添加tool_execution_start/tool_execution_end实现流式 update 事件 — 在
stream_chat的 callback 中 emitmessage_update,在工具执行中间 emittool_execution_update集成 Tracer 为内置 subscriber — 将
Tracer改为 lifecycle subscriber,record_llm/record_tool内部改为lifecycle.emit(),消除调用路径耦合添加 Lifecycle 单元测试 — 测试事件嵌套合法性、handler 注册/注销、流式 update 顺序
Decision Document
Lifecycle.emit(type, data)同步分发,handler 抛出则中断Lifecycle作为NanoAgent.run()的局部实例,每次 run 独立_depth计数器验证agent > turn > message/tool严格嵌套message_update/tool_execution_update支持流式中间状态Tracer单例 API,内部改为事件触发,不破坏现有调用方Tracer作为 subscriber 接收所有事件,写入 SQLitecore/lifecycle.py— 新文件,不修改现有文件结构Testing Decisions
Lifecycle的嵌套合法性(深度验证)、handler 注册/注销、事件分发顺序agent.run(),验证事件顺序正确tests/agent/测试框架风格Out of Scope
chat()交互模式的生命周期(仅run()方法)Further Notes
参考 Anthropic SDK 的事件生命周期设计(agent > turn > message/tool 三层嵌套)。