Claude---s1---框架梳理

详细数据流转:
1️⃣ 用户发起指令与系统组装 (CLI & Initialization)
-
用户动作:在终端输入 RuiZN
run --goal "读取当前目录下的 README.md"。 -
数据流转:
-
cli/main.py接收到原生命令行参数,argparse将其解析为字符串goal。 -
AgentRunner启动,生成全局唯一的run_id(如20260722-182000-a1b2c3),并创建ExecutionContext,将goal写入上下文作为初始目标。 -
建立订阅网络:
AgentRunner将负责终端 UI 的StdoutPrinter和负责写日志的EventWriter绑定到EventBus上。 -
发布起点事件:
EventBus广播RunStartedEvent,EventWriter收到后立刻在events.jsonl中追加写入第一行 JSON 数据并flush刷盘。
-
2️⃣ 第一次 Loop:发送 Context 给 LLM (Plan 阶段)
-
数据流转:
-
AgentLoop读取当前ExecutionContext中的messages(此时包含系统 prompt 和用户的goal)。 -
构造 API 请求:
AnthropicProvider从ToolRegistry获取所有工具的 Schema(如ReadFileTool的输入参数结构),并向systemprompt 和工具列表末尾注入"cache_control": {"type": "ephemeral"}标记。 -
发起 HTTP/gRPC 流式请求:数据发送给 Anthropic Claude API。
-
流式 Token 处理:
-
API 逐字返回文本 Chunk,
AnthropicProvider捕获到 Chunk 后,向EventBus发布LlmTokenEvent。 -
StdoutPrinter收到LlmTokenEvent,调用print(token, end="", flush=True)在终端呈现打字机效果,并将内部标志位_inline置为True(表示当前处于未换行的流式输出状态)。
-
-
3️⃣ LLM 决策使用工具 (Observe 阶段)
-
数据流转:
-
API 响应接收完毕,LLM 判断需要调用工具,返回响应:
-
stop_reason:"tool_use" -
content: 包含ToolCallBlock(id="call_123", name="read_file", input={"path": "README.md"})
-
-
解析与入栈:
AnthropicProvider将其包装为LlmResponse数据对象并返回给AgentLoop。 -
AgentLoop将 LLM 的这条带有tool_use的assistant消息完整追加到ExecutionContext.messages中,作为对后续工具调用的上下文约束。
-
4️⃣ 安全调度与工具执行 (Act & Result 阶段)
-
数据流转:
-
响应格式化:
AgentLoop发现 LLM 的返回中包含tool_calls,发起invoke_tool()调用。 -
发布启动事件:向
EventBus发布ToolCallStartedEvent。-
StdoutPrinter收到事件,检查到_inline == True,先调用_ensure_newline()补打一个\n换行,然后再打印[tool] read_file {"path": "README.md"},避免日志与流式 Token 粘在一起。
-
-
安全拦截与执行(以
ReadFileTool为例):-
路由查找:
ToolRegistry查找是否存在名为read_file的工具。 -
必填校验:校验
path参数是否存在。 -
安全防线 1(路径检查):检查
path中是否包含".."。若包含,直接抛出PermissionError; -
安全防线 2(超时控制):通过
asyncio.wait_for(..., timeout=10.0)执行异步读取; -
安全防线 3(内存防爆):读取文件二进制流,若超过
512KB,截断前面部分并追加\n[truncated]。
-
-
封装结果:
-
若成功:返回
ToolResult(content="文件内容...", is_error=False)。 -
若报错(例如文件不存在或越界):被
invoke_tool()内部的try...except捕获,不让异常抛出崩溃,而是转换为ToolResult(content="PermissionError: ...", is_error=True)。
-
-
写回上下文:
AgentLoop将ToolResult包装成user角色的tool_result格式,追加回ExecutionContext.messages(如果一轮中有多个工具调用,ExecutionContext内部会自动进行数据合并)。
-
5️⃣ 第二次 Loop 与优雅收尾 (Final Step & Termination)
-
数据流转:
-
再次发起 API 请求:
AgentLoop带有最新的messages(包含上一步读取到的文件内容/错误信息)再次调用AnthropicProvider。 -
缓存命中:因为头部 Prompt 和 Tools 未变,Anthropic 服务端直接命中 Prompt Caching,响应速度大幅提升。
-
生成最终回答:LLM 结合文件内容生成总结文本,通过流式 Token 实时打字呈现在终端。
-
检测终止标志:本次 API 返回的
stop_reason == "end_turn",且没有新的tool_calls。AgentLoop识别到任务完成,退出while循环,更新context.status = "success"。 -
生命周期闭环 (
AgentRunner):-
AgentRunner捕获到 Loop 结束,向EventBus发布RunFinishedEvent。 -
StdoutPrinter打印最终统计日志(如[run] success 2 steps 1.5s)。 -
EventWriter写入最后一条 JSONL 日志,在async with上下文退出时安全关闭events.jsonl文件句柄。 -
整个进程以 Exit Code
0干净退出。
-
-
核心组件与名称含义全解析
1. 入口与生命周期管理层 (CLI & Lifecycle)
-
RuiZN
-
含义与职责:本 AI Agent 框架的 CLI 命令行工具名称。
-
-
main.py/commands.py-
含义与职责:CLI 命令入口。解析参数(如
--goal),捕获系统级信号(如 UNIX SIGINT /KeyboardInterrupt),并驱动异步主协程启动。
-
-
AgentRunner(运行组装车间)-
含义与职责:Agent 的“工厂与收尾车间”。
-
干什么的:
-
生成本次调用的唯一编号
run_id(如20260511-161020-abc123)。 -
实例化并组装所有零散组件(EventBus, ExecutionContext, Provider, Registry)。
-
注册订阅者(
StdoutPrinter和EventWriter)。 -
负责安全收尾:无论 Agent 是成功退出、超步数崩溃还是被
Ctrl+C中断,都保证发布RunFinishedEvent,并在安全关闭日志文件后再重新抛出CancelledError。
-
-
2. 状态与内存管理层 (Context & Events)
-
ExecutionContext(工作记忆与状态机)-
含义与职责:Agent 的“大脑内存卡”与“运行状态追踪器”。
-
干什么的:存储当前任务的
goal、run_id、当前步数step、终止状态status以及核心的对话历史messages。 -
关键细节:封装了 Anthropic API 的消息合并逻辑(同一轮次中的多个
tool_result必须合并进同一条user消息中)。
-
-
EventBus(事件总线)-
含义与职责:解耦的“内部广播中心”。
-
干什么的:维护订阅者列表
_subscribers。当 Loop、Tool 或 Provider 发生关键动作时发布事件(如 Token 生成、工具启动、运行完成),总线按顺序并发通知所有订阅者。
-
-
EventWriter(日志写入器)-
含义与职责:持久化“黑匣子”日志记录员。
-
干什么的:订阅 EventBus,每收到一个事件就将其序列化为 JSON 并立刻写入
events.jsonl文件(无缓冲区打折,强制flush),保证进程突发崩溃时日志不丢失。
-
-
StdoutPrinter(终端输出格式化器)-
含义与职责:终端 UI 渲染控制者。
-
干什么的:订阅 EventBus,将事件转化为终端看得懂的打印输出。
-
关键细节:维护
_inline标志位。当 LLM 处于流式打字机输出状态(未换行)时突然收到工具调用通知,_ensure_newline()会先自动补全一个换行,避免输出混成一团。
-
3. 大模型与通信层 (LLM Provider)
-
AnthropicProvider(模型适配器)-
含义与职责:与 Anthropic (Claude) API 通信的底层驱动。
-
干什么的:封装流式请求(Streaming),将 API 返回的文本片段实时转化为
LlmTokenEvent抛给 EventBus;同时负责将本地ToolRegistry的工具定义转为 API 格式。
-
-
Prompt Caching(提示词缓存机制)-
含义与职责:API 成本与性能优化手段。
-
干什么的:在
systemprompt 和tools列表末尾加上cache_control: {"type": "ephemeral"}标记,让后续轮次的重复上下文命中服务端缓存,降低 90% 的 Token 费用并加快响应。
-
4. 主循环控制器 (Control Loop)
-
AgentLoop(主循环状态机)-
含义与职责:Agent 的“核心发动机/调度控制器”。
-
干什么的:驱动
Observe ──► Act状态循环。按顺序完成:调用 LLM 决策 $\rightarrow$ 记录 LLM 回复到上下文 $\rightarrow$ 执行工具 $\rightarrow$ 记录工具返回结果 $\rightarrow$ 检查终止条件(如end_turn或达到max_steps)。
-
5. 工具系统 (Tool System)
-
BaseTool(工具基类/模板)-
含义与职责:所有工具必须遵循的抽象接口规范(继承自
abc.ABC)。 -
干什么的:定义工具的元数据(
name,description,input_schema),并强制实现async def invoke()方法。
-
-
ToolResult(工具返回数据结构)-
含义与职责:工具执行结果的标准数据包(
dataclass)。 -
核心字段:
-
content: str:给 LLM 看的工具输出内容。 -
is_error: bool:标记工具执行是否出错(即使出错也不抛出 Python 异常,而是作为结果返回)。 -
error_type: str | None:错误类型标记(如timeout,permission_error,runtime_error)。
-
-
-
ToolRegistry(工具注册表)-
含义与职责:工具的“仓库管理者”。
-
干什么的:维护工具字典
_tools。提供tool_schemas()方法直接导出适配 Anthropic API 的tools格式,供 LLM 了解当前可用的工具列表。
-
-
invoke_tool()(安全执行包装器)-
含义与职责:工具调用的“安全隔离舱/调度员”。
-
干什么的:
-
查找与校验:检查工具是否存在、必填参数(
required)是否缺失。 -
超时控制:使用
asyncio.wait_for(..., timeout=10.0)防死锁。 -
异常捕获与
_fail()兜底:捕获所有运行时报错与超时,不让异常冒泡到AgentLoop,统一转为带is_error=True的ToolResult。
-
-
-
ReadFileTool(内置读取文件工具)-
含义与职责:S1 阶段内置的具体工具示例。
-
内部三层安全边界:
-
防路径穿越:若路径包含
".."则抛出PermissionError,禁止读取上层路径。 -
防内存/Token 溢出:文件超过
512KB时自动截断,并在末尾追加\n[truncated]告知 LLM。 -
错误转化:触发任何错误后由
invoke_tool()捕获并转为错误结果给 LLM,触发 LLM 的自我纠错机制。
-
-
更多推荐




所有评论(0)