Agent
Agent 是什么?
我认为 Agent 就是自主工具循环。
脱离具体范式讨论 Agent 是什么意义不大。最基本的 Agent 范式是 ReAct,本质上就是一个 while True 循环:
停止条件由具体定义和框架决定。
Agent 的最小基础定义为自主工具循环;记忆和规划很重要,但不是 Agent 成立的必要条件。
- 规划:事实上即使没有显式的规划,agent 或者说 LLM 也能通过整个上下文大致知道下一步要做什么(比如调用什么工具)
- 记忆:对于最基本的 agent,上下文就是记忆,或者你叫它是短期记忆也行;但是长期记忆真的不是基本架构之一。
Tool、workflow
Tool 是被 Agent 使用的,Agent 是 Workflow 中的一个基本的执行单元,而 Workflow 是组织多个执行单元的方式。
我不想把 Tool、LLM、Agent 分得太玄乎。Tool 本质上就是一段业务代码,只是为了让 LLM 能调用,额外包了一层 schema 和描述。LLM 也可以被看作一个最小执行单元,甚至可以理解成一个退化版 Agent:只做一次模型调用,不进入工具循环。
既然 Workflow 是“怎么组织”,那它当然可以有不同形态。
一种是确定性 Agentic Workflow:用 Python 代码、DAG、条件分支来决定下一步。即使节点里包含 Agent,控制流仍然由代码掌握,所以相对稳定、可复现、可调试。
另一种是动态 Agentic Workflow:引入高层次的 Agent 组织者,由它判断下一步应该调用哪个低层 Agent、Tool 或流程。只有当下一步判断无法用明确代码规则解决时,才有必要引入这种上层 Agent。
Agent 设计范式
我确实知道有基本的 ReAct,以及 Plan-and-Execute,还有 Reflection。
- ReAct 就是 LLM 调用工具,得到结果,LLM 分析并进行下一轮工具调用。
- Plan-and-Execute 是先规划后执行。
- Reflection:事后检讨。
我基本没见过成熟产品把 Reflection 当成核心 Agent 范式来用。工程上更常见的基础骨架还是 ReAct。
ReAct
ReAct 是设计范式,不是模型内置运行时;既然是范式,就当然需要代码或框架实现循环。
LangChain 这类框架的作用,本来就是封装 ReAct loop:调用 LLM、解析 action、执行 tool、写回 observation、判断停止条件。
重点不是“模型会不会自己循环”,而是 LLM 每轮只负责决策,循环由宿主程序驱动。
Plan-and-Execute
简单来说就是先规划后分步执行。但是这实在是太浅薄了。
动态 Replan:比如执行过程中是否需要调整计划?多久检查一次?
以及既然有了规划,有了任务拆分,那么任务之间是否有先后关系?有哪些是可以并行的?
你能很明显的感觉到这种模式是依附于 orchestration - worker 模式的,比如调度一个 planner 之类的。
Reflection
也许可以理解为独立的检查 agent。说独立是因为一般一个 agent 对自己的输出是有自信的。
重点是要限制轮次。
压缩机制
压缩/裁剪的目的都是因为 context window 长度有限。这个问题在实际项目中非常常见,解决方案有好几种思路,从简单到复杂都有。
最简单的是「滑动窗口」,只保留最近 N 轮对话,更早的历史直接丢弃。好处是实现简单,代价是早期的重要信息可能被丢掉。比如用户在第一轮就说了「所有代码用 TypeScript」,到了第十轮这条信息被滑出窗口了,Agent 又开始写 JavaScript,用户就会很崩溃。
进阶一点的做法是「摘要压缩」。当历史长度接近上限时,用 LLM 把早期的对话历史压缩成一段摘要,替换掉原始的冗长历史。比如把前面十轮的详细对话压缩成「用户要求用 TypeScript 编写一个 REST API,已完成数据库设计和路由定义,当前正在实现用户认证模块」,一段话就把关键信息保留了,token 占用从几千降到几百。代价是压缩过程本身会丢失细节,而且需要额外的 LLM 调用来做摘要。
还有一种做法是把长结果从 context 里卸载到外部存储。比如工具调用返回了一大段日志、网页正文、代码搜索结果或中间分析产物,当前上下文里不一定需要完整保留,就可以把原文写入数据库、文件或对象存储,只在 context 中留下一个简短摘要和引用 ID。
后续如果 Agent 需要查看细节,再通过专门的读取工具按引用 ID 取回原文。这样 context window 里保留的是“索引 + 摘要”,而不是完整材料,既能减少 token 占用,又不会真正丢失信息。
这更像是给 Agent 配一个外部工作区:桌面上只放便签和索引,完整资料放在抽屉里,需要时再按编号取出来。
multi-agent
说到 multi-agent,一般是认为某一个复杂任务无法由一个 agent 完成。
一般不只是上下文长度的问题,而是涉及到分工、人格的问题:让一个 Agent 既搜信息、又写代码、又做测试、又写文档,它在每一件事上都得兼顾,精力是分散的,就像一个人同时担任产品经理、程序员、测试工程师和文档工程师,每个角色都做得不够专注,互相干扰。
就目前来说,multi-agent 有很多方式,比如:
- 有最固定的流水线,流水线上的每一步都是一个 agent,但是就工作流来说没有非确定性的部分
- 假设 1 不足够,有些流程上的判断无法仅有一些确定性逻辑完成,那么就可以引入一些 LLM 判断节点
- 再进一步的,如果任务无法预先知道细节,那么就可以引入 orchestration - worker 模式,也即最上层的工作流编排也由 agent 掌握。不过这仍然是中心化方能。
- 传说中的去中心化方案,也就是多个 Agent 通过共享的消息队列或状态空间自行协商、直接通信。这很难,更多停留在学术研究里探索生产环境里,几乎所有正经项目都选 Orchestrator 模式。
就 anthropic 的 blog 来说:很多时候你总要先尝试 single-agent,然后观察是否能把任务完成得比较好,如果不行才需要使用更复杂的架构。
「手搓」Agent,而不是直接用成熟框架?
我只能说目前我使用的是 langchain。
要分 2 层回答问题:
框架适合的时机:POC 阶段快速验证 idea,目标是跑通而不是优化;团队刚接触 Agent 开发,用框架能少踩一些基础性的坑;周边工具(文档解析、向量检索)依赖框架的生态,核心逻辑本身复杂度不高。这些场景里,框架带来的速度优势是真实的,值得用。
手搓的时机:准备上生产,稳定性成为核心关切;流量开始上来,性能和成本变得敏感;业务逻辑高度定制,和框架的通用设计偏差很大,改起来反而麻烦;团队需要高可观测性,链路要能随时监控和回溯。
可是就我的经验来看,我只能说我是边用然后边自己打补丁,比如有框架暂时没有解决的问题我会自己补上。
然后就是所谓的抽象过多——其实我认为在现在有 ai 可以追查库代码的情况下很难说是非常大的问题。
我对手搓轮子还是有一定警惕,因为成本太高,所以要和你的需求结合。