主题
Day 4 — Agent Runtime 设计文档
设计目标:实现 ReAct(Reasoning + Acting)推理循环,让 Agent 能与 LLM 交互、调用工具、管理迭代和超时,形成完整的"思考-行动"闭环。
一、核心接口设计
1.1 AgentConfig
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| system_prompt | str | 内置默认 | Agent 的基础人设提示词 |
| model | str | "gpt-4o-mini" | LLM 模型名称 |
| temperature | float | 0.7 | 创造性参数(0-2) |
| max_tokens | Optional[int] | None | 单次回复最大 Token 数 |
| max_iterations | int | 10 | ReAct 最大迭代次数 |
| timeout_seconds | float | 300 | 单次处理超时(秒) |
1.2 LLMProvider(抽象接口)
| 方法 | 签名 | 说明 |
|---|---|---|
| chat | async chat(messages, tools=None, **kwargs) -> LLMResponse | 同步聊天(等完整回复) |
| chat_stream | async chat_stream(messages, tools=None, **kwargs) -> AsyncIterator[str] | 流式聊天(逐字返回) |
1.3 OpenAIProvider
LLMProvider 的具体实现,封装了 AsyncOpenAI 客户端:
| 特性 | 说明 |
|---|---|
| 异步原生 | 使用 AsyncOpenAI,不阻塞事件循环 |
| 工具支持 | 自动把 tools 定义传给 API |
| 配置灵活 | 支持自定义 base_url(兼容国内模型 API) |
1.4 AgentRuntime
| 方法 | 签名 | 说明 |
|---|---|---|
| process | async process(user_input, session, **kwargs) -> str | 处理用户输入,返回最终回复 |
二、关键流程图
ReAct 推理循环
超时保护
三、设计决策与权衡
决策 1:工具错误不抛异常,而是以文本告知 LLM
| 方案 | 优点 | 缺点 |
|---|---|---|
| 错误文本化(选择) | LLM 可以自主决定如何应对(换工具、直接回答) | 错误信息可能不够结构化 |
| 抛出异常 | 错误处理清晰 | Agent 直接失败,用户收不到有意义的回复 |
| 静默忽略 | 简单 | LLM 不知道工具失败了,可能给出错误答案 |
选择理由:AI Agent 的核心价值在于自主应对。工具失败不应该导致 Agent 崩溃,而是应该让它思考替代方案。
决策 2:迭代次数硬上限
| 方案 | 优点 | 缺点 |
|---|---|---|
| max_iterations 硬限制(选择) | 简单可靠,100% 防止无限循环 | 可能在复杂任务中过早终止 |
| Token 预算限制 | 更精确 | 实现复杂 |
| 无限制 | 灵活 | 可能死循环,烧光 API 费用 |
决策 3:同步 vs 流式输出
AgentRuntime 的 process() 返回完整字符串(同步模式)。流式输出通过 LLMProvider 的 chat_stream() 支持,但需要上层自行处理。
| 方案 | 优点 | 缺点 |
|---|---|---|
| 同步返回(选择) | 简单,与 Session 集成方便 | 用户需等待完整回复 |
| 流式返回 | 用户体验好(逐字显示) | 工具调用流程复杂化 |
教学阶段优先同步模式,降低复杂度。
决策 4:LLMProvider 抽象
| 方案 | 优点 | 缺点 |
|---|---|---|
| ABC 接口(选择) | 可替换模型提供商(OpenAI → Azure → 国内模型) | 需要定义统一的 response 格式 |
| 直接依赖 openai SDK | 简单 | 锁死到 OpenAI |
四、与前序章节的集成点
- 依赖 Day 1:使用 GatewayMessage 接收用户输入
- 依赖 Day 3:Session 存储对话历史,process() 读写 Session.messages
- 被 Day 5 依赖:process() 中的工具调用逻辑依赖 ToolRegistry
- 被 Day 6 依赖:Skill 的 system_prompt 注入到 AgentConfig
- 被 Day 7 依赖:SystemPromptBuilder 替代简单的 system_prompt 字符串
五、与真实生产系统的对比
| 维度 | miniOpenClaw | 生产级实现 |
|---|---|---|
| 推理模式 | 简单 ReAct 循环 | Multi-Agent 协作、Plan-and-Execute |
| 流式输出 | Provider 层支持 | 全链路流式(Server-Sent Events) |
| 并行工具调用 | 顺序执行 | asyncio.gather 并行执行 |
| 重试机制 | 无 | 指数退避重试 + 模型 fallback |
| 成本控制 | max_iterations | Token 用量监控 + 每用户配额 |
| 可观测性 | logging | LangSmith / LangFuse 全链路追踪 |