Skip to content

03 · 如何实现一个 Agent? - Agent Implementation ​

所属知识库:Agent 全栈技术地图
所属领域:02 · Agent
所属章节:03 · 如何设计、构建和测试 Agent? - Development & Practice
文档类型:技术原理与工程实践研究
版本:v2.0
更新日期:2026 年 10 月 28 日
核心问题:如何把 Agent 的任务契约和有效配置落实为可运行的软件,具体实现模型调用、结构化决策、工具执行、权限校验、状态转换、预算控制、错误处理、可观测性与测试,并在真实框架和自建运行循环之间做出有证据支持的工程选择?

一、问题定位:从设计文档到可运行的 Agent ​

本篇属 Development & Practice。前两篇 Design 与 Configuration 分别产出任务契约、架构方案和有效配置。Implementation 的任务是把这些声明变成可观察的执行行为:模型如何接收上下文、如何提出下一步行动,程序如何校验并执行工具,工具观察如何写入状态,任务如何在成功、失败、预算耗尽或等待人工审批时终止。

核心区分是:模型提供决策建议,Runtime 执行控制与状态管理,可信工具层实施外部动作与授权。模型生成 {"tool":"send_email"} 只是一个行动请求;只有程序完成参数校验、身份与权限检查并调用邮件系统后,外部动作才实际发生。把这三者混为一谈,是很多“能演示、难上线”Agent 的根源。

本文研究的是单 Agent 的实现边界。通用多 Agent 调度、分布式执行、持久化检查点集群、租户资源调度等归入 Agent System;平台化 Agent 创建、发布、监控与计费归入 Agent Platform。单 Agent 可以使用这些基础设施,但不必在本篇重新实现整个系统。

1.1 最小可用 Agent 与工程可用 Agent ​

最小可用 Agent 需要输入、模型、工具、循环与输出。工程可用 Agent 还需要严格契约、可控终止、权限、失败路径、运行记录、可重现配置、回归测试。两者之间的差距不是多写几段 Prompt,而是建立可执行的不变量。

工程属性最小演示工程实现要求
模型输出直接读取自然语言结构化决策及解析失败处理
工具调用按工具名执行函数注册表、参数验证、身份授权、超时与副作用管理
状态消息列表任务状态、观察证据、事件、配置摘要
终止模型说“完成”成功契约、预算、截止时间、失败原因
错误抛异常分类、记录、受控重试、必要时暂停
测试跑通一次单元、集成、故障注入、真实任务评测

二、总体架构:控制流、数据流与信任边界 ​

mermaid
flowchart TD
  U[TaskSpec 用户任务] --> V[任务校验]
  C[EffectiveConfig 有效配置] --> R[Run Controller]
  V --> R
  R --> B[Context Builder]
  B --> M[Model Adapter]
  M --> P[Decision Parser]
  P -->|tool| G[Tool Gateway]
  P -->|finish / stop| F[结果验证 / 终止]
  G --> A[Policy / Authorization]
  A --> X[Tool Executor]
  X --> O[Observation]
  O --> S[State Reducer / Event Log]
  S --> R
  F --> S

控制流由 Controller 持有:每次模型调用之前检查预算与截止时间;每次模型返回后先解析、再分派;每次工具执行后更新状态。数据流由 TaskSpec、Context、Decision、Observation 和 State 组成。信任边界出现在外部输入进入模型上下文、模型意图进入工具网关、工具返回进入证据状态三个位置。

建议将以下四种对象分离:TaskSpec 是不可随意修改的用户目标;EffectiveConfig 是运行开始时已校验的能力与约束快照;RunState 是任务执行中不断变化的事实;RunEvent 是带顺序号、时间及关联 ID 的操作记录。它们的生命周期不同,混入一个可变字典会使恢复、审计和测试复杂化。

三、执行循环的精确定义 ​

一个受约束的 Agent 循环可抽象为状态转移:

St+1=δ(St,validate(M(C(St))),Ot)

其中 C 根据状态构建模型上下文,M 产生候选行动,validate 检查输出契约,O 是执行工具后得到的观察。对于 finish 行动没有工具观察,而应执行最终结果验证。该表达只是软件状态转移的抽象,不意味着模型决策是确定性的。

text
validate(task, effective_config)
state = initialize_run()
while state.status == RUNNING:
    enforce_deadline_and_step_budget()
    context = build_context(task, state, effective_config)
    candidate = model.generate(context)
    decision = parse_and_validate(candidate)
    match decision:
        ToolCall:
            enforce_tool_budget()
            authorize(identity, tool, arguments, resource)
            observation = execute_with_timeout(tool, arguments)
            append_event_and_reduce_state(observation)
        Finish:
            verify_output_contract_and_evidence(decision)
            mark_completed_or_failed()
        Stop:
            mark_stopped_with_reason()

3.1 决策协议:判别联合类型 ​

推荐显式区分三种行动:

json
{"kind":"tool","name":"search_evidence","arguments":{"query":"Agent architecture"}}
{"kind":"finish","answer":"...","citations":["doc-1"]}
{"kind":"stop","reason":"INSUFFICIENT_EVIDENCE"}

这不是模型提供商统一协议,而是本篇参考 Runtime 的内部契约。真实 API 的原生 function calling 结构需要由适配器转换为该内部协议。解析器必须检查字段类型、必填字段、未知字段、工具是否存在、参数是否符合 Schema。不能用正则从任意模型文本中提取 shell 命令后执行。

3.2 一次调用与一个执行步骤不一定相同 ​

某些模型一次返回多个工具调用;一次工具调用可能产生多个事件;某些框架有 handoff、interrupt、streaming 等额外事件。max_steps 需要明确计数语义(模型决策轮次、图节点数还是工具执行数),不能假定不同框架的“step”可以直接比较。

3.3 终止条件 ​

终止状态至少区分 COMPLETED、STOPPED、FAILED、WAITING_APPROVAL。COMPLETED 表示输出满足契约,不只是模型声称任务完成;STOPPED 可以是用户取消、预算耗尽或证据不足;FAILED 表示未能恢复的执行错误。等待审批不是失败,也不应伪装成成功。

四、模型适配器:提供商 API 与 Agent Runtime 的接口 ​

模型适配器承担:构造请求、发送请求、处理超时与提供商错误、解析模型输出、保留用量与模型标识,并转换为 Runtime 可理解的决策。模型不应该直接持有工具执行器或数据库连接。

4.1 两条实现路线 ​

路线 A:自行控制循环。 应用直接调用模型 API,自己解析决策、执行工具和更新状态。优势是控制流完全可见、可实现严格业务契约;代价是必须自己维护历史、重试、追踪、工具协议和升级兼容。

路线 B:使用 Agent SDK / 框架。 由框架处理循环、工具分派、状态或图执行,应用注入业务工具、策略与数据。优势是复用成熟抽象;代价是必须理解框架的生命周期、配置覆盖、异常语义与隐藏的执行行为。

OpenAI 官方文档明确区分直接使用 Responses API、自主管理循环,与使用 Agents SDK 让 Runner 管理工具、handoff、会话等运行机制。SDK 的基本循环是模型调用、检查输出、执行工具或 handoff、继续,直到产生最终结果。见文末 [S1][S2]。

4.2 最小真实 API 适配器的限制 ​

配套 runtime.py(完整包 03-Agent-Implementation-v2.0.zip)提供可选 ResponsesModel:通过 HTTPS 向 /v1/responses 发送 instructions 与 input,读取响应的 output 内容并将 output_text 解析为 JSON 决策。它没有启用提供商原生工具调用,原因是本实验要将工具执行权明确保留在本地 Runtime。该适配器仅用于演示“真实模型可替换模拟决策器”的边界,不是完整 SDK 替代品。

重要限制:当前示例没有实现流式解析、提供商原生工具事件、结构化输出模式、速率限制重试、真实 token 计费、异步并发、长任务恢复。模型可能输出非 JSON,代码会明确失败而不是执行猜测的行动。真实模式需要 API Key、网络与支持该请求的模型;本次未实测真实模式。

4.3 使用官方 SDK 的更短路径 ​

官方 Python Agents SDK 文档展示了 Agent(name=..., instructions=...) 与 Runner.run(agent, input) 的基本用法,并提供 run_sync、run_streamed 等形式;当前文档还描述了 RunConfig、Session、工具执行并发配置等。对需要自定义执行控制的项目,应审查 SDK 实际支持哪些 guardrail、approval 与运行边界,而不是仅凭 SDK 提供工具接口就认为权限安全。见 [S2][S3][S4]。

五、工具网关:将模型意图转为可信动作 ​

工具调用应经过四道检查:

  1. 名称与注册表:模型请求的工具是否存在,是否在本 Agent 允许列表中。
  2. 参数与契约:字段类型、枚举、长度、资源标识与业务不变量是否正确。
  3. 身份与权限:当前用户、租户、任务和资源是否允许这次操作。
  4. 执行与副作用:是否需要审批、幂等键、事务、沙箱或速率限制。

设注册工具集合为 D,Agent 配置白名单为 C,针对主体和资源的实时授权集合为 A(p,r),真正可执行集合为 D ∩ C ∩ A(p,r)。配置白名单不等于授权:本篇最小代码仅实现静态白名单,未实现多租户身份验证或真实资源级授权,不能用于敏感生产工具。

5.1 工具返回不是天然可信事实 ​

检索网页或文档得到的文本属于外部数据,可能包含错误信息和提示注入。Runtime 应将工具结果封装为带来源、时间、工具 ID、错误状态的 Observation;不要把网页中的“请忽略此前指令”提升为高优先级指令。引用检查应验证来源确实被检索到,而内容真实性仍需独立评价。

5.2 读操作与写操作的不同重试语义 ​

查询类工具通常可以在超时后安全重试,但仍需考虑配额与成本。发邮件、支付、提交订单等具有副作用的工具,超时不代表操作未成功:可能是远端执行成功但本地未收到响应。必须优先使用服务端幂等键、状态查询或事务性操作记录,避免简单重试导致重复副作用。

5.3 审批位置 ​

人工审批应在有副作用的操作真正执行之前进行。OpenAI 官方的 guardrails / human review 指南将输入、输出、工具校验与人工审批区分,并指出敏感动作应在执行前暂停等待批准。见 [S4]。审批通过后仍应重新检查实时授权与资源状态,防止审批等待期间条件变化。

六、状态、事件与上下文管理 ​

6.1 状态与事件不是同一对象 ​

状态是当前事实快照,例如证据列表、预算余额和任务状态;事件是发生过的动作,如 MODEL_DECISION、TOOL_RESULT、TOOL_ERROR、STOP。只存状态会失去“为什么到达此状态”的证据;只存事件则需要重放才能恢复当前状态。生产实现可使用事件日志与检查点组合,但持久化策略属于更深的 Agent System 研究。

6.2 Context Builder 的职责 ​

模型上下文应包含:稳定任务契约、可用工具描述、当前状态摘要、必要的观察证据和输出格式要求。应避免把完整原始日志无限追加。对研究助理而言,证据 ID、来源和主题映射通常比全部聊天历史更重要。上下文压缩必须保留事实与来源之间的可追溯关系。

6.3 中断与恢复的实际语义 ​

LangGraph 官方资料描述:interrupt() 可以在节点内暂停图执行,并依赖 checkpointer 保存状态;恢复使用 Command(resume=...) 和同一 thread ID。尤其需要注意,恢复时节点可能从头重新执行,因而中断前的副作用代码可能再次运行。这个细节直接影响审批前后的工具设计,应将副作用放在可重入安全的位置或使用幂等保障。见 [S5]。

本篇配套 Runtime 没有实现持久化恢复,不能因为记录了事件就声称支持崩溃后继续运行。

七、预算、超时与错误分类 ​

Agent 执行存在至少四种预算:模型轮次、工具调用数、总墙钟时间、真实货币成本。它们的计数对象不同,不能互相替代。特别是并发执行时,预算检查必须在资源分配前原子预留,否则多个调用可能同时通过检查导致超限。

错误类型典型原因处理原则
模型格式错误返回不符合结构化契约拒绝执行,必要时受控修复
提供商超时/限流网络、容量、额度有界退避;尊重截止时间
工具参数错误类型、缺字段、越界明确失败或让模型重新规划
权限拒绝工具或资源未授权Fail closed;不能自动升级权限
工具超时外部服务不响应区分只读与副作用操作
证据不足检索无结果或质量不够明确停止或追加受预算约束的检索
预算耗尽步数、调用、时间或成本上限终止并报告已完成部分
状态不一致并发写入或恢复冲突检测版本冲突、回滚或人工介入

参考代码通过 max_steps、max_tool_calls、deadline_seconds 展示三个确定性边界;它不计算真实 token 与货币成本,也没有实现跨进程原子预算预留。

八、真实框架的实现差异:三个观察尺度 ​

8.1 自建循环(Responses API + 自有 Controller) ​

调用链由应用掌握:ContextBuilder → ModelAdapter → Parser → Gateway → Reducer。适用于权限、状态和终止语义需要高度定制的单 Agent;开发者承担较多基础设施责任。

8.2 OpenAI Agents SDK ​

官方文档说明 Runner 管理 Agent 循环,并提供工具、handoff、guardrails、sessions 与 tracing 等机制。对于单 Agent 应用,可以把业务工具作为函数工具交给 SDK,而不是重新实现整个循环。其 RunConfig 与工具执行配置会影响运行时行为,例如本地函数工具并发限制与工具名未匹配时的处理策略。具体参数应以部署时 SDK 版本文档为准。见 [S1][S2][S3]。

需要研究的代码边界是:SDK 何时调用模型、如何解析工具事件、何时执行 guardrail、如何记录 trace、何时触发最大轮次或中断。框架提供 guardrail 并不自动等同于业务授权;敏感工具仍需应用自己的身份与资源校验。

8.3 LangGraph ​

LangGraph 将状态与节点执行组织为图结构,适合需要显式流程节点、状态转移、分支、人工中断与检查点的应用。与“模型每次自由决定下一步”的循环不同,图的节点和边可把一部分控制权固定在程序层。官方源码与文档中可核查 StateGraph、interrupt、Command 和 checkpointer 的契约;状态 reducer、并行更新与持久化语义需要按具体版本测试。见 [S5][S6]。

维度自建 RuntimeAgents SDKLangGraph
控制结构自定义循环SDK Runner 循环显式图与状态更新
工具执行应用全权实现SDK 集成工具调用由节点/工具组件实现
状态应用自建SDK 提供会话/运行结果能力图状态与检查点能力
人工介入自建暂停/恢复官方审批机制interrupt / resume
主要取舍灵活但维护成本高集成速度与抽象约束流程可见性与图设计复杂度

这不是基准测试排名。不同框架可以互相组合,也可以在不同层承担不同职责。是否采用某框架,应根据任务控制权、可观察性、状态恢复、工具授权、团队经验和部署环境判断。

九、完整工程实验:技术研究助理的最小 Runtime ​

9.1 文件与环境 ​

本次提供配套包 03-Agent-Implementation-v2.0.zip(目录 runtime.py 等),Python 3 标准库(含 3.9)。它包含:Config、State、Event、模型协议、确定性模型、可选真实 Responses API 适配器、工具、决策解析器、Controller 与 12 项单元测试。

bash
python3 runtime.py --test
python3 runtime.py --mode mock --question "agent architecture" --output run.json

本地执行 python3 runtime.py --test:12 项确定性测试全部通过。真实 API 模式未在本次交付环境实测。

若要尝试真实 API(本次未实际验证),先在本地安全设置 OPENAI_API_KEY,再运行:

bash
python3 runtime.py --mode real --model gpt-4.1-mini --question "agent architecture"

模型名仅为示例默认值,实际可用性取决于账号、模型生命周期与 API 兼容性;如模型不支持或响应结构变化,应核对当日官方文档并修改适配器。不要把密钥写入代码、提交到仓库或附在执行日志中。

9.2 实验执行路径 ​

以模拟模式执行 agent architecture:

  1. Controller 初始化任务与事件;
  2. 模拟模型在证据为空时提出 search_evidence 请求;
  3. Parser 验证结构;Gateway 检查工具白名单与调用预算;
  4. 本地工具返回 doc-agent-1;Controller 将观察写入证据状态;
  5. 模拟模型返回 finish,引用已获取的 doc-agent-1;
  6. Controller 检查引用存在,设置 COMPLETED 并写入结束事件。

这条路径说明“模型建议 - 程序验证 - 工具执行 - 状态更新 - 结果校验”的基本机制,不说明研究报告已经达到真实业务质量。

9.3 实验实际验证结果 ​

本地执行 12 项确定性单元测试,全部通过。测试覆盖:成功路径、事件顺序、虚构引用拒绝、无效模型决策、工具白名单拒绝、工具预算、步数预算、工具超时、模型主动停止、无效配置、空输入和截止时间。

测试不能证明的内容:真实 LLM 是否遵守 JSON 协议;模型在复杂任务中的规划能力;真实网络调用与成本;租户级权限;副作用幂等;生产环境中断恢复;多轮上下文的质量。这些需要单独的集成测试、真实模型评测与安全审查。

9.4 代码中刻意保留的局限 ​

  • EvidenceTool 是内存中的合成证据库,不是真实检索系统。
  • allowed_tools 只实现静态允许列表,没有身份和资源级授权。
  • 模型适配器直接解析文本 JSON,未启用原生结构化输出或 function calling。
  • 模型请求是同步 HTTP 调用;没有流式响应与异步取消。
  • 截止时间在循环边界检查,无法强制中断已经阻塞的任意工具。
  • 事件保存在内存;崩溃后无法恢复。
  • 引用校验只检查 ID 是否出现过,不判断证据是否支持结论。
  • 没有费用估算、价格版本和原子预算预留。

明确这些限制比将教学代码称为“生产级 Agent”更符合工程研究标准。

十、从教学 Runtime 走向可部署工程 ​

建议按以下顺序扩展:

阶段 A:真实模型与工具接口。 使用官方 SDK 或直接 API,实现真实模型调用、原生工具事件解析、超时、限流、结构化输出校验和真实检索工具。建立模型/工具契约测试。

阶段 B:安全与副作用控制。 为工具网关接入用户身份、资源授权、审批与审计;为写操作引入幂等键与外部状态查询;隔离代码执行环境。不能依赖 Prompt 作为唯一防线。

阶段 C:状态与恢复。 定义持久化状态、运行 ID、配置快照、事件存储与恢复协议;验证中断前后重复执行、任务取消与状态迁移。复杂跨进程运行转入 Agent System 研究。

阶段 D:可观测性与评测。 为每次模型调用和工具执行记录关联 ID、耗时、用量、错误类型和输出版本;建立固定任务集、异常注入和真实模型重复评测。

阶段 E:灰度与回滚。 对模型、Prompt、工具和策略变更做回归,记录实际解析版本;在质量、成本或安全指标下降时恢复到已验证配置。

十一、工程选型的决策框架 ​

任务条件推荐优先考虑必须验证
步骤稳定、动作风险高确定性工作流是否真的需要模型自由决策
单 Agent、工具较少、控制要求特殊自建受约束循环异常、权限、维护成本
需要快速构建工具型 AgentAgent SDKRunner 生命周期、授权和版本兼容
分支复杂、状态明确、需暂停恢复状态图/图式 Runtimecheckpoint、节点重入、副作用安全
需要长时运行、多任务调度、多 AgentAgent System 方案持久化、队列、隔离与资源治理

设计原则是把可确定的约束留在程序层,把需要语义判断的局部问题交给模型。模型越强,并不意味着越应该将所有控制权交给模型。

十二、典型故障与调试路径 ​

  1. 模型反复调用同一工具:检查任务停止条件、证据状态是否真正更新、模型是否看到工具观察,以及预算是否有效。
  2. 工具调用未执行却被写入成功日志:区分模型决策事件、网关授权事件、工具实际执行事件。
  3. 输出出现虚构引用:将最终引用与证据注册表关联,建立引用存在性与证据支持性两层验证。
  4. 工具超时后重复发送:审查副作用、幂等键与远端结果查询机制。
  5. 配置改变后行为漂移:记录有效配置、模型实际标识、Prompt 与工具版本,不只记录 Git 提交。
  6. 人工审批恢复后重复执行:检查框架中断恢复语义,避免在可能重入的节点中放置未受保护的副作用。
  7. 成本超过限制:区分模型 token、工具计费与并发预留;仅有 max_steps 不构成完整成本上限。

排查顺序建议为:确认有效配置 → 确认输入与模型响应 → 确认 Parser → 确认授权与工具执行 → 确认状态更新 → 确认终止逻辑 → 再讨论模型“智能程度”。

十三、质量验收与后续研究 ​

本篇可作为 Implementation 专题的技术机制与参考工程实现版,其质量验收应包括:

  • [x] 给出完整控制流、数据流、信任边界和关键对象契约。
  • [x] 实现最小运行循环、决策解析、工具白名单、状态、事件和终止。
  • [x] 用确定性测试覆盖正常路径与关键失败路径。
  • [x] 对比自建循环、Agents SDK 与 LangGraph 的控制方式。
  • [x] 结合官方文档核对 SDK 运行循环与图式中断语义。
  • [ ] 固定依赖版本并运行真实模型端到端实验。
  • [ ] 对指定版本框架做逐文件源码审计与运行轨迹对照。
  • [ ] 实现资源级授权、审批恢复、幂等和持久化。
  • [ ] 完成真实任务数据集上的质量、成本与可靠性评测。

因此,本文不应被标记为生产工程验证完成。它完成了研究框架、关键执行语义、部分官方资料核对和最小确定性实现;下一步应通过真实集成与专题 Testing 形成更高等级的证据。随后可通过 Case Studies 对照真实开源项目的实现差异。

十四、核心结论 ​

Agent Implementation 的关键不在于“循环调用模型直到它回答”,而在于建立模型决策与可信执行之间的严格契约。模型可以提出行动、解释证据和生成内容;程序必须负责验证行动、授权工具、维护状态、执行预算、记录事件并确定任务终止。框架能够减少基础设施开发,但不能替代业务级权限、数据质量和工程验收。

这一实现边界也构成后续 Agent System 的基础:当多个 Agent、长任务和多租户应用共享这些运行能力时,单 Agent 内部的 Controller、状态与工具网关将逐步演化为可复用的运行时服务与协作架构。

参考资料与核验记录 ​

以下资料于 2026-10-28 检索;引用的是官方文档或项目维护者源码入口,部分文档会随版本更新。本文未固定安装并逐项验证这些框架的最新发布版本,因此涉及 API 细节时仍应以实际部署版本为准。

研究边界声明:本篇对 [S1] - [S7] 的引用用于支持所述框架机制;自建 Runtime 的结构与工程建议是本文的参考设计,并非任何框架官方推荐的唯一实现。配套 03-Agent-Implementation-v2.0.zip 测试结果只覆盖本地模拟路径(12 项 OK);真实 API、生产权限与恢复能力仍待验证。