LLM工具调用速记

LLM 工具调用

第一层:Function Calling (函数调用) 核心总结

Function Calling 是整个大模型 Agent 架构的最底层基建。它的核心使命是将大语言模型(LLM)的意图转化为可以被代码直接执行的指令。


一、 核心概念与职责分工 (What & Who)

理解 Function Calling 的第一步,是明确各方的"权责边界"。大模型绝对没有自己访问网络或直接执行代码的能力。整个流程是一场标准的任务委托:

  • 开发者 (HR) :负责编写结构化的 JSON Schema(职位说明书),清晰定义工具的名称、功能描述和参数规范。
  • 大模型 (经理) :只负责决策。它阅读 Schema 后,判断当前任务需要哪个工具,并输出一段结构化的 JSON 指令。
  • 宿主代码 (员工) :负责执行。比如你的 Spring Boot 后端拦截到这条 JSON,去调用 MyBatis 查库或者请求第三方 API,然后把真实数据反馈给模型。

二、 训练机制:模型是怎么学会的?(How)

Function Calling 绝不是大模型参数量大自然产生的"涌现能力",而是经过两个阶段专项训练"教"出来的:

  1. SFT (监督微调) ------ 解决"会不会调"

    • 目标:让模型通过模仿,学会标准动作。
    • 方法:给模型喂大量包含完整链路的对话数据(包括 Schema 识别、结构化 JSON 输出、处理外部结果)。
    • 关键点:训练数据必须包含失败重试、不需要工具直接回答等场景,否则模型会变成遇到什么问题都去调工具的"傻瓜"。
  2. RLHF (人类反馈强化学习) ------ 解决"该不该调"

    • 目标 :帮模型建立边界感
    • 方法:通过奖励模型(Reward Model)打分,引导主模型:能用内部知识解决的直接回答,需要实时数据或特定操作时才输出工具调用指令。

三、 核心运行闭环 (The Loop)

在实际的工程运行中,这套机制表现为一个"两轮对话 + 中间执行"的标准闭环:

  1. 第一轮对话 (模型下指令) :将用户问题和可用工具列表发给模型。模型决定调用工具,暂停回答,输出包含工具名和参数的 JSON,并返回 finish_reason: "tool_calls" 信号。
  2. 中间执行 (代码干活) :宿主程序拦截该信号,解析 JSON,执行本地方法获取结果。
  3. 第二轮对话 (模型给答案) :将执行结果封装成 role: "tool" 的消息,追加到历史对话中再次请求模型。模型结合数据,生成最终的自然语言回复。

四、 进阶特性与工程化考量 (Advanced)
  • 并行调用 (Parallel Tool Calling) :当任务需要多个不相关的工具时(如同时查北京和上海的天气),模型可以一次性输出多个 JSON 指令。此时,宿主代码可以利用 Java 的并发工具(如 JUC 的线程池或 CompletableFuture)同时执行这些方法,将耗时极大的多轮串行压缩为"一轮对话 + 并发执行"。前提是工具之间没有依赖关系
  • JSON Schema 的核心命门 :在定义工具时,description (描述) 字段是模型决定"要不要调"和"怎么填参数"的唯一依据。描述越清晰、边界越明确,模型的准确率越高。

五、 常见面试踩坑预警 (Pitfalls)
  1. 误区:把"涌现能力"当成工具调用能力。 必须明确指出它是 SFT 和 RLHF 双阶段训练的产物。
  2. 误区:认为新一代推理模型(如 o1, DeepSeek-R1)的 Function Calling 能力一定更强。 实际上,早期推理模型因为"连续的思维链生成"与"中断等待工具结果"在工作范式上存在根本冲突,往往不支持或需要使用"思考完再调工具"的折中方案。

第二层:MCP (模型上下文协议) 核心总结

一、 为什么有了 Function Calling 还需要 MCP?(痛点与背景)

在只有 Function Calling 的时代,接工具是个纯纯的"体力活":你写了一个查数据库的工具,要在你的系统里写一遍对接代码;如果你换了个项目,或者要把这个工具给 Cursor 用,你得把代码重写一遍

MCP 的核心使命 :打破这种碎片化,充当 AI 界的 "USB 接口标准" 。只要工具方(比如 GitHub)按照 MCP 标准写好一个 Server 服务,任何支持 MCP 的 AI 客户端插上就能用,真正做到"一次编写,到处复用",零代码接入

二、 架构分工:三个角色的各司其职

不要把 MCP 简单理解为普通的 C/S 架构,它其实有三个明确的角色:

  1. Host (宿主应用) :比如你用的 Claude Desktop 或者 Cursor。它是"总指挥",负责决定连接哪些外部 Server,但不亲自负责通信。
  2. Client (客户端模块) :内嵌在 Host 里的"联络员"。负责转发模型的指令,带回执行结果。
  3. Server (服务端/工具端) :外部工具的实际实现方(比如本地文件系统 Server)。它不在乎是谁在调用它,只要对方支持 MCP 协议就行。一个 Host 可以同时连接无数个不同的 Server。
三、 核心能力:Server 能提供什么?

面试如果问到 MCP 能暴露什么,千万别只答"能提供工具"。它其实把能力划分成了严格的三类:

  1. Tools (工具) :有副作用、会改变世界的操作(如建文件、改代码、删库)。因为有破坏性,通常必须经过用户授权确认
  2. Resources (资源) :纯只读的资料室(如读本地日志、查天气)。无副作用,安全级别高,可以直接给模型看。
  3. Prompts (提示模板) :带参数占位符的预定义模板。解决团队协作中重复手写 Prompt 的问题,统一规范。
四、 💣 面试必杀题:MCP 和 Function Calling 到底啥区别?

这是极其容易踩坑的地方!两者处于完全不同的抽象层次,绝不是替代关系。

  • 根本区别:Function Calling 解决的是"模型怎么输出调用格式(指令)";MCP 解决的是"工具怎么跨项目复用与自动发现(生态管理)"。
  • 依赖关系MCP 底层依然是靠 Function Calling 驱动的! 大模型本身根本不知道什么是 MCP。是 MCP Client 连接 Server 后,把工具翻译成了 Function Calling 的 JSON Schema 喂给大模型,大模型依然输出 tool_calls JSON 指令。
  • 总结 :原生 Function Calling 是驱动 MCP 最高效、最主要的方式;但不支持原生 FC 的模型并非绝对用不了 MCP------Host 可以把 MCP 工具说明书以自然语言喂给模型(ReAct 式),靠文本解析拿到调用意图后再转成 JSON-RPC,只是可靠性和成本更差。

为了彻底搞懂,我们把整个系统拆解成三个实体角色,并一步步演示它们的交互流程:

  1. MCP Server(工具端) :比如你本地跑的一个能读写文件的服务。
  2. AI Client / Host(调度端) :比如你正在用的 Cursor 或 Claude Desktop 软件。
  3. 大模型 LLM(大脑端) :比如云端的 GPT-4o 或 Claude 3.5。

请记住核心秘密:大模型是瞎子,它根本不知道有 MCP 的存在。全靠中间的 AI Client 在做"翻译"和"跑腿"。

下面是完整的详细执行流程:

🔄 详细协同流程(6步闭环)

第 1 步:自动发现工具(MCP 协议发力)
  • 动作:你打开了 Cursor。Cursor (AI Client) 根据配置文件,在后台连接上了本地的文件系统 MCP Server。
  • 通信 :Cursor 问:"你会干啥?" MCP Server 返回一份自己支持的工具列表(比如 read_file, write_file)。
  • 此时,大模型还没参与进来。
第 2 步:翻译成 Schema(桥梁纽带)
  • 动作 :Cursor 拿到工具列表后,在内部默默做了一件事------翻译
  • 转换 :它把 MCP 定义的工具格式,精准翻译成大模型能听懂的 Function Calling JSON Schema (包含 name, description, parameters)。
第 3 步:带上工具问大模型(进入 Function Calling)
  • 动作 :你在对话框输入:"帮我读取一下桌面上的 test.txt"。
  • 通信 :Cursor 把你的问题,连同刚才翻译好的 JSON Schema 列表,一起打包通过 API 发送给云端的大模型。
  • 此时,大模型看到了用户问题和一份说明书。
第 4 步:模型输出 JSON 指令(Function Calling 发力)
  • 动作 :大模型读完说明书,发现需要读文件,于是它暂停生成自然语言回答
  • 通信 :大模型输出了一段特定的 JSON 指令(比如 {"name": "read_file", "arguments": {"path": "desktop/test.txt"}}),并返回 tool_calls 结束信号。
  • 记住:模型只输出指令,它自己没有去读文件!
第 5 步:拦截并真正执行(回到 MCP 协议)
  • 动作:Cursor 拦截到了模型发来的这条 JSON 指令。它知道要调哪个工具了。
  • 通信 :Cursor 通过 MCP 协议 (JSON-RPC),向本地的文件系统 MCP Server 发送执行请求。MCP Server 真正去硬盘里把 test.txt 的内容读了出来,返回给 Cursor。
第 6 步:带着结果索要最终答案
  • 动作:Cursor 拿到了文件内容(比如里面写着"Hello World")。
  • 通信 :Cursor 把这个结果打包成 role: tool 的上下文,再次发给大模型
  • 最终:大模型结合内容,生成最终回复:"您桌面上的文件内容是 Hello World。" Cursor 展示给你看。
五、 通信基建:到底怎么传数据?

MCP 的设计非常优雅,做到了消息格式与传输通道解耦

  • 统一语言 :大家都用轻量级的 JSON-RPC 2.0 格式发消息。

  • 两种通道任选

    1. stdio (标准输入输出) :本地首选。Server 作为子进程直接跑在本地电脑上,通过操作系统的管道通信,零网络延迟,最安全
    2. Streamable HTTP :远程首选。通过单一 HTTP 端点处理,方便团队共享云端服务。 (注:老面经里经常提的 SSE 传输方式,在 2025 年的 MCP 规范中已经被正式弃用了!)

第三层:Agent Skill (智能体技能) 核心总结

一、 痛点与背景:有了工具,为什么还需要 Skill?

给新员工配了电脑、开了系统权限(相当于接了 MCP),但他依然可能不知道"财务报表"应该按什么格式写、先查哪个库后查哪个库。

  • 过去的做法:人类每次都要手动复制粘贴一大段长长的 Prompt,告诉 AI 步骤,繁琐且团队标准难以统一。如果把所有步骤全塞给 AI,又会撑爆宝贵的上下文窗口(Context Window)。
  • Skill 的核心定位 :把重复性的工作流(指令、脚本、模板)打包成一个标准化的、能被 Agent 自动发现并按需加载 的能力模块。它提供的是知识和业务流程(脑)
二、 物理形态:Skill 到底长什么样?

Skill 并不是一段简单的文本,它在物理层面上是一个文件夹 。这种纯文本/Markdown 的设计"零门槛",已被各大主流平台广泛支持。 一个标准的 Skill(比如代码审查 code-review)长这样:

  • SKILL.md核心灵魂。包含头部描述(告诉 AI 这是啥)和正文步骤(第一步干啥,第二步干啥)。
  • scripts/(可选):放一些辅助脚本,比如安全扫描的 Python 代码。
  • assets/(可选):放输出模板,比如 review_report_template.md
三、 🌟 面试必考亮点:渐进式加载 (Progressive Disclosure)

这是 Skill 最聪明的设计,也是面试拿高分的关键!为了防止成百上千个 Skill 瞬间挤爆 Agent 的脑容量,它采用了"三层按需加载":

  1. 第一层(看面试) :平时 Agent 只加载 Skill 的名字和一句话介绍(只占几十个 Token),心里有个数。
  2. 第二层(看详细手册) :只有当你真的让它"做个代码审查"时,它匹配上了,才会去完整读取 SKILL.md 里的所有步骤。
  3. 第三层(用到再取物) :当步骤执行到"请按模板输出"时,它才会在那一刻去读取 assets/ 里的模板文件。 (这就好比:平时只看目录 -> 报销时才翻看报销流程 -> 填表时才下载报销单模板。)
四、 黄金三角关系:Function Calling vs MCP vs Skill

如果在面试中被问到这三者的区别,直接抛出这个"厨房做菜"的满分推演:

  • Function Calling (底层) :是厨师的"手",能拿刀、开火。
  • MCP (中间层) :是标准化的"厨房",工具和食材都摆好了,随取随用。
  • Skill (顶层) :是"菜谱",告诉你"先用 MCP 拿这块肉,再用 Function Calling 切片,最后按菜谱排盘"。

现代大模型 Agent 全链路架构与运行时解析

核心体系:Function Calling (底层通信) × MCP (工具生态) × Agent Skills (业务编排)

架构哲学:大模型只做无状态的"闭眼决策",宿主应用(Host)掌控全场的状态刷新与数据喂养。


一、 核心组件与物理形态解构

在代码跑起来之前,我们必须明确这四大组件在服务器里的真实物理形态,这是理解数据流转的前提:

组件名称 物理形态 核心职责与状态
Host 宿主应用 Java/Spring Boot 进程 全场唯一主宰(Stateful) 。维护长连接、管理状态机、负责工具剪枝(海选)以及向大模型发起网络请求。
MCP Server 独立子进程 / 微服务 外部手脚(执行层) 。将查库、读文件等物理操作标准化为 Tools,通过 stdio/HTTP 供 Host 随时调用。
Agent Skill 磁盘里的文件夹 大脑里的 SOP(战术层) 。包含 SKILL.md(纯文本操作步骤)和输出模板,指导模型"先干嘛,后干嘛"。
LLM 大模型 云端计算引擎 绝对无状态(Stateless) 。没有记忆,不上网。单次请求只负责阅读 Host 递过来的 JSON 包,并输出下一个 Token。
Function Calling JSON 文本协议 神经电信号。大模型与 Host 之间的结构化意图传递格式。

二、 全生命周期:五大执行流转阶段 (核心数据流)

当用户下发任务(如:"帮我审查桌面上的 login.java"),底层会经历极其严密的 5 个阶段流转:

阶段一:系统启动与工具静态收割(初始化)

  1. MCP 物理建连 :Host 启动时,拉起所有的 MCP Server,通过 RPC 将上百个原子工具的 Schema 全部拉取并常驻在本地内存中
  2. 轻量菜单注入 :Host 扫描本地 Skills 目录,只提取每个 Skill 的 namedescription,拼入 System Prompt

💡 此时状态 :大模型只知道自己有几个"技能包",对底层的具体操作步骤和细粒度工具一无所知,完全闭眼,极大节省 Token 成本。

阶段二:意图匹配与渐进式加载(技能激活)

  1. 语义匹配 :大模型阅读用户提问和精简菜单,精准命中 code-review 技能,并输出特定激活信号。
  2. Host 物理读取 :Host 拦截到该信号,立刻去磁盘把 SKILL.md完整 SOP 步骤文本读取到内存中,准备拼装上下文。

阶段三:前置拦截与运行时工具剪枝(Tool RAG)

SOP 第一步要求:"请读取待审查的代码文件内容。"

  1. Host 独自海选 :Host 拿到这一步的文字意图,在本地内存的"百宝箱"中做向量/关键词检索,将 100 个工具强行精简 为当前步骤最需要的 1 个工具(如 read_file)。

  2. Payload 组装发货:Host 构造一个全新的 HTTP POST 请求包:

    • Skill 的步骤文本 塞进 messages 数组(任务语境)。
    • 海选出的 read_file Schema 塞进 tools 数组(唯一的合法工具)。
  3. 发送请求:Host 将这个合二为一的数据包,一次性发给云端大模型。

阶段四:大模型决策与脑冻结(输出 FC)

  1. 双线配对 :大模型收到包,在 messages 看到读文件要求,同时在 tools 看到贴心准备好的 read_file 说明书。两者结合,触发 SFT 训练形成的肌肉记忆。
  2. 强制暂停 :大模型立刻中断文本生成
  3. 输出指令 :大模型输出结构化的 JSON 指令(包含函数名和路径参数),API 响应 finish_reason: "tool_calls"。大模型随后进入休眠挂起。

阶段五:物理执行与多轮刷新闭环(偷梁换柱)

  1. 走 MCP 驱动硬件 :Host 拦截 JSON 指令,通过 MCP 协议指挥底层 FileSystem_MCP_Server 真正去读取硬盘源码。

  2. 刷新工具背包,开启下一轮(最核心机制)

    • Host 拿到源码,准备发起全新的一轮 HTTP 请求
    • 动态切换 :Host 发现 SOP 进入第二步(运行扫描脚本)。它会把第一轮用过的 read_file 工具从 Payload 中彻底抹掉,换成最新的 run_script 工具 Schema
    • 数据回喂 :将读出的源码打包成 role: "tool" 塞进历史,连同换好的新工具包,再次发给大模型。
  3. 完美交卷 :大模型经历多次死循环流转,走到 SOP 最后一步(套用模板)。大模型评估无需新工具,直接吐出最终报告文本返回 stop,Host 拦截放行,任务结束。


三、 抓包级揭秘:底层 JSON Payload 对照

为了看清 Host 是如何"偷梁换柱"的,我们对比第一轮和第二轮的真实 HTTP 请求载荷(Payload):

📦 轮次 1:步骤一,Host 只给 read_file 工具

JSON

swift 复制代码
{
  "model": "gpt-4o",
  "messages": [
    {
      "role": "system",
      "content": "【code-review】技能 SOP:\n1. 读取代码。\n2. 运行扫描脚本。"
    },
    { "role": "user", "content": "审查桌面 login.java" }
  ],
  "tools": [
    {
      "type": "function",
      "function": { "name": "read_file", "description": "读取文件" }
    }
  ]
}

📦 轮次 2:步骤二,Host 拿到源码,动态换成 run_script 工具

JSON

swift 复制代码
{
  "model": "gpt-4o",
  "messages": [
    { "role": "system", "content": "【code-review】技能 SOP:\n1. 读取代码。\n2. 运行扫描脚本。" },
    { "role": "user", "content": "审查桌面 login.java" },
    { "role": "assistant", "tool_calls": [{"id": "call_1", "function": {"name": "read_file"}}] },
    { "role": "tool", "tool_call_id": "call_1", "content": "public class Login { ... }" }
  ],
  "tools": [
    {
      "type": "function",
      "function": { "name": "run_script", "description": "运行安全检测脚本" }
    }
  ]
}

🔑 核心密码 :大模型并不在运行中途伸手要工具,而是 Host 趁着每一轮新请求发起前,主动在 tools 数组里玩了一场"魔术替换"。


四、 高级架构师面试金句储备

  1. "大模型是木偶,Host 才是真正的主宰"

    大模型从不主动翻书或找工具,它所有的上下文(SOP)和可见选项(Tools)全靠 Host 应用在 HTTP 请求发起前进行打包组装。大模型每次下达指令后都会断开连接交出控制权,赋予了 Host 拦截和状态重置的绝对权力。

  2. "信息减肥(Tool Pruning)是生产级 Agent 的生死线"

    绝不能把系统内所有的 MCP 工具在初始化时全塞给模型。必须依靠 Host 结合 Skill 步骤意图进行 Tool RAG(工具海选)动态剪枝。这不仅能死守 Context Window(省钱),更是彻底消灭"模型调错工具"这种高维幻觉的唯一手段。

  3. "宏观流程归 Skills,微观原子归 MCP"

    Skill 提供的是纯文本 SOP,解耦了业务逻辑;MCP 提供的是通用协议接口,解耦了硬件实现。即使明天读文件底层从本地硬盘换成了阿里云 OSS,Skill 手册连一个字都不用改,大模型依然只需说"我要读文件",底层适配由 Host 和 MCP 搞定。

现代大模型 Agent 第四层:A2A 多智能体协同架构解析

核心体系 :Agent-to-Agent (A2A) / Multi-Agent Orchestration 架构哲学:不要造一个全能的神,而是造一群偏执的专家。大模型之间从不直接通信,一切皆由 Host(宿主代码)通过切换上下文与状态机进行"物理隔离"与"无缝接盘"。
⚠️ ⚠️⚠️ 命名纠偏(面试保命,必读): 本层讲的"Host 内切换 Prompt/Tools 的多 Agent 编排"是进程内(in-process)多智能体架构 。而 Google 2025 年发布的 A2A 是一个真正的开放网络协议 ------支持跨机器、跨组织、异构框架的独立 Agent 通过 HTTP/JSON-RPC 互相发现(Agent Card)与调用,Agent 之间真的会联网通信。面试提到 "A2A" 时默认指后者这个协议;说进程内编排时用 "Multi-Agent Orchestration / Handoff" 更准确,别张冠李戴。


一、 为什么必须引入 A2A?(单体 Agent 的死亡陷阱)

在真实的生产环境中,试图打造一个"既能写代码、又能测 Bug、还能查数据库、最后发邮件"的全能单体 Agent(God-mode Agent) ,在工程上注定会引发三大灾难:

  1. 人格精神分裂(System Prompt 爆炸) :为了让它什么都会,你必须在 System Prompt 里塞入极其庞大的设定和几十个 SOP。大模型的"注意力机制(Attention)"会被彻底分散,导致它什么都做不好,频繁遗忘步骤。
  2. 工具海选失控(Tool RAG 失效) :当一个 Agent 挂载了跨领域的 500 个微观工具时,语义搜索极易发生灾难性重叠。例如:"删除无用代码"和"删除数据库冗余表"意图相近,大模型一旦幻觉调错,可能直接删库跑路。
  3. 上下文雪崩(Context Bloat) :一个人干完所有事,其漫长的思考链、报错重试日志全堆积在同一次对话历史中。不出 10 轮,Token 上限被撑爆,系统瘫痪。

A2A 的本质解法 :化繁为简。通过公司级的组织架构编排,建立多个职责单一、隔离运行的专职 Agent(各自拥有极简的 Prompt 和极少的专属 Tool),并通过 Host 宿主应用进行调度。


二、 进程内多 Agent 编排的底层真相:大模型之间如何"聊天"?

打破幻觉:在单进程编排(如 LangGraph/Swarm)里,两个 Agent 角色之间不会通过网络互发消息。

在一个宿主应用中,全场依然只有一个(或少数几个)"大模型 API"(计算引擎),和你的一个"Java 后端"(Host 宿主)。所谓的"多个 Agent",在代码底层其实是"Host 维护的多个配置字典(包含专属 Prompt 和专属 Tools)"。

当 Agent A 需要呼叫 Agent B 时,本质上是: 大模型输出一段 Function Calling ──> Host 拦截该调用 ──> Host 把发给大模型的 System Prompt 从 A 替换成 B ──> Host 再次发包。


三、 进程内多 Agent 编排的三大主流工程落地模式

在 Java/Python 宿主代码的控制下,A2A 呈现出三种极其经典的拓扑结构:

模式 1:交接棒模式 (Handoff / OpenAI Swarm 架构)

最轻量、最优雅的流水线模式。把"转接"本身当成一种工具(Function Calling)。

  • 机制 :【前台客服 Agent】的专属背包里,有一个特殊的工具叫 transfer_to_order_agent

  • 执行流

    1. 客户问订单状态,【客服 Agent】发现超纲,调用 transfer_to_order_agent 工具(输出 JSON)。
    2. Host 核心魔法(偷梁换柱) :Java 后端拦截到这个函数名,不调物理世界 ,而是将当前的 System Prompt 强行切换为"你是订单专家",并将背包里的工具清空,换上 query_sql 工具。
    3. Host 带着原来的聊天记录和新的设定,发起新一轮无状态 HTTP 请求。大模型睁眼一看,自己已经"魂穿"成了订单专家。

模式 2:包工头模式 (Supervisor / Router 架构)

适用于高度并行的宏观复杂任务拆解(Map-Reduce 思想)。

  • 机制:设立一个不干脏活的【包工头 Agent】(Router),它的工具全都是呼叫小弟的指令。

  • 执行流

    1. 【包工头 Agent】接到大任务,输出 Function Calling 决定分发给 Coder_AgentTester_Agent
    2. Host 核心魔法(异步线程) :Java 后端拦截到分发指令,在后台开启两个异步线程(或微服务) ,分别挂载两套不同的 Prompt 和 Tools 请求大模型。
    3. 两个子线程干完活,Host 将它们的结果汇总成一段 Markdown,作为 Tool Result 塞回给【包工头】,包工头做最终汇报。

模式 3:共享白板模式 (StateGraph / LangGraph 思想)

适用于需要频繁打回、反复横跳的环形工作流(如:写代码 -> 跑测试 -> 报错打回重写)。

  • 机制 :Host 在 JVM 内存中维护一个全局的 JSON 状态树(State 对象) ,它是一块所有 Agent 共同读写的"大白板"。

  • 执行流

    1. 【Coder Agent】写完代码,Host 将其存入 State 的 code_snippet 字段,Coder 休眠。
    2. Host 核心魔法(状态机驱动) :Java 后端监听 State 变化,触发图节点流转,唤醒【Tester Agent】。【Tester Agent】只读取白板上的代码,测出 Bug,将报错写入 State 的 error_logs 字段。
    3. Host 再次监测到状态变化,顺着状态图 (注意:带"报错打回重写"回路的图不是 DAG ------DAG 不允许环;LangGraph 的核心卖点恰恰是支持带环的循环图 )重新唤醒【Coder Agent】修复 Bug,直到 error_logs 为空。

四、 源码抓包级解密:Handoff 模式的 Payload 变身

我们来看看在"交接棒模式(Handoff)"下,Host 是如何通过修改 HTTP Payload 让大模型瞬间"换脑"的。

🎭 上半场:【接待员 Agent】的 Payload

JSON

json 复制代码
{
  "model": "gpt-4o",
  "messages": [
    { "role": "system", "content": "你是前台接待员。如果用户问订单,请调用转接工具交接给订单专员。" },
    { "role": "user", "content": "我昨天的退款到账了吗?" }
  ],
  "tools": [
    {
      "type": "function",
      "function": { "name": "transfer_to_order_agent", "description": "转接给订单专员" }
    }
  ]
}

大模型输出:我要调 transfer_to_order_agent。Host 拦截!

🎭 下半场:Host 偷梁换柱后,发出的【订单专员 Agent】Payload

JSON

json 复制代码
{
  "model": "gpt-4o",
  "messages": [
    { "role": "system", "content": "你是严格的订单专员。请使用查库工具解决用户关于退款的问题。" }, 
    { "role": "user", "content": "我昨天的退款到账了吗?" },
    { "role": "assistant", "content": "为您转接订单专员..." }
  ],
  "tools": [
    {
      "type": "function",
      "function": { "name": "query_database", "description": "查询 MySQL 订单表" }
    }
  ]
}

⚠️ 视觉盲区破除 :你看,根本没有两个大模型在通信!只有 Host 这一双"无形的手",在两次 HTTP 请求之间,强行把大模型的"脑子"(system prompt)和"手脚"(tools)给换掉了。 大模型永远以为自己只是在回答当前上下文的问题。


五、 面试通关核心大局观(背诵金句)

  1. "A2A 的本质,是 Prompt 和 Tools 的动态沙盒隔离" 多智能体架构并不是 AI 产生意识在互相聊天,而是 Host 宿主应用通过维护复杂的状态机(State Machine),在多轮对话中动态切换 System Prompt 和权限极窄的 MCP 工具集。通过空间隔离,彻底消灭了单体 Agent 的上下文污染和工具乱调问题。
  2. "调用同僚也是一种 Function Calling" 在现代 A2A 设计(如 Swarm)中,将控制权移交给下一个 Agent,其底层实现就是让大模型触发一个特定的 Function Calling。Host 拦截到这个动作后,不操作物理世界,而是操作内存中的上下文路由表。
  3. "状态图(带环的图)是 A2A 走向工业级的底座" 面对复杂的长周期业务流(如自动化软件开发),不能依赖大模型自己做路由。必须在 Java/Python 后端引入 LangGraph 思想,通过预先定义好的状态图(支持循环/回路的图,而非严格 DAG------重试打回的场景天然有环) 和共享状态(Shared State)来兜底,确保 AI 的每一步执行都在人类设定的公司组织架构约束之内流转。

现代大模型 Agent 第五层:通信协议与 LLM Gateway 架构解析

核心体系 :网络传输协议栈 × API 网关基建 × SRE 可靠性保障 架构哲学:大模型 API 极其昂贵、缓慢且充满不确定性。绝不能让业务代码直接"裸奔"调用大模型,必须通过统一的 LLM Gateway 充当防弹衣、路由器和印钞机。


一、 通信层:为什么传统的 HTTP 抓不住大模型?

大模型的计算特性是"自回归生成(一个字一个字往外吐)"。传统的 HTTP/1.1 请求-响应模式(必须等整个 JSON 拼完才返回)会导致极高的首字延迟(TTFT)。为了实现流式传输(Streaming),现代后端架构必须在三种长连接协议中做取舍:

1. SSE (Server-Sent Events):纯文本流式的绝对王者

  • 底层机制 :建立在标准 HTTP 协议之上。客户端发起请求后,服务端保持连接不断开,持续单向地往客户端推送 text/event-stream 格式的数据块。
  • 工程优势 :对反向代理(Nginx)、防火墙极其友好;在 Java 体系中实现极其轻量(Spring Boot 原生支持 SseEmitter 或 WebFlux 的 Flux<ServerSentEvent>)。
  • 架构痛点 :它是单向水管。大模型在吐字时,如果用户想打断它,不能在同一根管子里逆流喊停,必须重新发起一个 HTTP POST 请求去通知服务端中断。

2. WebSocket:全双工的对讲机与高并发噩梦

  • 底层机制:通过 HTTP 握手升级协议,建立持久的 TCP 全双工通道,客户端和服务端随时可以互发消息。
  • 架构痛点(后端必考题) :WebSocket 是强状态绑定(Stateful)的。当系统面临百万并发洪峰时,长连接死死绑在某一台特定的 JVM 实例上,导致极难进行水平扩容(Scale-out)。如果该节点宕机,所有连接瞬间断开。为了解决这个问题,往往需要引入 Redis Pub/Sub 或 RocketMQ 来做跨节点的会话状态路由,极大增加了系统架构的复杂度。

3. WebRTC:实时语音 Agent 的唯一解(抗击网络抖动)

  • 底层机制 :彻底抛弃 TCP,走向 UDP 协议
  • 核心破局点 :为什么语音通话不能用 WebSocket?因为 TCP 追求"绝对可靠"。一旦网络抖动丢失了一个数据包,TCP 会触发队头阻塞(Head-of-Line Blocking),死等重传,导致语音瞬间卡顿。而 WebRTC 基于 UDP, "宁可丢包,绝不等候" ,配合底层的 PLC(丢包隐藏算法),换取了低至 100ms 以内的极致丝滑打断体验。

二、 网关层(LLM Gateway):企业级 AI 架构的中枢防线

在微服务架构中,如果几十个业务模块各自在代码里写死 OpenAI 的 SDK、直连公网,系统将面临密钥泄露、节点宕机雪崩、账单失控三大灾难。

引入独立部署的 LLM Gateway(大模型网关) ,是解决这些问题的标准动作:

核心功能 1:统一路由与 SRE 故障转移(Failover)

  • 无缝模型切换 :网关对外暴露一套标准化的 OpenAI API 协议。业务层代码完全不用动,只需在网关后台将路由配置从 gpt-4o 指向私有化部署的 Qwen,流量瞬间无缝切换。
  • 熔断与降级保护:引入高并发熔断机制。当海外大模型 API 出现严重网络超时或 500 报错时,网关立即触发断路器,将请求秒级平滑地 Failover(故障转移)到国内的备用模型节点,保障系统的极致高可用。

核心功能 2:安全防御与鉴权(Cybersecurity 防火墙)

作为抵御恶意攻击的第一道防线,网关承担着至关重要的安全责任:

  • 密钥隔离:将真实的厂商 API Key 封印在网关内存或 Vault 加密机中,对外只给各个业务团队颁发虚拟 Key(JWT Token)。
  • 防注入与漏洞拦截:在流量清洗阶段,集成安全探针。不仅能拦截常见的 Prompt Injection(提示词注入),更能对流入的 Payload 进行深度的模型漏洞分析,精准过滤包含恶意触发器(Trigger)的污染样本,防范潜在的后门攻击(Backdoor Attacks),保护云端模型的纯洁性。

核心功能 3:限流控制(Rate Limiting)与配额管理

大模型接口是极其稀缺的计算资源,极易被恶意请求打挂或刷爆信用卡。

  • 高并发控流:结合 Redis 和 Lua 脚本,实现分布式的令牌桶(Token Bucket)或滑动窗口限流算法。
  • 租户隔离:对不同业务线(如 C端免费用户、B端付费大客)进行细粒度的并发度(TPS)与总 Token 消耗额度控制,防止"吵闹的邻居"效应。

核心功能 4:语义缓存(Semantic Cache)------ 降本增效的核武器

这是大模型网关独有的高级特性,彻底颠覆了传统的 HTTP 文本精准匹配缓存。

  • 原理:用户提问到达网关后,网关首先将其转为向量(Embedding),去后端的 Redis 或专门的向量数据库中进行相似度检索。
  • 效果 :如果发现历史请求中存在极度相似的意图(例如"怎么用 Docker 部署 MySQL"和"MySQL 的 Dockerfile 怎么写",向量相似度 > 0.95),网关将直接拦截请求,把缓存的答案秒级返回给前端。
  • 收益:彻底绕过大模型的漫长推理,API 成本降为 0,响应延迟从 10 秒骤降至 50 毫秒以内。

三、 从底至上的终极技术栈串联

为了将整个五层架构落地为可运行的企业级系统,你可以这样组织你的技术栈:

  1. 容器化基建 :将网关、Host 应用与所有的 MCP Server 打包进 Docker 镜像,通过 docker-compose 或 K8s 进行隔离编排。
  2. 并发与异步调度:在 Host 宿主层(Java 端),利用多线程并发工具包(JUC)、线程池隔离或虚拟线程(Virtual Threads)来处理密集的多 Agent A2A 异步回调与状态流转。
  3. 数据持久与缓存:使用 Redis 来支撑网关层的分布式限流、会话状态(StateGraph)保存以及语义缓存的极速响应。

🎯 终极面试大局观(第五层核心金句)

  1. "大模型的算力瓶颈,必须靠后端的网关基建来填补。" > 不要试图在业务代码里处理大模型的超时与并发。通过引入独立的高可用 LLM Gateway,将熔断、限流、故障转移等 SRE 职责下沉,才能让上层的 Agent 专心做业务编排。
  2. "安全和成本,是企业级 AI 架构的生命线。" 通过网关层的集中化虚拟 Key 签发、动态流量审计以及向量化的语义缓存拦截,将大模型的调用从"不可控的黑盒"变成"可观测、可防御、可计费"的标准化企业资产。

企业级 AI Agent 全链路架构与底层工程实践

架构哲学:大模型只是无状态的"闭眼决策引擎"。真正的智能体架构,是通过宿主应用(Host)掌控全场的状态刷新、数据喂养与上下文沙盒隔离。


🏗️ 第一篇:基础武器库(单兵作战基建)

要构建企业级 Agent,必须先将底层能力解耦为三个层次:指令语言、工具生态、业务大脑

1. 第一层:Function Calling (底层神经元)

Function Calling 的核心使命是将大模型(LLM)的自然语言意图,转化为可被代码直接执行的结构化指令。

  • 训练机制:它绝不是模型的"涌现能力",而是通过 SFT(监督微调)教会格式,再通过 RLHF(人类反馈强化学习)建立边界感(知道什么时候该调,什么时候该直接回答)。

  • 并行调用 (Parallel Tool Calling) :当任务无依赖时(如同时查北京和上海天气),模型可一次性输出多个指令。

    底层细节:此时大模型返回的 tool_calls 是一个 JSON 数组 [{"name": "get_weather", "args": {"city": "Beijing"}}, {"name": "get_weather", "args": {"city": "Shanghai"}}]。宿主代码需遍历数组,丢进 JUC 线程池并发执行,将耗时的串行网络请求压缩为一轮并发。

2. 第二层:MCP 模型上下文协议 (工具生态)

打破 Function Calling 必须硬编码对接的痛点,充当 AI 界的 "USB 接口标准"

  • 物理隔离:MCP Server 是独立运行的外部服务(提供 Tools、Resources、Prompts),它完全不在乎调用者是谁。
  • 绝对盲区大模型根本不知道什么是 MCP! 全靠中间的 AI Client(宿主)去连接 MCP Server,将工具列表"翻译"成 Function Calling 的 JSON Schema,大模型依然只输出原生的 FC 指令。

3. 第三层:Agent Skill (战术大脑)

解决重复手写 Prompt 以及 Context Window 被撑爆的问题。以标准化文件夹的形式持久化业务 SOP。

  • 渐进式加载 (Progressive Disclosure) :这是控制 Token 成本的核心。

    1. 第一层:平时只加载所有 Skill 的名字和简介(用于意图路由)。
    2. 第二层 :只有匹配命中时,才全量读取 SKILL.md 正文(业务步骤)。
    3. 第三层 :走到最后一步时,才动态读取 assets/ 下的输出模板文件。

⚙️ 第二篇:单体 Agent 的运行时黑盒(执行流与抓包)

在代码跑起来后,系统分为两大阵营:有状态的 Host (Java/Spring Boot 后端)与 无状态的 LLM(云端计算引擎)。

🔄 全生命周期:五大执行流转阶段

  1. 系统启动(静态收割) :Host 启动,拉起 MCP Server,将上百个工具 Schema 缓存在本地内存,大模型此时完全闭眼。
  2. 技能激活(渐进加载) :用户发问,大模型命中 Skill。Host 拦截信号,去磁盘读取完整 SKILL.md 准备拼装。
  3. 工具剪枝(Tool RAG) :Host 拿到当前步骤文本,在内存中做向量检索,将 100 个工具强行精简(剪枝)为当前唯一需要的 1 个工具,组装成 Payload 发给模型。
  4. 脑冻结(输出 FC) :大模型看到步骤和说明书,触发肌肉记忆,立刻中断文本生成,吐出 JSON 指令并休眠。
  5. 多轮刷新(偷梁换柱) :Host 走 MCP 驱动硬件拿到结果。在发起下一轮请求前,Host 主动将旧工具 Schema 丢弃,换上下一步需要的新工具 Schema,连同结果发给模型,直到任务结束。

📦 源码抓包级解密:Host 的 Payload 魔术

  • 第一轮请求 (Host 看到了步骤一,只配给 read_file 工具)

    JSON

    json 复制代码
    {
      "messages": [
        {"role": "system", "content": "SOP: 1. 读取代码 2. 运行脚本"},
        {"role": "user", "content": "审查 login.java"}
      ],
      "tools": [{"function": {"name": "read_file"}}]
    }
  • 第二轮请求 (Host 拿到源码,动态换成了 run_script 工具)

    JSON

    json 复制代码
    {
      "messages": [
        {"role": "system", "content": "SOP: 1. 读取代码 2. 运行脚本"},
        {"role": "assistant", "tool_calls": [{"function": {"name": "read_file"}}]},
        {"role": "tool", "content": "public class Login { ... }"}
      ],
      "tools": [{"function": {"name": "run_script"}}] 
    }

    (注:第二轮的 tools 数组里,read_file 被彻底抹去,换成了 run_script。大模型是被 Host 牵着鼻子走的。)


🌐 第三篇:从单兵到军团的宏观基建

单体 Agent 容易陷入"人格分裂"和"上下文雪崩"。走向工业级,必须引入多智能体协同与底层网关护城河。

4. 第四层:A2A 多智能体协同 (组织架构)

A2A 的本质是Prompt 和 Tools 的动态沙盒隔离 (注意版本语境:这说的是进程内编排 ;真正的 A2A 网络协议下 Agent 之间通过 HTTP/JSON-RPC 跨网络互调)。单进程内,Agent 之间不联网通信,全靠 Host 进行内存路由。

  • Handoff (交接棒模式) :转接也是一种 Function Calling。Host 拦截到转接指令后,不调物理世界,而是直接替换大模型的 System Prompt 和专属工具,发起新请求让其"瞬间换脑"。

  • Supervisor (包工头模式) :包工头负责拆解任务,Host 拦截后开启异步子线程,并发挂载不同 Prompt 拉起子 Agent 执行。

  • StateGraph (共享白板模式) :适用于复杂的环形工作流。

    底层细节:Host 在内存中维护一个全局 State 状态树。这是典型的黑板模式 (Blackboard Architecture)响应式事件驱动 (Event-Driven) 设计。Agent A 更新白板数据后休眠,Host 监听到状态变更,自动唤醒 Agent B 接盘,直到全流程走完。

5. 第五层:LLM Gateway (基础设施与 SRE)

绝不能让业务代码直连大模型裸奔。引入独立的 LLM Gateway 充当防弹衣、路由器和印钞机。

  • 网络协议选型 :普通文本流式首选 SSE (对 Nginx 友好,单向流);高并发打断不选有状态的 WebSocket,而选走 UDP 的 WebRTC (宁可丢包绝不重传,抗网络抖动防队头阻塞)。
  • SRE 故障转移 (Failover) :海外 API 宕机超时,网关触发熔断,秒级平滑切流至国内备用模型节点,业务方零感知。
  • 降本核武器 (Semantic Cache 语义缓存) :网关将用户提问向量化,通过计算 Cosine Similarity,拦截相似度 > 0.95 的意图(如"怎么用 Docker"与"Dockerfile 咋写"),直接返回历史答案,API 成本降为 0,延迟降至 50ms 级别。

💡 架构师箴言 : 不要试图让 AI 产生意识去自己找工具。优秀的 Agent 平台,是一个极其精密、充满心机的高并发后端状态机。用 Host 的算力去剪枝,用 Gateway 的缓存去挡枪,把大模型的上下文环境剥离到极简,才是企业级 AI 落地的唯一真相。


⚡ 补充层一:并行工具调用(Parallel Tool Calls,面试高频)

1. 是什么

  • 一次响应里模型同时输出多个 tool_calls (数组多元素,共享同一个 tool_call_id 批次),如"查天气 + 查日历"一次说完。
  • 触发判断在模型侧: 是否并行由模型自己决定(多个调用互不依赖时倾向并行);API 侧可关parallel_tool_calls: false,要强串行时用------比如写操作的顺序敏感场景)。

2. Host 侧实现要点(工程答案,讲这个拿分)

  1. 并发执行: 收到 N 个 tool_calls,用 Promise.all(JS)或线程池(Java)并发分发------串行执行是浪费延迟,面试官等着你说这句。
  2. 结果回喂的顺序铁律: 下一轮 messages必须按 tool_call_id 一一对应地回填所有结果,顺序错/漏一个,API 直接 400------因为模型按 id 关联"哪次调用哪个结果"。
  3. 失败处理: 单个工具失败不要中断整批 ------失败的那条回填 error 消息(is_error 标记),模型看到后会自行决定重试/换路------与 自研 Agent 平台 的"错误回喂自愈"一脉相承。
  4. 写操作慎并行: 并行前提是调用间无依赖且幂等;有依赖的调用模型自己会拆到多轮(但也出现过竞态翻车,所以关键写路径显式关掉 parallel)。

3. 一句话总结

"并行工具调用 = 模型一次给一篮子互相独立的调用,Host 并发执行后按 tool_call_id 对齐回填再进下一轮------收益是延迟取 max 而不是求和;代价是必须自己管好失败隔离和顺序对齐。"


🤖 补充层二:DeepAgents(面试高频,三个考点)

  • 是什么: LangChain 团队推出的深度研究 Agent 框架(2025),= 规划(todo 清单)+ 子 Agent(隔离上下文的文件系统)+ 长时任务管理 三合一的参考实现。

  • 核心机制:

    1. Planning Tool: 维护结构化 todo 列表,每完成一项勾一项------对抗长任务"迷路"。
    2. FileSystem: 把中间产物(笔记/草稿/报告)当文件读写,跨子 Agent 共享------上下文以文件形式外化,突破单轮 context 限制。
    3. SubAgents: 研究型子任务独立上下文执行,结果写回文件系统(与 Supervisor 模式同源,但共享的是文件不是内存 State)。
  • 面试话术: "DeepAgents 的价值不在框架本身,而在它示范了长时 Agent 的三件套------计划外置(todo)、记忆外置(文件)、上下文隔离(子 Agent) 。我项目实践做的 自研 Agent 平台 三层记忆与多 Agent 委派,和它解决的是同一类问题,思路可以互相印证。"


🛡 补充层三:SSRF 与 API 限流退避(自研 Agent 平台 三层防线点名)

1. SSRF(服务器端请求伪造)------ 动态 API 工具的生死题

  • 是什么: 攻击者诱导服务端 替自己去访问内网资源(http://169.254.169.254/ 云元数据、http://localhost:6379 Redis、内网管理后台)------Agent 拿 URL 去调接口的场景天然高危。

  • 三层防线(对齐 自研 Agent 平台 生产实现):

    1. 权限过滤: 工具清单来自 RBAC + swagger 白名单------不在清单里的接口 URL 根本不可达(源头治理)。
    2. 鉴权注入:当前登录用户的身份调用(而非服务账号超级权限)------即使被诱导,权限也只有用户本人那么多(最小权限)。
    3. 目标校验: 解析 DNS 后校验 IP 非内网段/环回/链路本地(防 DNS rebinding:域名解析时换 IP 绕过校验,需在连接时二次校验)、禁非常规协议与端口、跟随重定向时逐跳复检。
  • 一句话: "Agent 能动态调 URL = 把 SSRF 风险当一等公民设计------白名单源头、用户级权限、目标 IP 校验三道闸。"

2. 429 与退避(LLM API 语境)

  • 429 Too Many Requests: 上游限流信号,响应头 Retry-After: n(等 n 秒)优先按它来。
  • 指数退避 + 抖动: 重试间隔 1s→2s→4s...,加随机抖动(jitter)防止集体同步重试造成二次洪峰(雷霆群羊效应);一般 3~5 次后放弃并走降级(切备用模型/返回兜底)。
  • 注意幂等: 429 后重发的请求必须是可安全重放的(补全类请求天然幂等------同 prompt 结果语义等价;带副作用的自定义工具调用要带幂等键)。
  • 与后端限流的呼应: 微服务速记的"重试三原则"(只重试幂等、次数有限、退避)完全通用------区别只在 LLM 场景多了 Retry-After 头和"切模型降级"这个选项。
相关推荐
YIAN2 小时前
手撸社区后端:一套可落地的用户 - 文章 - 互动体系 MySQL 表设计与优化思路
后端·mysql
ThinkerQAQ_3 小时前
并发编程(一):先谈硬件——从 count++ 到原子性、可见性与有序性
后端
岁月如歌77863 小时前
分布式锁完全指南:从数据库到 Redisson 的演进
java·后端·架构
技术猫3 小时前
记一次因线程池不合理使用导致生产拨测告警
后端
写后端的胖头鱼3 小时前
【高频面试题】spring事物失效场景(带原理 + 代码示例)
java·后端·spring·事务·事物失效
JohnCarter20213 小时前
双卡 Atlas 300I Duo 部署 Qwen3-VL-32B:血泪实录
后端
码外生活3 小时前
🎥 手搓一套直播高并发环境!一个后端小白从 0 到 1 的搭建笔记
后端·spring cloud
Lyra_Infra3 小时前
记一次麒麟 Linux 下达梦数据库 (DM8) 部署与 MySQL 命令行无界面迁移踩坑指南
数据库·后端·dba
Daemonkey4 小时前
苦 Elasticsearch/Prometheus 久矣?试试 Rust 打造的云原生可观测新星:OpenObserve
后端