抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Anthropic 12 月 19 日发布《Building effective agents》,其中一句和我的工程经验很一致:成功实现更常使用简单、可组合的模式,而不是复杂框架。Agent 架构不是功能越多越好,关键是任务到底需要哪种自由度。

我不会拿一个通用 Agent loop 处理所有问题。路径已知就做 chaining,类别明确就 routing,子任务独立就 parallelization,拆分动态才用 orchestrator-workers,需要反复改进就 evaluator-optimizer,真正开放探索才进入 autonomous agent。

用小模式组合 Agent,而不是先上复杂框架

Anthropic 在 11 月 25 日公开 Model Context Protocol(MCP)后,Agent 连接数据和工具终于有了一套开放协议。它解决的核心问题很实际:每个 AI 应用不必为每个数据源重复写私有集成,Server 可以用统一方式暴露 resources、prompts 和 tools。

但 MCP 是连接与能力发现协议,不会替企业完成对象权限、审批、数据分级和副作用治理。我会把 MCP Client/Server 放进现有 Agent Gateway,而不是让发现到的 Server 直接获得执行权。

MCP 连接层与企业治理层

企业系统通常已经有大量 REST/RPC API,把 OpenAPI 文档转成 function schemas,看起来就能让 Agent 使用。问题是内部 API 是为确定性程序和后台页面设计的:参数宽、状态隐含、错误复杂,调用方默认知道对象 ID 和业务前置条件。模型不具备这些默认知识。

我会在现有 API 外增加 Agent Tool Facade。接口围绕用户目标和安全闭环设计,而不是一一映射 Controller 方法。典型动作拆成 Discover/Resolve、Preview、Execute、Observe、Verify/Compensate。

企业工具接口的 Preview-Execute-Observe 闭环

最小 Agent loop 往往是一段 while true:调用模型,看到 tool call 就执行并把结果放回消息,看到 final answer 就结束。Demo 里足够,生产中只要进程重启、用户确认等十分钟、工具超时但实际成功,内存里的循环就无法给出正确恢复。

我会把 loop 做成持久化状态机。每次模型 attempt、工具 operation、用户等待和最终化都有独立状态,迁移先写事件和 artifact,再推进 current state。重启后从最后一个已提交状态恢复,不从对话文本猜执行到哪里。

Agent Loop 的可恢复状态机

Agent 工具多起来后,最初那份 name + description + parameters 列表很快不够用。平台不知道哪个工具有副作用、能否自动重试、需要什么权限、错误如何分类,也不知道 schema 改动会影响哪些 Prompt 和运行中的 Agent。

我把工具注册表做成 Capability Registry。注册项不仅供模型选择,也供路由、策略、执行器、审计和发布系统使用。每个版本不可变,Agent Bundle 固定 registry snapshot,运行中不会看到工具定义漂移。

工具注册表发布的是可验证能力版本

Agent 出问题后,常见做法是把用户问题再问一次。第二次可能用了新模型、新索引和变化后的工具状态,即使答对,也不能证明原问题修复;如果工具有副作用,直接重跑还可能再次发送、创建或修改。

我把 Trace Replay 分成三层:先用原始事件回放协议转换和状态归并,再用固定检索/工具 fixture 回放编排,最后才在隔离环境调用新模型或新索引。每层回答不同问题,且生产副作用默认不重演。

Agent Trace 的三层回放

Agent 评测最容易从“先造 100 道题”开始。题目通常干净、步骤短、工具永远成功,最后测出一个不错的完成率。生产失败却来自另一套分布:权限刚变化、工具 200 但 body 缺字段、流中途断开、两个同名对象、旧 memory 污染了本轮。

我更愿意从真实失败反向建设评测。每个对用户有影响的 Run,先完成证据归因,再抽成最小可复现场景,脱敏审核后加入固定版本的 regression suite。评测集不是一次性题库,而是系统故障经验的可执行资产。

从生产失败生成可回放评测

模型能稳定返回 JSON 后,很多 Agent 链路会直接反序列化并调用后端。JSON Schema 确实能挡住缺字段、类型错和非法枚举,但它无法证明 job_id 指向用户想要的任务,也无法证明开始时间早于结束时间、资源仍处于可操作状态。

我把结构化输出看成候选命令。它要经过解析、schema、归一化、业务语义和执行前绑定五层,最后才成为工具可接受的 command。结构正确只是第二层,不是执行许可。

结构正确之后还要做语义归一与状态校验

企业里讨论 Agent,常从“让模型自己规划并完成任务”开始。实际落地时,很多目标早已有明确步骤:查元数据、生成 SQL、跑验证、等待确认、发布结果。把这些步骤全部交给模型动态决定,会增加成本和不确定性,却没有增加业务价值。

我的默认选择是先做 Workflow。运行时控制阶段与状态,模型只出现在需要语言理解或候选判断的节点。只有任务路径确实无法预先枚举、并且工具与权限边界已经成熟,才开放有限 Agent loop。

先把确定性骨架搭好,再开放 Agent 决策

知识摄取任务变绿,用户仍搜不到文档,通常不是“向量库偶尔没命中”这么简单。任务成功只说明代码走到了结束,没有证明源内容枚举完整、解析结果没截断、每个 chunk 都生成向量、索引切到了新版本,也没证明查询链路使用了这版索引。

我会沿六层做证据对账:枚举、抓取、解析、切块/embedding、发布、查询。每层都有输入输出不变量和 manifest。定位从第一个数量或版本不一致的层开始,不先调 top-k。

知识摄取失败的分层定位

AI 写 SQL 已经不难,难的是决定哪条 SQL 可以进入生产查询链路。只做语法检查,会放过越权与全表扫描;只做权限,会放过指标口径错误;让用户自己审核,又很难在一键分析和 Agent 自动执行中保持一致。

我会设置四道独立闸门:语句、数据、资源、语义。它们分别回答“能不能解析”“能不能看这些数据”“能不能以这个代价运行”“是否真的回答了问题”。四层结论和证据一起返回,不用一个笼统的 safe/unsafe 盖掉差异。

AI SQL 的四道闸门

Prompt Injection 不是在 system prompt 后面多写一句“不要听用户的”就能解决。Agent 会读取网页、文档、邮件和工具输出,这些内容都可能包含类似指令的文本。模型很难只凭自然语言可靠区分“这是数据”还是“这是更高优先级命令”。

我的防线不建立在模型永远识别攻击上,而是建立在权限与执行分层:不可信内容可以影响候选答案,不能自行提升为控制指令;任何工具动作仍需通过确定性的对象、权限、状态和确认检查。

不可信内容不能直接变成工具指令