Agent Framework 工程:从最小循环到可评测的生产系统

1. 先从最小系统开始

学习 Framework 最有效的方式不是先读一堆抽象,而是先实现一个能工作的最小闭环:Model Adapter、Tool Executor、Session State、Verifier 和事件输出。

handle(request):
    session = store.load_or_create(request)
    for turn in budget:
        context = context_builder.build(session)
        decision = model.call(context)
        emit(model_event(decision))
        observations = execute_tools(decision.tool_calls)
        emit(tool_events(observations))
        session = reducer.apply(session, decision, observations)
        verdict = verifier.check(session)
        if verdict.stop:
            emit(stop_event(verdict.reason))
            store.save(session)
            return verdict

这个版本故意不追求聪明,只暴露基本事实:模型会输出无效 Tool Call,工具会失败,状态会被并发修改,用户会中断,服务会断线。

2. 数据模型比 API 更重要

建议明确区分:

  • Request:用户本次输入和控制操作。
  • Session:跨 Turn 的任务状态、权限、预算和检查点。
  • Turn:一次 Model Call 与 Tool Call 集合。
  • Event:不可变事实,如模型输出、工具开始/结束、验证和中断。
  • State:由事件 Reducer 得到的当前投影。
  • Rollout:一次完整运行尝试。
  • Trajectory:用于分析和评测的有序轨迹。

事件是事实,状态是投影;状态损坏时可以通过事件重放恢复。Rollout 记录一次尝试,Trajectory 则应包含足够上下文,让别人能重现或归因失败。

3. SSE、Stream 与背压

SSE 解决浏览器接收服务端事件的问题,Stream 解决增量传输的问题,但两者都不负责业务一致性。服务端事件要带 event_idsession_idturn_id、序列号和版本;客户端断线后按最后事件重连,服务端补发或返回快照。

如果消费者处理速度低于生产速度,就会产生背压。系统要限制事件缓冲、合并可丢弃的增量文本、保留状态变化和 Tool 终态,并允许客户端从快照继续,而不是无限堆积。

4. Middleware 与 Hook

Middleware 参与控制流程,可以修改、拒绝、暂停或恢复;Hook 主要观察生命周期并触发记录、指标、通知等动作。典型 Middleware 包括 Context、Auth、Budget、Risk、Retry、Compression 和 HumanDecision。

顺序必须显式。例如权限检查不能在 Tool 执行之后,压缩不能覆盖刚刚产生的关键证据,PostTurn 验证不能被一个只记录日志的 Hook 阻断。每个中间件要有输入输出合同、异常策略和测试。

5. Rollout 与 Trajectory 数据采集

生产系统要采集的不只是最终答案:任务合同版本、模型版本、Prompt/Skill 版本、Context manifest、Tool 参数摘要、权限决定、Sandbox 版本、事件序列、压缩前后摘要、验证证据、StopReason、延迟和成本都要可关联。

敏感数据要脱敏和分级保留,但不能把审计做成无法定位的空壳。轨迹应支持按失败类型切片:规划错误、上下文错误、Tool 错误、环境错误、验证缺失、恢复错误和用户目标变化。

6. 可靠状态机

推荐把任务状态显式化:created → running → waiting_human → paused → resuming → completed/failed/cancelled。每次状态变化都有事件和版本,非法迁移直接拒绝。

恢复时读取检查点,校验工作区和外部副作用,重建 Context,再继续未完成动作。Exactly-once 在外部系统中通常难以保证,工程上更常用 at-least-once + 幂等键 + 状态查询 + 补偿。

7. 验证闭环与发布门禁

Framework 不应让模型自己决定成功。Verifier 可以分层:结构验证、工具结果验证、代码测试、产物检查、任务合同检查和人工批准。每层都输出证据,最终由策略聚合。

发布前至少跑:单元测试、Tool 契约测试、状态迁移测试、SSE 重连测试、压缩回归、权限测试、Sandbox 恢复测试、长程故障演练和离线 Eval。新模型上线要区分模型变化和 Harness 变化,保留可回滚版本。

8. 从原型到生产

原型阶段只需跑通 Loop;第二阶段加入结构化事件和状态;第三阶段加入权限、Sandbox、Verifier 和检查点;第四阶段加入多租户、预算、灰度、轨迹和评测;最后才考虑复杂 MultiAgent、自进化 Memory 和大规模调度。

每次扩展都问三个问题:增加了什么能力,增加了什么失败面,如何评估和回滚。没有这三个答案,就不应把“更复杂”当成“更先进”。

9. 学习者毕业项目

实现一个最小 Coding Agent Framework:支持一个代码仓库、三个 Tool、SSE、Session/Turn、用户中断、Tool 超时、L1 压缩、Verifier、检查点恢复和 Rollout 导出。然后写 20 个 Single Turn 与 Multi Turn Case,做一次模型替换和一次故障演练。