用过 [LangChain]的人很多,能讲清agent.run()内部在做什么的人很少。
我也是前者。所以这次把框架放一边,从零手写了一个 Multi-Agent 客服系统——能查订单、答 FAQ、处理投诉,多个 Agent 协作。
不是为了取代框架,是想搞懂。
写完不到 600 行、6 个核心文件,最大的收获不是代码,是终于能回答那个问题:Agent 到底在干什么?
代码在这里:https://github.com/helloworldtang/my-multi-agent-system。下面是我拆出来的东西。
一、"Multi-Agent"这个词,是障眼法
先祛魅。
抛开术语,一个 Multi-Agent 系统就四件事:
- 调 LLM(带超时、重试、日志)
- 工具调用(让 LLM 能调你的函数)
- ReAct 循环(LLM 边想边调工具,直到给出答案)
- 多 Agent 编排(谁干啥、并行还是串行)
每一件单独看都不复杂。框架的价值在于把它们打包、藏起来、给你一个agent.run()。
但"藏起来"恰恰是问题:出了 bug 不知道在哪一层;想换个模型、改个工具,得先学框架的抽象;面试被问"讲讲你们的 Agent 架构",只能背 API。
所以我决定一件件自己写。
下面按这个顺序拆。
二、function calling:不是 AI 的新能力,是一份协议
很多人觉得 function calling 是"AI 学会了调函数"。
不是。它是一份协议约定:你告诉模型"有这些工具、参数长这样"(JSON schema),模型回复"我要调这个、参数是这些"(JSON),你负责真的执行。
模型从来没碰过你的函数,是你的代码在派发。
理解这一点,工具注册就好写了——本质是把 Python 函数签名翻译成 JSON schema。我用一个装饰器自动完成:
@tool
def query_order(order_id: str) -> str:
“”"查询订单状态与物流。
Args: order\_id: 订单号,如 ORD20240001。 """ ...装饰器用inspect反射签名 + pydantic 校验参数,自动生成 OpenAI 的 schema。模型返回{"order_id": "ORD20240001"},pydantic 校验,不合法就回灌让它重试。
整个 function calling 机制,几十行就讲透了。它不是魔法,是"JSON schema + 派发"。
三、ReAct:所谓"自主决策",就是一个 while 循环
ReAct(Reason + Act)被讲得很玄。其实流程朴素得有点扫兴:
模型看问题 → 要调工具?
- 要:执行工具,把结果喂回去,再问一次
- 不要:输出最终答案
写成代码,核心就是一个循环加一个停止条件:
for step in range(max_steps):
resp = llm.chat(conv.to_dicts(), tools=tool_schemas)
if not resp.tool_calls:
return resp.content # 模型不再要工具 → 最终答案
for tc in resp.tool_calls:
result = execute_tool(tc)
conv.tool(result, tool_call_id=tc.id, name=tc.name) # 结果回灌
但这里有个反直觉的点:ReAct 的难点不在循环,在防御。
模型会卡死(连续调同一个工具)、会幻觉参数、会无视你的确认要求。真正花心思的是这些:
max_steps硬上限,防死循环
连续 3 次相同调用 → 判卡死,强制停止
工具执行报错不崩,把错误回灌,让模型换法子
写操作(取消订单、退款)打
requires_confirmation标记,先问用户
这些才是工程。框架替你做了,所以你以为 ReAct 很简单。
而且——这些不是 ad-hoc 补丁。先记住它们,第六节会收回这条线:它们其实是一种更普适思路的具体实现,叫给不可靠的 LLM 套一层审视。
四、多 Agent:最容易过度设计的地方
"Multi-Agent"最容易让人想多。我一开始想上 Actor 模型——每个 Agent 一个消息邮箱,搞订阅、序列化、生命周期。
写了两小时,停下来想了想拓扑,发现自己犯傻。
我的系统是静态 DAG:用户问题 → 路由识别意图 → 挑对应 Agent → 合并回复。这张图是固定的,不需要 Actor 那套动态订阅。函数式 fan-out 两个函数就够:
def fanout(agents, msg):
with ThreadPoolExecutor() as ex:
return [f.result() for f in [ex.submit(a.run, msg) for a in agents]]
def merge(results, llm):
if len(results) == 1:
return results[0].content # 单 Agent:零 LLM
return llm.chat(…).content # 多 Agent:一次摘要去重
Actor 要 3 倍代码,收益为零。这不是偷懒,是拓扑分析后的工程判断——我把这个否决理由写进了设计文档,因为"为什么不用 X"往往比"用了 X"更有信息量。
真正用上多 Agent 的地方是路由支持多意图。用户说"查下 ORD001,顺便问退货政策"——既是订单又是 FAQ。老项目if/elif只能选一个,必然漏处理。这里返回多意图,fan-out 并行两个 Agent,再 merge。
这才是 Multi-Agent 协作的真实形态:不是一堆 Agent 互发消息,是一次请求里的并行分工。
五、实测:function calling 比 prompt 强,强多少?
光讲道理不算数。我跑了 40 个 prompt × 3 种"让模型调工具"的方式,120 次真实调用:
| 方式 | 总成功率 | FAQ 场景 |
|---|---|---|
原生tools参数 | 95% | 87% |
response_format=json_object | 95% | 87% |
| 纯 prompt 引导(“输出 TOOL: 名字”) | 72% | 33% |
这张表回答了一个真问题:function calling 到底比 prompt 强在哪、强多少?
强在可靠性。原生协议和 json_mode 打平(95%),因为它们都给了模型一个结构化的契约去遵守。纯 prompt 引导在 FAQ 场景只有 33%——模型压根不按你规定的格式,随手回你一段自然语言。
结论很直接:function calling 不是花架子。能用原生协议,就别用 prompt 硬模拟。
剩下 5% 的失败更有意思——不是协议不稳,是模型"觉得自己知道答案,跳过了检索工具"直接回答。这是 RAG 的老难题,得靠 prompt 强制检索解决,跟换不换调用方式无关。
六、LLM 只是跑出结果:你还需要一层审视
写到这,停下来看一个贯穿始终、却很容易被"Agent 很酷"盖过去的事实:
实测里那 5% 的失败、72% 的 prompt fallback,说的是同一件事——LLM 是概率性的。
它会跳过你给的检索工具直接编、会不按你规定的格式输出、会对着一个不存在的订单号一本正经地胡说。"跑出结果"和"结果可靠"之间,隔着不确定性。
这是 LLM 和传统确定性开发的根本边界。你写if x > 0:,它永远只在 x>0 时进分支;你让 LLM 判断意图,它有概率判错。你不能像信任 if/else 那样,信任 LLM 的任何一次单点输出。
所以一个能上生产的 Agent 系统,光靠 LLM 不够,外面必须套一层审视机制。两种形态:
on-the-loop——系统在回路上监督。不信任单次输出,用确定性代码约束它:max_steps防死循环、连续调用检测防卡死、JSON schema 校验防乱编参数、工具报错回灌让它重试、路由置信度低于阈值就降级为"请您描述清楚一些"。LLM 每走一步,都被一道闸门拦一下。
in-the-loop——人在回路里把关。高风险动作绝不自动执行:取消订单、发起退款这些有现实后果的操作,打requires_confirmation,先回"确认取消 ORD001 吗?",用户点头才放行。把人插进回路,用人的确定性兜 LLM 的不确定性。
这套"把不可靠的 LLM 单元套进一层驾驭"的思路有个名字:Harness 架构——上下文管理 + 评估循环 + 护栏,目的就一个,让 AI 可靠地完成任务。Claude Code、Cursor 这些工程化做得好的 Agent,内核都是 harness;它们的"好用",很大程度来自 harness 做得厚,不是模型本身多神。
回头看第三节那些"防御":max_steps、循环检测、错误回灌、requires_confirmation——它们不是临时补丁,正是 harness 的具体实现。on-the-loop 是max_steps和校验,in-the-loop 是requires_confirmation。每写一层 LLM 调用,你都会本能冒出一句"它要是出错怎么办",然后加一道审视。手写一遍,这句话会问到你的肌肉记忆里。
而且这些审视,现在还是散落在各模块里的——agent.py 管循环、tools.py 管校验、system 管路由阈值。当它们被收敛成一个统一管上下文、评估循环和护栏的运行时层,就是harness runtime。Claude Code、Cursor 好用的秘密,LangChain 真正在卖的东西,很大程度就是这一层——而这层该长什么样,手写一遍你就知道了。
这也是为什么"Multi-Agent 到底比单 Agent 强在哪"的答案,不在 Agent 数量,而在你愿意为不可靠性配多厚的审视层。
七、写完之后
手写一遍,我得到了什么?
不是"以后可以不用框架了"。框架依然有价值——省事、有生态、有社区。
而是用框架时,终于知道每一行在干什么。agent.run()卡住,我知道去查哪一层;想加个工具,我知道在哪注册;面试被问架构,我能讲清"为什么这么设计"。
还有一条更重要的:懂了 LLM 的边界在哪——哪些可以交给概率,哪些必须用确定性兜底。这条边界,不亲手写一遍,看不见。
"会用"和"懂"之间,隔着一条手写的沟。框架帮你跳过了实现,但没帮你跳过理解。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~