文章目录
- LLM 自己是不能执行代码的,它本质上只是在"生成文本"。那它怎么调工具呢? 答案是:LLM 输出一段结构化的 JSON,告诉宿主程序"我想调这个工具": { “tool”: “get_weather”, “parameters”: { “city”: “上海” } } 这就是 Function Calling——LLM 用结构化数据表达调用意图,但它自己不执行。
- MCP 是宿主程序(比如 Claude Code)用来管理和连接外部工具服务器的协议。它解决的是"工具从哪来、怎么调"的问题。
- LLM 输出 Function Call → Host 解析 → 通过 MCP(或其他方式)路由到具体工具 → 执行 → 结果返回给 LLM 这里有个关键理解:从 LLM 的角度看,所有工具长得都一样。无论这个工具是内置的还是通过 MCP 配置的,LLM 都是输出同样格式的 Function Call。至于工具到底是内置的还是 MCP 的,那是 Host 层面的事。 好吧,用人话说就是 : Function Calling = LLM 的"嘴"(表达意图) MCP = Host 的"手"(连接和执行工具)
- LLM 怎么知道该调哪个工具?答案是靠工具描述。对比一下: // ❌ 模糊的描述 name: “data_processor” description: “处理数据” // ✅ 精准的描述 name: “csv_to_json_converter” description: “将 CSV 格式的文本转换为 JSON 数组, 每一行成为数组中的一个对象,首行作为字段名” 第一个描述太泛了——"处理数据"?处理什么数据?怎么处理?LLM 看到这种描述基本是蒙圈的。第二个描述就很明确,LLM 知道遇到 CSV 转 JSON 的需求时该调它。 记住:工具描述不是写给人看的注释,而是写给 LLM 看的"使用说明书"。
- 工具调用涉及到安全问题,比如"发邮件"这种不可逆操作。完整的安全设计有三层: 工具描述约束:在工具描述中写明"调用前必须和用户确认内容" LLM Think 评估:LLM 在 Think 步骤判断"这个操作是否需要确认" Host 拦截:宿主程序对高风险操作弹出确认提示 三层防线,缺一不可
- 关键不是简单列个 TODO list,而是要搞清楚任务之间的依赖: 任务 1: 初始化项目 → 无依赖 任务 2: 搭建页面布局 → 依赖任务 1 任务 3: 实现暗黑模式 → 依赖任务 2 任务 4: 写单元测试 → 依赖任务 2、3 为什么依赖关系这么重要?三个原因: Agent 知道执行顺序 保证依赖任务完成后才执行下游任务 在多 Agent 模式下,能知道哪些任务可以并行分配
- 策略 说明 适用场景 Plan-then-Execute 先规划好所有步骤,然后逐步执行 需求明确、步骤可预见 Interleaved(交替式) 规划一步、执行一步、再根据结果规划下一步 不确定性高的任务 实际的 Agent 更偏向交替式。因为就算规划得再好,执行过程中也可能遇到突发情况——比如执行到第 3 步发现 Next.js 版本不支持某个暗黑模式方案,这时候 Agent 需要重新审视整个计划,调整方案再继续执行。 还有一个容易忽略的点:探索先于规划! 比如要重构一个认证模块,Agent 不应该上来就写计划。而是先审视一下项目现有的认证模块——看能不能改、改了影响多大——然后再做规划。
- 不一次性读所有文件,而是先搜索定位,再精确读取。 比如 Claude Code 修一个 bug,它的做法是: 先用 grep 搜索关键词,找到 3 个相关文件 只读取这 3 个文件的内容 修改完成 而不是把整个项目的 50 个文件全部读一遍。
- 对话太长时,把早期的对话内容压缩成摘要,保留关键信息,释放上下文空间。
- 把任务拆给子 Agent 处理,每个子 Agent 有自己独立的上下文窗口。这样就把一个大的上下文需求分散到了多个小窗口里。
- 已经知道的信息不要重复加载。比如 Claude Code 编辑完一个文件后,不会重新读取这个文件——因为编辑的内容已经在上下文里了,再读一次就是加载重复信息。 "避免冗余"和"摘要压缩"不是一回事! 避免冗余:不加载重复信息 摘要压缩:把已有信息压缩变短 前者是"不加",后者是"缩短"。我之前就搞混过
- 做法 问题 只推理不行动(Chain-of-Thought) LLM 一直在"想",但不调工具,容易产生幻觉 只行动不推理(Action-only) 直接调工具,不说明为什么,遇到意外就懵了 ReAct 的创新就是把两者结合——Thought 和 Action 交替进行: Thought: 我需要先确认《三体》的作者,不能凭记忆猜 Action: search(“三体 作者”) Observation: 刘慈欣 Thought: 确认是刘慈欣,接下来搜他的其他作品 Action: search(“刘慈欣 其他作品”) Observation: 《球状闪电》《流浪地球》
- 1. 自我纠错 当搜索失败时,Thought 步骤让 Agent 能反思原因并调整策略: Thought: 我需要先确认作者 Action: search(“三体 作者”) Observation: 没有找到相关结果 Thought: 搜索失败了,可能是关键词不对,换个方式试试 Action: search(“《三体》 科幻小说 作者是谁”) Observation: 刘慈欣 如果是 Action-only 模式,搜索失败后 Agent 可能直接跳到下一步,或者傻乎乎地告诉你"找不到" 2. 可追溯性(Traceability) 每一步推理都显式输出,开发者能看到 Agent "在想什么"。出了问题可以精确定位到哪一步的推理出了错。 其实你在 Claude Code 里已经见过了——Agent 在每次调用工具前输出的那些分析和推理文字(比如"让我先搜索一下相关文件"),就是 ReAct 中 Thought 的体现
- 流程固定、没有不确定性的任务不需要。 比如"每天早上查天气 → 格式化 → 发通知",这种固定流水线甚至不需要 LLM 来编排,一个定时脚本就够了。ReAct 的价值在于应对不确定性,固定流程用它反而是浪费 token
- 优势 说明 并行效率 没有依赖的任务可以同时跑 上下文隔离 每个 Agent 只加载自己需要的信息,不互相污染 专业化 每个 Agent 专注一个领域,配备针对性的工具和提示
- 中心编排(Orchestrator): [主 Agent] / | 后端Agent 前端Agent 测试Agent 主 Agent 负责分配任务、收集结果、协调信息。子 Agent 之间不直接通信。 去中心化(Peer-to-peer): 后端Agent ←→ 前端Agent ↕ ↕ 测试Agent ←→ … Agent 之间直接通信,通过共享状态来同步。
- 中心编排。 Claude Code 有一个主 Agent 做全局把控,spawn 出子 Agent 来并行处理任务。子 Agent 之间不直接通信,所有信息流经主 Agent。 为什么选这种?因为主 Agent 能统一调度——当后端 Agent 改了 API 字段名,主 Agent 可以通知前端 Agent 和测试 Agent 同步修改。如果是去中心化的,这个信息同步就会很混乱。
- 主 Agent 会成为瓶颈——所有信息都要经过它,带来额外的 token 消耗和延迟。所以实际使用中,主 Agent 不会让子 Agent 汇报每一个细节,而是只收集关键结果和变更 🎯
- 来源 说明 可靠性 环境反馈 执行结果直接告诉你错了(测试失败、命令报错、API 404) ⭐⭐⭐ 最高 人类反馈 用户主动指出问题("你改错文件了") ⭐⭐ 自我反思 Agent 在 Thought 中自己发现不对("这个文档版本不匹配") ⭐ 可能反思错 需要注意的是,这里的可靠性指的是信号的确定性——环境反馈是程序化的确定结果, 而人类反馈可能存在表述模糊的情况。但在意图判断层面,人类反馈的权威性是最高的。
- 策略 说明 适用场景 换方式重试 换关键词、换思路,不是重复同样的操作 第一次失败,可能是方法不对 回退重来 撤销修改,从头用完全不同的方案 连续修补越改越乱 升级求助 请求用户介入,或调用更强的模型 自身能力不足 优雅失败 承认失败,报告已尝试的方案 所有策略都用尽 还记得核心循环里的 Think 吗?这里又用上了: Think 决定"做什么",重试上限决定"做多久"。 没有 Think,Agent 会盲目重试同样的操作;没有重试上限,即使有 Think 也可能无限尝试。两者缺一不可! 实际中,一个错误可能需要组合使用多种策略。比如执行 npm install 报磁盘空间不足,Agent 可能需要先清理缓存(换方式重试),但清理磁盘属于有风险的操作,又需要先问用户(升级求助)。
- 风险等级 操作类型 处理方式 无风险 读取文件、搜索 直接执行,不问 中等风险 编辑文件 可配置(严格模式要问,宽松模式自动执行) 高风险 Bash 命令、删除文件、推送代码 默认必须确认 禁止 恶意代码、攻击系统 无论如何都不执行 如果你用过 Claude Code,应该对此很熟悉——读文件不问你,执行 Bash 命令会弹确认。
- 这是整个安全设计中最重要的概念 层级 机制 说明 第 1 层:模型层 LLM 训练时内置的对齐 拒绝明显有害的请求 第 2 层:工具层 工具描述中的约束规则 "发邮件前必须确认" 第 3 层:系统层 权限分级、沙箱隔离 限制可访问的目录范围 第 4 层:人类层 Human-in-the-Loop 关键操作让用户确认 核心原则是:每一层都不能完全信任上一层。 即使模型层没拦住(被 prompt injection 绕过了),工具层可以拦;工具层也没拦住,系统层可以拦;系统层也漏了,还有人类做最后把关。 如果你做过前端,这个思路你一定不陌生——输入校验就是一样的: 用户输入 → 前端表单校验 → API 参数校验 → 数据库约束(NOT NULL、UNIQUE) 每一层都不信任上一层已经校验过了。这就是多层防御的精髓
- 层级 Agent 领域 前端类比 特点 底层 SDK Claude Agent SDK 原生 JS 最大灵活性,什么都能控制 编排框架 LangGraph、CrewAI React、Vue 核心抽象开箱即用,有约定模式 低代码平台 Dify、Coze Webflow 可视化搭建,上手快但灵活性低
- 选底层 SDK: 需要极致控制力,团队技术能力强。比如 Anthropic 的 Claude Code,它的核心循环、上下文管理、权限系统、hook 机制都是从底层直接构建的——这种高度定制的场景,就适合在 SDK 层级或更底层去实现。 选编排框架: 有开发能力的团队,想利用框架的核心抽象(Agent、Tool、Memory)快速搭建,同时保留一定的灵活性和可扩展性。 选低代码平台: 不懂开发的人员也能用可视化方式搭工作流,或者需要快速验证想法。比如一个运营同学想搭个"每天自动总结新闻发到飞书群"的工作流,用 Dify 拖拖拽拽就行了。 一个有趣的趋势: 当前 Agent 领域还在快速演化,底层 SDK 的使用率在上升。因为很多编排框架的抽象层反而成了限制——Agent 的行为很难被预定义的流程图完全覆盖。Anthropic 官方推荐的做法就是用轻量 SDK + 简单代码编排,而不是引入重型框架。 这就像前端早期——很多人觉得必须用框架,后来发现对于很多场景,原生 JS + 轻量库反而更合适
目录
- 前言
- 一、Agent 核心循环:Perceive → Think → Act → Observe
- 二、工具调用机制:Function Calling 与 MCP
- Function Calling:LLM 的"表达方式"
- MCP:宿主侧的"连接协议"
- 它们的关系
- 工具描述的质量决定一切
- 三层安全设计
- 三、规划与任务分解:Agent 怎么把大任务拆小
- 带依赖关系的拆解
- 两种执行策略
- 四、记忆系统:短期、长期、工作记忆
- 三种记忆
- 五、上下文窗口管理:Agent 的"内存管理"
- 策略一:按需加载
- 策略二:摘要压缩
- 策略三:子 Agent 分担
- 策略四:避免冗余
- 六、ReAct 范式:边想边做的艺术
- ReAct 之前的两种做法
- ReAct 的两大核心价值
- 什么时候不需要 ReAct?
- 七、多 Agent 协作:一个人干不完就叫帮手
- 为什么需要多 Agent?
- 两种协作架构
- Claude Code 用的是哪种?
- 中心编排的代价
- 八、错误处理与自我纠正:Agent 犯错了怎么办
- 三类错误信号来源
- 四种应对策略(从轻到重)
- 九、安全与对齐:给 Agent 装上"刹车"
- 风险分级权限模型
- 四层防御(Defense in Depth)
- 十、编排框架与实战选型:用什么工具来造 Agent
- 三个层级
- 选型指南
- 后语
你盼世界,我盼望你无 bug。Hello 大家好!我是霖呆呆。
目前各种 Agent 产品层出不穷。我自己也用了一段时间的 Claude Code,用着用着就产生了一个疑问:
这些 Agent 到底是怎么"思考"的?它凭什么知道该调哪个工具?它怎么记住我之前说的话?
带着这些问题,我系统地学习了 AI Agent 的 10 个核心概念,从最基础的"Agent 核心循环"一直学到"编排框架选型"。
这篇文章就是我整个学习过程的总结,会用大量实际场景来帮你理解这些概念。如果你也在用 Agent 工具但对背后的原理一头雾水,这篇文章应该能帮到你
学 Agent 的第一步,就是搞清楚它到底在干嘛。
大家可能也知道,Agent 发展至今,已经不仅仅停留在"你问它答"了。一个真正的 Agent 在工作时,一直在跑一个四步循环:
Perceive(感知)→ Think(思考)→ Act(行动)→ Observe(观察)
↑ |
└──────────────────────────────────────────┘
来看个例子:
你让 Agent 帮你翻译一份 PDF 文档:
| 步骤 | Agent 做了什么 |
|---|---|
| Perceive | 接收到用户指令:"帮我翻译这个 PDF" |
| Think | 思考:我需要先读取 PDF 内容,然后翻译 |
| Act | 调用 PDF 读取工具,获取文本 |
| Observe | 拿到了 PDF 的文字内容 |
| Think | 思考:内容拿到了,开始翻译 |
| Act | 执行翻译 |
| Observe | 翻译完成 |
| Think | 思考:翻译结果是否符合用户预期?可以返回了 |
| Act | 将翻译结果返回给用户 |
看到没,Agent 不是一条线走到底的,而是在不断循环。每一次 Observe 之后都会回到 Think,重新审视当前状态。
最容易踩的坑:Think 缺失导致死循环
如果一个 Agent 陷入了死循环,第一反应不应该是"加个重试上限",而是要问:它的 Think 步骤是不是出了问题?
来看个反面案例:
Agent 在翻译完 PDF 后,没有经过 Think 步骤来判断"翻译结果是否可以返回给用户了",而是直接又回到 Perceive,把翻译结果当成新的输入,开始翻译"翻译后的内容"… 然后无限循环
翻译 PDF → 拿到结果 → 没有思考"是否完成" → 又去翻译 → 又拿到结果 → ...
这不是"缺少重试上限"的问题——那只是工程层面的补救。根本原因是 Think 步骤缺失,Agent 没有在 Observe 之后停下来思考:"我到底做完了没有?"
这个区分很重要:Think 决定"做什么",重试上限决定"做多久"。两者缺一不可。
搞清楚了核心循环,下一个问题来了:循环中的 Act 步骤,Agent 是怎么"动手"的?
这里涉及两个容易混淆的概念:Function Calling(函数调用) 和 MCP(Model Context Protocol)。
LLM 自己是不能执行代码的,它本质上只是在"生成文本"。那它怎么调工具呢?
答案是:LLM 输出一段结构化的 JSON,告诉宿主程序"我想调这个工具":
{
"tool": "get_weather",
"parameters": {
"city": "上海"
}
}
这就是 Function Calling——LLM 用结构化数据表达调用意图,但它自己不执行。
MCP 是宿主程序(比如 Claude Code)用来管理和连接外部工具服务器的协议。它解决的是"工具从哪来、怎么调"的问题。
LLM 输出 Function Call → Host 解析 → 通过 MCP(或其他方式)路由到具体工具 → 执行 → 结果返回给 LLM
这里有个关键理解:从 LLM 的角度看,所有工具长得都一样。无论这个工具是内置的还是通过 MCP 配置的,LLM 都是输出同样格式的 Function Call。至于工具到底是内置的还是 MCP 的,那是 Host 层面的事。
好吧,用人话说就是 :
- Function Calling = LLM 的"嘴"(表达意图)
- MCP = Host 的"手"(连接和执行工具)
LLM 怎么知道该调哪个工具?答案是靠工具描述。对比一下:
// ❌ 模糊的描述 name: "data_processor" description: "处理数据" // ✅ 精准的描述 name: "csv_to_json_converter" description: "将 CSV 格式的文本转换为 JSON 数组, 每一行成为数组中的一个对象,首行作为字段名"
第一个描述太泛了——"处理数据"?处理什么数据?怎么处理?LLM 看到这种描述基本是蒙圈的。第二个描述就很明确,LLM 知道遇到 CSV 转 JSON 的需求时该调它。
记住:工具描述不是写给人看的注释,而是写给 LLM 看的"使用说明书"。
工具调用涉及到安全问题,比如"发邮件"这种不可逆操作。完整的安全设计有三层:
- 工具描述约束:在工具描述中写明"调用前必须和用户确认内容"
- LLM Think 评估:LLM 在 Think 步骤判断"这个操作是否需要确认"
- Host 拦截:宿主程序对高风险操作弹出确认提示
三层防线,缺一不可
如果你用 Claude Code 帮你做一个博客项目,你会发现它不会上来就开始写代码。它会先做一件事:规划。
列出需求点、确定技术栈、规划页面结构、拆出任务清单——每一项都是具体要执行的步骤。
关键不是简单列个 TODO list,而是要搞清楚任务之间的依赖:
任务 1: 初始化项目 → 无依赖 任务 2: 搭建页面布局 → 依赖任务 1 任务 3: 实现暗黑模式 → 依赖任务 2 任务 4: 写单元测试 → 依赖任务 2、3
为什么依赖关系这么重要?三个原因:
- Agent 知道执行顺序
- 保证依赖任务完成后才执行下游任务
- 在多 Agent 模式下,能知道哪些任务可以并行分配
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Plan-then-Execute | 先规划好所有步骤,然后逐步执行 | 需求明确、步骤可预见 |
| Interleaved(交替式) | 规划一步、执行一步、再根据结果规划下一步 | 不确定性高的任务 |
实际的 Agent 更偏向交替式。因为就算规划得再好,执行过程中也可能遇到突发情况——比如执行到第 3 步发现 Next.js 版本不支持某个暗黑模式方案,这时候 Agent 需要重新审视整个计划,调整方案再继续执行。
还有一个容易忽略的点:探索先于规划!
比如要重构一个认证模块,Agent 不应该上来就写计划。而是先审视一下项目现有的认证模块——看能不能改、改了影响多大——然后再做规划。
Agent 怎么"记住"东西?这里有三种截然不同的记忆类型
| 类型 | 类比 | Agent 中的体现 | 生命周期 |
|---|---|---|---|
| 短期记忆 | 和朋友聊天时的对话内容 | 当前对话的上下文 | 本次对话 |
| 长期记忆 | 手机备忘录 | MEMORY.md、CLAUDE.md | 跨对话保留 |
| 工作记忆 | 做数学题时的草稿纸 | TodoWrite 任务清单、Plan | 任务结束就丢弃 |
这三者最容易搞混的是长期记忆和工作记忆。
来个场景帮你区分:
一个客服 Agent,用户打来电话说"耳机坏了要退货"。Agent 承诺 3 天内处理。
三天后用户又打来问进度。
这时候 Agent 需要知道"之前承诺了 3 天内处理"这个信息——它应该存在哪种记忆里?
答案是长期记忆。因为这个信息需要跨对话保留。工作记忆不行,因为它在上一次对话结束时就被丢弃了。
区分标准很简单:需要跨对话保留的 → 长期记忆。只在当前任务中有用的 → 工作记忆。
LLM 的上下文窗口是有限的(就像你电脑的内存)。一个处理大型项目的 Agent,不可能把所有文件都塞进上下文里。
那怎么办?这里有几个核心策略:
不一次性读所有文件,而是先搜索定位,再精确读取。
比如 Claude Code 修一个 bug,它的做法是:
- 先用
grep搜索关键词,找到 3 个相关文件 - 只读取这 3 个文件的内容
- 修改完成
而不是把整个项目的 50 个文件全部读一遍。
对话太长时,把早期的对话内容压缩成摘要,保留关键信息,释放上下文空间。
把任务拆给子 Agent 处理,每个子 Agent 有自己独立的上下文窗口。这样就把一个大的上下文需求分散到了多个小窗口里。
已经知道的信息不要重复加载。比如 Claude Code 编辑完一个文件后,不会重新读取这个文件——因为编辑的内容已经在上下文里了,再读一次就是加载重复信息。
"避免冗余"和"摘要压缩"不是一回事!
- 避免冗余:不加载重复信息
- 摘要压缩:把已有信息压缩变短
前者是"不加",后者是"缩短"。我之前就搞混过
ReAct = Reason + Act。它和核心循环是什么关系?
核心循环是通用的设计模式,ReAct 是具体的实现方法。
就像"组件化"是通用的前端思想,React 是实现组件化的具体框架。你不会说"组件化是 React 的改良版"对吧
| 做法 | 问题 |
|---|---|
| 只推理不行动(Chain-of-Thought) | LLM 一直在"想",但不调工具,容易产生幻觉 |
| 只行动不推理(Action-only) | 直接调工具,不说明为什么,遇到意外就懵了 |
ReAct 的创新就是把两者结合——Thought 和 Action 交替进行:
Thought: 我需要先确认《三体》的作者,不能凭记忆猜
Action: search("三体 作者")
Observation: 刘慈欣
Thought: 确认是刘慈欣,接下来搜他的其他作品
Action: search("刘慈欣 其他作品")
Observation: 《球状闪电》《流浪地球》
1. 自我纠错
当搜索失败时,Thought 步骤让 Agent 能反思原因并调整策略:
Thought: 我需要先确认作者
Action: search("三体 作者")
Observation: 没有找到相关结果
Thought: 搜索失败了,可能是关键词不对,换个方式试试
Action: search("《三体》 科幻小说 作者是谁")
Observation: 刘慈欣
如果是 Action-only 模式,搜索失败后 Agent 可能直接跳到下一步,或者傻乎乎地告诉你"找不到"
2. 可追溯性(Traceability)
每一步推理都显式输出,开发者能看到 Agent "在想什么"。出了问题可以精确定位到哪一步的推理出了错。
其实你在 Claude Code 里已经见过了——Agent 在每次调用工具前输出的那些分析和推理文字(比如"让我先搜索一下相关文件"),就是 ReAct 中 Thought 的体现
流程固定、没有不确定性的任务不需要。
比如"每天早上查天气 → 格式化 → 发通知",这种固定流水线甚至不需要 LLM 来编排,一个定时脚本就够了。ReAct 的价值在于应对不确定性,固定流程用它反而是浪费 token
到目前为止我们聊的都是单个 Agent 的能力。但当任务变复杂了,一个 Agent 就不太够用了。
| 优势 | 说明 |
|---|---|
| 并行效率 | 没有依赖的任务可以同时跑 |
| 上下文隔离 | 每个 Agent 只加载自己需要的信息,不互相污染 |
| 专业化 | 每个 Agent 专注一个领域,配备针对性的工具和提示 |
中心编排(Orchestrator):
[主 Agent]
/ |
后端Agent 前端Agent 测试Agent
主 Agent 负责分配任务、收集结果、协调信息。子 Agent 之间不直接通信。
去中心化(Peer-to-peer):
后端Agent ←→ 前端Agent
↕ ↕
测试Agent ←→ ...
Agent 之间直接通信,通过共享状态来同步。
中心编排。 Claude Code 有一个主 Agent 做全局把控,spawn 出子 Agent 来并行处理任务。子 Agent 之间不直接通信,所有信息流经主 Agent。
为什么选这种?因为主 Agent 能统一调度——当后端 Agent 改了 API 字段名,主 Agent 可以通知前端 Agent 和测试 Agent 同步修改。如果是去中心化的,这个信息同步就会很混乱。
主 Agent 会成为瓶颈——所有信息都要经过它,带来额外的 token 消耗和延迟。所以实际使用中,主 Agent 不会让子 Agent 汇报每一个细节,而是只收集关键结果和变更 🎯
Agent 不是万能的,它会犯错。关键是怎么发现错误和怎么处理错误。
| 来源 | 说明 | 可靠性 |
|---|---|---|
| 环境反馈 | 执行结果直接告诉你错了(测试失败、命令报错、API 404) | ⭐⭐⭐ 最高 |
| 人类反馈 | 用户主动指出问题("你改错文件了") | ⭐⭐ |
| 自我反思 | Agent 在 Thought 中自己发现不对("这个文档版本不匹配") | ⭐ 可能反思错 |
需要注意的是,这里的可靠性指的是信号的确定性——环境反馈是程序化的确定结果, 而人类反馈可能存在表述模糊的情况。但在意图判断层面,人类反馈的权威性是最高的。
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 换方式重试 | 换关键词、换思路,不是重复同样的操作 | 第一次失败,可能是方法不对 |
| 回退重来 | 撤销修改,从头用完全不同的方案 | 连续修补越改越乱 |
| 升级求助 | 请求用户介入,或调用更强的模型 | 自身能力不足 |
| 优雅失败 | 承认失败,报告已尝试的方案 | 所有策略都用尽 |
还记得核心循环里的 Think 吗?这里又用上了:
Think 决定"做什么",重试上限决定"做多久"。 没有 Think,Agent 会盲目重试同样的操作;没有重试上限,即使有 Think 也可能无限尝试。两者缺一不可!
实际中,一个错误可能需要组合使用多种策略。比如执行 npm install 报磁盘空间不足,Agent 可能需要先清理缓存(换方式重试),但清理磁盘属于有风险的操作,又需要先问用户(升级求助)。
Agent 能力越强,越需要安全约束。这不是可选的,是必须的
| 风险等级 | 操作类型 | 处理方式 |
|---|---|---|
| 无风险 | 读取文件、搜索 | 直接执行,不问 |
| 中等风险 | 编辑文件 | 可配置(严格模式要问,宽松模式自动执行) |
| 高风险 | Bash 命令、删除文件、推送代码 | 默认必须确认 |
| 禁止 | 恶意代码、攻击系统 | 无论如何都不执行 |
如果你用过 Claude Code,应该对此很熟悉——读文件不问你,执行 Bash 命令会弹确认。
这是整个安全设计中最重要的概念
| 层级 | 机制 | 说明 |
|---|---|---|
| 第 1 层:模型层 | LLM 训练时内置的对齐 | 拒绝明显有害的请求 |
| 第 2 层:工具层 | 工具描述中的约束规则 | "发邮件前必须确认" |
| 第 3 层:系统层 | 权限分级、沙箱隔离 | 限制可访问的目录范围 |
| 第 4 层:人类层 | Human-in-the-Loop | 关键操作让用户确认 |
核心原则是:每一层都不能完全信任上一层。
即使模型层没拦住(被 prompt injection 绕过了),工具层可以拦;工具层也没拦住,系统层可以拦;系统层也漏了,还有人类做最后把关。
如果你做过前端,这个思路你一定不陌生——输入校验就是一样的:
用户输入 → 前端表单校验 → API 参数校验 → 数据库约束(NOT NULL、UNIQUE)
每一层都不信任上一层已经校验过了。这就是多层防御的精髓
学完了 9 个核心概念,理论上你完全可以从零写一个 Agent 了。但正如你不会用原生 JS 从头撸一个大型应用一样——有框架帮你封装好了通用的能力,何必自己造轮子
| 层级 | Agent 领域 | 前端类比 | 特点 |
|---|---|---|---|
| 底层 SDK | Claude Agent SDK | 原生 JS | 最大灵活性,什么都能控制 |
| 编排框架 | LangGraph、CrewAI | React、Vue | 核心抽象开箱即用,有约定模式 |
| 低代码平台 | Dify、Coze | Webflow | 可视化搭建,上手快但灵活性低 |
选底层 SDK: 需要极致控制力,团队技术能力强。比如 Anthropic 的 Claude Code,它的核心循环、上下文管理、权限系统、hook 机制都是从底层直接构建的——这种高度定制的场景,就适合在 SDK 层级或更底层去实现。
选编排框架: 有开发能力的团队,想利用框架的核心抽象(Agent、Tool、Memory)快速搭建,同时保留一定的灵活性和可扩展性。
选低代码平台: 不懂开发的人员也能用可视化方式搭工作流,或者需要快速验证想法。比如一个运营同学想搭个"每天自动总结新闻发到飞书群"的工作流,用 Dify 拖拖拽拽就行了。
一个有趣的趋势:
当前 Agent 领域还在快速演化,底层 SDK 的使用率在上升。因为很多编排框架的抽象层反而成了限制——Agent 的行为很难被预定义的流程图完全覆盖。Anthropic 官方推荐的做法就是用轻量 SDK + 简单代码编排,而不是引入重型框架。
这就像前端早期——很多人觉得必须用框架,后来发现对于很多场景,原生 JS + 轻量库反而更合适
知识无价,支持原创!这篇文章就介绍到这里。
整篇文章下来,我们从 Agent 最基础的核心循环一路学到编排框架选型,10 个概念环环相扣:
- 核心循环是 Agent 的"心跳"
- 工具调用让它能"动手"
- 规划让它能"拆解问题"
- 记忆让它能"记住你"
- 上下文管理让它能"高效工作"
- ReAct让它能"边想边做"
- 多 Agent让它能"叫帮手"
- 错误处理让它能"从失败中恢复"
- 安全与对齐给它装上"刹车"
- 编排框架提供"开箱即用的工具箱"
到此这篇关于一文盘点Agent开发入门必懂的10个核心概念的文章就介绍到这了,更多相关Agent核心概念内容请搜索风君子博客以前的文章或继续浏览下面的相关文章,希望大家以后多多支持风君子博客!