跳到正文

30 行写一个会调用工具的最小 Agent

LLM + 工具循环 = Agent 的本质;面试这条线就靠它讲透

一句话:把「LLM + 一个工具循环」拼起来,就是 Agent 的本质。面试里「Agent 比直接调 LLM 多了什么」「ReAct 怎么跑」「Function Calling 怎么落地」,本质都在问这 30 行。 先建立心智:Agent = LLM + 工具循环 直接调一次 LLM,是「问一句、答一句」,模型只能用它脑子里的东西回答。 Agent 多了一个循环:模型可以说「我先去查一下」,你把它要查的工具真的执行,把结果喂回去,它再接着想——直到它觉得够了,给出最终答案。 这个「想 → 调工具 → 看结果 → 再想」的循环,就是 ReAct(Reasoning + Acting)最朴素的样子。 最小实现(可跑,约 30 行核心) 下面用 OpenAI 兼容接口(DeepSeek / 通义 / 本地 vLLM 都兼容,换 base url 和 model 即可),只给模型一个工具:查天气(这里用假数据,真实场景换成你的 API 调用)。 跑通后你会看到:模型先调两次 get weather,拿到「北京 26℃ / 上海 24℃」,再自己比较,最后回答「北京更暖和」。这就是一个最小 Agent——它没有任何框架,核心就是那个 while True 循环。 逐段拆解(面试能讲清的点) 工具 schema:模型不会执行代码,它只会根据 description 决定「要不要调、传什么参数」,然后吐出一个结构化的调用请求。执行永远是你的代码做的。 role: "tool" 回灌:工具结果必须按规范(带 tool call id)加回 messages,模型下一轮才能「看见」结果。漏了这步是新手最常见的 bug。 循环出口:msg.tool calls 为空就代表模型决定收尾。一定要给循环加最大轮数上限(下面坑里讲),否则可能死循环烧钱。 多工具:把更多函数加进 tools 列表 + 在执行处按 call.function.name 分发,就从「单工具」变「工具箱」。 常见坑 + 工程取舍 不设轮数上限:模型可能反复调工具不收尾。实战必须加 for in range(MAX STEPS) 兜底,超了就强制让它总结。 工具报错不处理:工具抛异常、超时、返回空,要 try/except 兜住,把「失败原因」也当作 tool 结果喂回去,让模型自己决定重试还是换路——而不是整个程序崩。 上下文膨胀:每轮都往 messages 堆东西,长任务很快撑爆上下文。轻量做法是截断/摘要历史(再往上就是训练营讲的 ReSum 那套)。 权限与副作用:能「下单/删库/发消息」的工具,必须加确认或权限闸门——别让模型一句话就把生产数据删了。 关联面试题(去站内练手) 「ReAct 框架的工作流程是什么?和 Plan-and-Execute 有什么区别?」 「Function Calling 在 Agent 里是怎么落地的?数据怎么造?」 「Agent 比直接调 LLM 多了什么?」 👉 去 题库 搜 Agent / Function Calling / ReAct,用相关题目继续练:先讲清这段最小实现,再说明状态、失败处理和生产边界。 训练营延伸 这 30 行是「单 Agent」的地基。再往上——多 Agent 协作、统一工具网关 + 沙箱、长程记忆压缩、用 RL 训练 Agent 的决策策略、可观测与私有化上线——就是训练营里集群 Agent 那条线在做的事。