先说一个现象:打开任何技术社区,刷三屏,必有一个帖子在聊智能体。人人都在写 Agent,但以我在实际项目里看到的,大部分所谓“智能体”其实只是给大模型套了个 if-else 循环,本质上还是硬编码流程。直到 Anthropic 把《Building Effective Agents》这篇工程笔记发出来,很多人才第一次意识到,智能体工程里的坑从第一天就埋下了。这篇笔记不长,但信息密度很高,里面没有炫技,全是工程取舍。今天我就把里面的架构要点挑出来,结合我自己在多个项目里踩过的坑,把它彻底讲清楚。
这篇文章适合谁?如果你正在做大模型应用开发,准备把业务接到 LLM 上,或者你已经被“智能体”这个词绕晕了,那这篇就是给你扫盲的。我尽量用大白话,配上可复用的代码片段和避坑清单,读完你至少能搞清楚一个问题:到底什么样的系统值得做成智能体,什么样的系统老老实实写成工作流就行。
1. 先把概念理清:工作流和智能体到底差在哪里
1.1 大模型原生能力与工程补丁
先回顾一个底层事实:大模型本身只是一个概率模型,输入一串 token,输出一串 token。聊天、写作、翻译这些场景,模型直接干就行。但一旦你要让模型去查数据库、调接口、操作文件、做决策,模型天然做不到,因为它只能“说”,不能“做”。
所以所有智能体项目本质上都在做一件事:给大模型补上执行能力,然后在外面套一层控制逻辑。这层控制逻辑怎么设计,直接决定了你这个系统到底算工作流还是算智能体。Anthropic 的笔记里给了一个很朴素但极好用的定义:工作流(Workflow)是预定义代码路径的编排,智能体(Agent)是模型自主决定流程和工具使用的系统。关键区别不在有没有工具,而在决策权在谁手里。
如果一段流程你事先就知道该怎么走,比如“先总结用户问题,再查知识库,再生成回复”,这就是工作流。如果一个问题你根本不知道要调几个工具、按什么顺序调,需要模型自己边试边调整,那才是智能体。
1.2 Anthropic 给出的划分标准
Anthropic 原文把系统分成了五类工作流加一类真正的 Agent,这个分类我建议你直接背下来:
- Prompt Chaining(提示链):把一个复杂任务拆成多个步骤,前一步的输出是后一步的输入。
- Routing(路由):先把输入分类,再分发给不同的处理流程。
- Parallelization(并行化):同一个任务拆成多个子任务并行处理,或者多个模型同时给答案然后投票。
- Orchestrator-Workers(编排者-工作者):一个主模型拆分任务,多个子模型或工具分别执行,再由主模型汇总。
- Evaluator-Optimizer(评估器-优化器):一个模型生成,另一个模型评估,迭代优化。
- Autonomous Agent(自主智能体):模型在环境中自主决策,多轮调用工具,处理复杂独立任务。
这套分类最大的价值是给你一颗定心丸:不是所有任务都要上 Agent,大部分场景用前五种工作流就够了,而且更稳、更便宜、更容易排查。
1.3 什么时候不该做自主智能体
我见过最典型的问题,是产品经理一听“Agent 能做决策”,立刻想把所有功能都改成自动决策。后果就是系统变得不可预测,用户骂街,开发天天救火。
Anthropic 在笔记里反复强调一个观点:简单任务用最直接的方式解决,不要为了智能体而智能体。如果用户问一句“我的订单到哪了”,你根本不需要一个能自主决定调用工具顺序的 Agent,只需要一个路由,把订单查询请求转发给订单系统,把售后请求转发给客服系统,这比任何花哨的 Agent 都稳定。
什么时候该上自主智能体?Anthropic 给了一个条件:当任务的步骤不可预测、需要动态调整工具选择时。比如“帮我整理一份行业研究报告,包含主要玩家的策略对比”,这个过程可能要搜网页、读 PDF、对比数据、写摘要,顺序不定,工具不固定,这才适合 Agent。
2. 构建前的底层能力:检索、工具、记忆
2.1 检索增强不是模型能力,而是工程外挂
很多文章把检索增强生成(RAG)当成模型能力来吹,但从架构角度说,RAG 就是你给模型挂了一个外部硬盘。Anthropic 的笔记明确把检索列为增强 LLM 的三种基本能力之一,另外两个是工具和记忆。
工程实现上,RAG 的核心是三个问题:文档怎么切、向量怎么建、结果怎么筛。我在项目里常用的做法是,先按章节或语义段落切分,控制在 500 到 1000 个 token 一段,然后建向量索引。检索的时候不要只取 top1,取 top5 到 top10,让模型自己判断哪些相关内容有用。这里有个容易踩的坑:检索结果长度要把控,别把几万字的资料一股脑塞进上下文,模型会迷失在噪声里,回答质量反而下降。
2.2 工具调用是智能体的“手”
工具调用(Tool Use / Function Calling)是所有 Agent 的物理基础。Anthropic 说得直白:没有工具调用能力,模型就只能聊天,不能干活。所以在 Claude 的 API 里,工具是通过 JSON Schema 定义的,模型在回答中会输出一个结构化的工具调用指令,然后由你的代码去真实执行。
这里我放一个最基础的例子,用 Anthropic 官方 Python SDK 定义一个查询天气的工具:
import anthropic client = anthropic.Anthropic(api_key="your-api-key") def get_weather(location: str, unit: str = "celsius") -> str: # 实际项目中,这里对接真实天气 API return f"{location} 当前温度:25{unit}" tools = [ { "name": "get_weather", "description": "查询指定城市的实时天气。location 必须是城市名,unit 可选 celsius 或 fahrenheit。", "input_schema": { "type": "object", "properties": { "location": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} }, "required": ["location"] } } ] response = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=1024, tools=tools, messages=[{"role": "user", "content": "北京现在多少度?"}] ) # 解析返回结果,判断模型是否要求调用工具 if response.stop_reason == "tool_use": for block in response.content: if block.type == "tool_use": result = get_weather(**block.input) # 把工具结果回传给模型 print(f"工具返回:{result}")这里有三个细节值得注意。第一,description一定要写清楚工具的适用场景和参数规则,模型就是靠这段描述来判断何时调用它的;第二,工具执行的结果要返回给模型继续推理,这是多轮工具调用的基础;第三,工具函数要做好异常处理,出错时把错误信息也返回给模型,让它自己决定下一步怎么处理。
2.3 记忆:上下文管理才是真门槛
记忆这件事,Anthropic 在笔记里讲得并不复杂,但在实际工程里是最难伺候的一块。模型本身有上下文窗口限制,你不能把所有历史对话都塞进去,成本高、响应慢、效果还会下降。
我的做法是把记忆拆成两层。短期记忆放在对话上下文中,只保留最近几轮,超过之后做摘要压缩;长期记忆存在外部存储里,比如向量数据库,需要时通过检索拉回。这其实就是给模型做了一个“人”一样的记忆结构:工作记忆有限,长期记忆靠检索触发。
有一个很反直觉的经验:不是所有历史都值得记住。有些团队拼命做记忆模块,把所有对话都存下来,结果模型被一些无关信息带偏。正确的做法是给记忆打上结构化标签,比如用户意图、业务状态、关键偏好,只有这些内容值得沉淀。
3. 五种工作流模式的逐个拆解
3.1 Prompt Chaining:把复杂任务拆成流水线
Prompt Chaining 的逻辑最好理解:一个任务太复杂,一个 prompt 做不了,就拆成多个步骤,每步一个 prompt,串行执行。Anthropic 用了一个很好的比喻:每一步都像一个工序,前一步的输出是后一步的原料。
我实际用过的一个场景是内容生成流水线:第一步写大纲,第二步根据大纲展开内容,第三步润色。每一步都是独立的 LLM 调用,输出单独校验,发现问题可以直接定位到具体环节。
伪代码大概是这样的:
def generate_article(topic): outline = llm_call("规划文章大纲", topic) draft = llm_call("根据大纲写初稿", outline) polished = llm_call("润色初稿", draft) return polished这种模式胜在可预测、易调试。缺点是每一步都在增加延迟和 token 成本,而且如果第一步的输出质量差,后面所有步骤都会跟着崩。所以使用 Promp Chaining 时,我强烈建议在关键节点加入校验逻辑,比如第一步输出大纲后,先检查是否包含目标章节,不合格就直接重试,不要进入下一步。
3.2 Routing:给问题分诊台
Routing 是解决“一类请求多种处理路径”问题的标准方案。Anthropic 是把 Routing 单独列出来的,但我理解它更像一个分诊台:先让模型判断输入属于哪一类,然后把它分发到对应的处理流程里。
一个我经常举的例子是客服系统。用户消息进来,先让模型判断意图:是投诉、退款、物流查询还是商品咨询?然后不同意图走不同的处理链。这比让一个 prompt 处理所有类型要稳定得多,因为每一类问题的处理逻辑、工具、话术都不一样。
关键实现细节在于分类方式。Anthropic 在笔记里特意提了一个小技巧:给模型 N 个固定分类选项,并且一定加一个“其他”选项,这比让模型自由发挥打标签要可靠得多。我测试过,固定分类的准确率明显更高,因为模型本质上是做选择题,而不是做填空题。
3.3 Parallelization:同时开工,互不干扰
Parallelization 适用于子任务之间没有严格依赖的场景。Anthropic 把它分成两类:一是把一个任务切成独立子任务分别执行,最后汇总;二是多个模型做同一件事,最后投票选出最优答案。
切分子任务这种并行方式,我常用于代码审查场景。比如我给代码同时跑三个检查:一个看安全漏洞,一个看性能问题,一个看代码风格,三个检查互相独立,可以并行调用,最后把结果合并成一份审查报告。这样比单线程串行检查快得多,而且每个检查的 prompt 都很专一,质量也明显更高。
投票式并行更奢侈,适合对准确性要求极高的场景。比如翻译任务,同时让三个不同参数的模型翻译同一段话,再让第四个模型选出最好的一版。效果确实更好,但 token 成本大概翻三倍,你自己算算值不值。
3.4 Orchestrator-Workers:主模型当项目经理
Orchestrator-Workers 的结构是一个主模型负责拆任务、派活、汇总,子模型或工具负责干活。这是很多人心中“智能体”的雏形,很多 Agent 框架的核心就是这个模式。
Anthropic 给出的适用场景是:任务可以切分成多个子任务,且子任务的边界不可预知,需要动态规划。比如“帮我分析这份财报”,主模型先判断需要做哪些步骤:提取关键指标、对比上期数据、查询行业新闻、生成分析结论,然后派给不同的 Worker,最后汇总。
这里最需要注意的一个问题:拆分任务的质量决定了整个系统的上限。如果主模型拆出来的子任务本身含糊不清,Worker 再强也做不出好结果。我习惯于在 prompt 里明确要求主模型按“任务目标-子任务清单-每个子任务的明确交付物”格式输出,同时限定子任务数量,不要拆得太碎。
3.5 Evaluator-Optimizer:生成与反馈的循环
Evaluator-Optimizer 是一个很有意思的模式:一个模型负责生成内容,另一个模型负责挑毛病,迭代几轮直到满意。Anthropic 把它形容成一个人写稿、另一个人审稿的过程。
我常用它来做文案优化。生成初稿之后,让评估模型按几个维度打分:语气是否友好、信息是否完整、专业度是否足够,然后给出修改意见,再让生成模型根据意见修改。每次循环多花一份 prompt 的钱,但输出质量确实肉眼可见地提升。
不过这个模式很容易陷入无限循环。我的做法是设置最大迭代次数,比如最多三轮,同时把评估标准写具体,不要让评估模型输出“整体还行”这种空话,逼它给出可执行的修改建议。评估模型输出质量不行,整个循环就是浪费钱。
下表把这五种工作流模式做个对比,方便你快速选型:
| 模式 | 核心逻辑 | 适用场景 | 主要风险 |
|---|---|---|---|
| Prompt Chaining | 串行分步 | 内容流水线、数据处理 | 前序错误会传播 |
| Routing | 先分类再分发 | 客服分流、意图识别 | 分类错误会被放大 |
| Parallelization | 并行子任务或投票 | 代码审查、多方案对比 | token 成本高 |
| Orchestrator-Workers | 主模型调度子任务 | 复杂分析、研究任务 | 任务拆分质量难保证 |
| Evaluator-Optimizer | 生成-评估-迭代 | 文案润色、翻译优化 | 可能陷入无限循环 |
4. 自主智能体的设计与边界
4.1 什么任务真的需要自主智能体
Anthropic 在笔记里很谨慎:自主智能体不是默认选项,而是最后手段。什么任务才够格?关键判断标准是任务路径本身不可预测,且需要模型根据环境反馈动态调整。
我举一个实际项目:写自动化研究报告。这个任务的步骤确实没法提前固定。今天用户要研究“新能源汽车市场”,明天要研究“半导体供应链”,需要搜什么、需要读哪些报告、需要对比哪些数据,全都未知。这种场景我确实用了 Agent 架构,让模型自己规划检索路径,根据已获得的信息决定下一步做什么。
但如果你问他“帮我查一下明天天气”,这种任务永远不该用 Agent。一眼就能看到终点,直接调工具取数返回就好。
4.2 工具集设计与环境搭建
自主 Agent 的能力边界完全由工具集决定。工具多不代表好,工具杂反而让模型选择困难。Anthropic 的建议非常实际:每个工具都要有清晰、完整的描述,并确保工具实现足够简单可靠。工具本身的 bug 会直接表现为 Agent 行为的不可预测,这是最难排查的。
环境搭建也要注意。如果 Agent 需要执行代码,一定要跑在沙箱里,限制网络和文件系统访问。如果 Agent 需要访问外部系统,尽量用只读权限起步,确认行为稳定后再逐步放开。这个原则我吃了很大教训:早期一个 Agent 因为环境未加沙箱,执行了一段意外代码,把测试库的数据改乱了。
4.3 护栏设计:给 Agent 戴上笼头
自主智能体最让人不安的是它的“自主性”,所以护栏不是可选,而是必须。Anthropic 在笔记里强调的护栏,和我在工程里的做法基本一致,归纳起来就几条:
- 最大步数限制:给 Agent 设一个工具调用次数的上限,比如 15 次,超过就停止并向用户解释。
- 关键动作人工确认:涉及资金操作、删除操作、对外发布等高危动作,必须停下来等人工批准。
- Token 预算限制:每个 Agent 会话设置 token 上限,防止单个任务耗尽配额。
- 输出结构约束:要求 Agent 在关键节点输出结构化中间结果,而不是自由文本,便于程序校验。
有一个经验也很重要:Agent 的任务目标要写得足够具体。给它一个模糊指令,它会给你一个模糊的结果,而且还会自作主张做一堆你没要求的操作。任务描述越清晰,Agent 才越像专业员工,而不是一个兴奋的实习生。
5. 工程化落地:框架怎么选,API 怎么用
5.1 框架与原生 API 之争
Anthropic 在笔记里对框架的态度非常务实:框架能帮你快速起步,但隐藏了底层细节,遇到问题排查困难;而直接调用模型 API 写代码,起初慢但完全可控。所以它的建议是,先从直接调用 API 开始,理解每一步发生了什么,再决定要不要用框架。
我自己同意这个方向。现在市面上的 Agent 框架很多,有些确实方便,但你得付出“黑盒”的代价。框架帮你封装了循环调度、记忆管理、工具分发,出了问题你根本不知道卡在哪一环,最后还得去翻框架源码。如果你追求的是业务的稳定性,建议核心逻辑自己写,把框架只当成一个辅助工具。
不过我也要补充一点:如果你只是做原型验证,用现成的开源框架或者商业化平台(比如 Coze、Dify)确实快得多。平台帮你解决了模型接入、工具配置、可视化编排,适合快速试错。但一旦要上线生产、做深度定制,还是要回到代码层面。
5.2 工具描述写法:细节决定成败
工具调用的可靠性,很大程度上取决于工具描述写得怎么样。Anthropic 在笔记里明确提醒:工具描述要完整、清晰,让模型知道该在什么时候使用它。这段描述是模型做决策的重要依据,绝不是随便写写的注释。
我建议描述里至少要包含这几部分:工具做什么、什么场景下用、参数是什么格式、有没有限制条件、错误返回长什么样。举个例子:
{ "name": "search_documents", "description": "在内部知识库中搜索与用户问题相关的文档。适用于查询公司制度、产品手册、技术规范。搜索关键词越具体,结果越准确。返回最多5条结果,每条包含标题和摘要。", "input_schema": { "type": "object", "properties": { "query": {"type": "string", "description": "搜索关键词,尽量使用原文中的专业术语"} }, "required": ["query"] } }注意最后我给 query 参数也加了描述。参数描述不要偷懒,它直接决定模型能不能正确填参数。我还见过一个更高级的玩法:在描述里写“当用户问到 X 时使用”,等于给模型做了一次 few-shot 提示。实测这方法在工具数量超过 10 个时特别管用。
5.3 结构化输出与中间校验
很多人忽略一个问题:模型输出自由文本,你怎么判断它做得好不好?Anthropic 的建议是让模型在关键节点输出结构化数据,比如 JSON,然后用代码去校验。这比让模型自己说“我完成了”可靠得多。
我在每一个工作流模式的组件里都加了中间校验。比如生成文章大纲后,要求模型必须输出 JSON:包含“title”“sections”两个字段,然后我用代码校验 sections 是否为空、是否满足模板。不满足就让模型重写。这一招能拦下大部分低级错误,从源头减少故障。
实现结构化输出有几种方式,最简单的是在 prompt 里指定输出格式,高级一点可以用 Claude 的强制 JSON 输出。但注意,格式越复杂,模型越容易出错,所以中间结构尽量精简,只在业务关键节点使用。
5.4 测试与追踪:没有观测就没有优化
智能体系统的测试和传统软件测试很不一样。传统程序是确定性的,输入相同输出一定相同;智能体系统是概率性的,同一个输入跑三次可能三个结果。所以测试策略要换思路。
核心方法是建立回归评测集:准备 20 到 50 个代表业务场景的测试用例,固定测试参数,每次代码改动都跑一遍,人工打分会话质量。Anthropic 在笔记里也提到了类似做法:把人类的反馈和评估结果加入到提示词和测试样例里,持续迭代。
另外一定要做好日志追踪。每次 LLM 调用、每个工具调用、每一步决策,都要记录上下文摘要、模型响应、耗时、token 数。没有这些数据,出了问题你连定位都做不到。我见过很多团队连日志都不打,Agent 出错了只能靠猜,这种项目基本走向是推倒重来。
6. 常见问题与排查实录
6.1 智能体陷入死循环
这是我遇到最多的一个问题:Agent 反复调用同一个工具,每次得到结果都继续调,始终无法收敛。核心原因是任务目标定义模糊,或者工具结果不符合模型的预期。
我的排查步骤很固定。先看日志确认循环调用的是哪个工具;然后检查这个工具的返回格式是否与描述一致;最后检查任务 prompt 是否明确告诉模型“什么情况下算完成”。多数时候不是模型笨,是你没告诉它终点在哪。
如果真出现死循环,直接靠护栏兜底:设置最大迭代次数,到次数强制退出并返回已做的部分结果。这一步必须在架构初期就设计进去,别等出问题再补。
6.2 工具调用返回格式解析失败
模型输出的工具调用参数偶尔会出现格式不完整或者类型不对,尤其是参数很多的情况下。我的缓解方案是:解析工具调用参数时用容错解析,失败后把错误信息返回给模型,要求它重新生成合法的工具调用参数。
这里有个细节:不要对模型的 JSON 输出做太苛刻的校验。它偶尔会在 JSON 里夹带一些多余字段或注释,如果直接报错,整个链路就断了。宽容一点,用解析库尽量提取可用字段,解析失败才重试。Anthropic 的 SDK 本身也做了容错处理,但业务代码里再兜一层更稳。
6.3 模型不调用该用的工具
有段时间我做测试,发现模型经常答非所问,明明需要查数据,它却凭记忆回复。排查后定位到原因:工具描述写得不够明确,模型根本不知道有这回事。
解决办法有两条路。首选是加强描述,在工具描述里增加“当用户问到时,必须调用此工具,禁止根据已有知识回答”这种强约束。如果加了强约束还是无效,就使用 few-shot 示例,在 prompt 中给一个对话样例,明确展示调用工具的时机。这两招能解决绝大多数工具选择问题。
6.4 上下文爆炸导致效果崩塌
Agent 每多一轮工具调用,工具返回结果就多占一段上下文。几十轮下来,早期信息被淹没,模型忘掉了最初的用户意图,回答质量严重下降。在 Anthropic 笔记里虽然没有展开,但这是 Agent 架构最普遍的工程问题之一。
我的处理方式是分层摘要:每几轮对话后,把前面的内容压缩成一个摘要,只保留关键事实、中间决策、未完成目标。工具调用结果也要摘要化,只保存提取后的结构化数据,不要把原始大文件留在上下文中。预算敏感的项目,可以把长期信息外置到向量库里,不再直接暴露给上下文。
6.5 稳定性不足时的降级策略
确定一个原则:没有一个 Agent 是永远稳定的,必须设计降级路径。我的做法是,给每个 Agent 任务都预设一个传统工作流兜底版本。比如 Agent 自动分析投资数据失败时,可以降级为让用户手动选择图表模板,由提示链生成报告。这样即使 Agent 表现不佳,业务也不至于完全不可用。
我对智能体开发的整体体会
Anthropic 这份架构笔记最让我服气的地方,是它把“克制”讲成了方法论。现在的行业氛围总喜欢把一个单词往天上吹,好像不用 Agent 就显得不够先进。但真实世界里,90% 的业务任务其实用一个结构良好的工作流就能解决,剩下 10% 才需要上自主 Agent。
从我个人的实际工程经验看,更靠谱的路线是反着来的:先用最简单的 Prompt Chaining 和 Routing 把主流程跑起来,观测模型在哪些环节出错,再逐步引入更复杂的编排模式。如果你一上来就搭一个全自主 Agent,最后大概率会花大量时间对付不可控性,而不是解决业务问题。
最后再分享一个小技巧:每天盯一遍日志里 Agent 的每一次决策路径,比看任何架构文档都有用。你会在里面看到模型是怎么被工具描述误导的,怎么被上下文带偏的,这些真实个案才是你后续优化 prompt 和工具设计的最佳素材。智能体开发不是一锤子买卖,它是一场持续调优的工程实践,谁把观测和迭代做扎实了,谁就能真正把“花架子”变成生产力。