Agent能力全景解析:从Function Calling到MCP的实战指南
1. 从热搜词看 Agent 的真实需求1.1 为什么大家都在搜 Agent 能力全景最近一段时间我注意到一个很明显的现象身边做后端的朋友、做前端的朋友、甚至做产品的同事都在问同一个问题——“Agent 到底能干什么”这个问题看起来很简单但真正回答起来比想象中要复杂得多。因为大多数人接触 Agent 的路径是反过来的先看到某个框架的文档先学 ReAct 怎么写先研究 Function Calling 的参数格式结果学了一圈下来脑子里全是零散的技术点却说不清楚 Agent 到底解决了什么实际问题。热搜词里有一组特别有意思的对比“agent 和 llm 和 ai 模型 有什么区别”、“比如常说的 deepseek 是属于哪个”。这说明很多人连基本的概念分层都还没理清楚。DeepSeek 是一个大语言模型LLM 是这类模型的总称而 Agent 是在 LLM 之上加了一层“感知-决策-执行”的循环结构。打个比方LLM 是一个知识渊博但只会动嘴的顾问Agent 则是给这个顾问配了手、配了眼睛、配了工具箱让他能真正去干活。还有一组词也很典型“agent开发学习路线”、“llm入门”、“agent框架”。这些搜索背后反映的是一个共同的焦虑——想学但不知道从哪下手。我的建议一直是先看它能干什么再学它怎么做。这个顺序不能反。你先理解了 Agent 能帮你自动查数据库、能帮你操作浏览器、能帮你串联多个 API 完成一个完整任务你再去学 ReAct 的循环怎么写、Function Calling 的 schema 怎么定义就会觉得每一步都有明确的目的而不是在背天书。1.2 本文适合谁看能解决什么问题这篇内容主要面向三类人。第一类是有一定编程基础、想入门 Agent 开发但被各种框架和术语绕晕的工程师。第二类是用过 ChatGPT 或类似产品、想进一步了解“为什么它能自己调用工具”的产品或运营同学。第三类是已经在用 LLM 做应用、但发现单纯靠 prompt 搞不定复杂任务的开发者。我会从 Agent 的能力全景讲起把 Function Calling、ReAct、MCP 这几个核心概念串起来然后给出可落地的实操步骤和参数配置最后分享一些我在实际项目中踩过的坑和排查技巧。全文不会堆砌术语每个技术点都会配生活化的类比和实际案例确保你看完能自己动手搭一个能跑起来的 Agent。2. Agent 能力全景先搞清楚它能干什么2.1 从“只会聊天”到“能干活”的跨越传统 LLM 的使用方式很简单你给它一段 prompt它给你一段回复。这个过程是单向的、无状态的、一次性的。你问它“今天北京天气怎么样”它只能根据训练数据里的信息瞎猜因为它没有实时获取数据的能力。你问它“帮我查一下数据库里上个月销售额最高的产品”它只能告诉你“我无法直接访问数据库”。Agent 的出现改变了这个局面。它的核心思路是让 LLM 不只是生成文本而是生成“行动指令”。这个行动指令可以是调用一个 API、查询一次数据库、打开一个网页、发送一封邮件。LLM 负责决策“该做什么”而实际的执行交给外部工具。执行完之后结果再返回给 LLMLLM 根据结果决定下一步做什么。这个循环可以重复多次直到任务完成。我常用一个类比来解释这个区别普通 LLM 像一个坐在办公室里的顾问你问他什么他答什么但他不会离开椅子去帮你办事。Agent 则像给这个顾问配了一个助理团队——有负责查资料的、有负责跑腿的、有负责操作电脑的。顾问只需要说“帮我查一下上个月的销售数据”助理就去执行然后把结果拿回来。顾问看到结果后继续说“把排名前三的产品做成图表”另一个助理就去画图。整个过程顾问不需要自己动手但他知道该让谁去做什么。2.2 Agent 的四大核心能力模块把 Agent 的能力拆开来看可以归纳为四个模块感知、决策、执行、记忆。感知能力指的是 Agent 获取外部信息的能力。这包括读取用户输入、查询数据库、调用搜索 API、读取文件内容等。没有感知能力Agent 就是一个瞎子只能靠训练数据里的旧信息做判断。决策能力是 Agent 的核心由 LLM 承担。LLM 根据当前的目标、已有的信息、可用的工具列表决定下一步该做什么。这个决策过程就是 ReAct 框架里说的“Reasoning”部分。LLM 会先思考“我现在需要什么信息”然后选择“用哪个工具去获取”最后判断“信息够不够要不要继续”。执行能力指的是实际调用工具的过程。这包括 Function Calling 的机制、API 的调用、参数的传递、结果的解析。执行环节最容易出问题因为外部工具可能返回各种奇怪的格式网络可能超时权限可能不足。记忆能力让 Agent 能在多轮对话中记住之前发生的事情。短期记忆就是当前对话的上下文长期记忆则可能涉及向量数据库、知识库检索等。热搜词里的“llm wiki知识库”、“karpathy llm wiki”就是在讨论如何给 LLM 外挂一个可检索的知识库让它能记住大量专业领域的信息。2.3 能力边界Agent 目前做不到什么在讲 Agent 能做什么的同时我也得说清楚它目前做不到什么。这很重要因为很多新手会对 Agent 抱有不切实际的期望。Agent 目前不擅长处理需要精确计算的任务。虽然它可以调用计算器工具但如果让它自己“心算”结果往往不可靠。Agent 也不擅长处理需要长期规划的任务比如“帮我规划一个为期三个月的学习计划并每天执行”因为它的记忆和规划能力在长周期任务中会衰减。Agent 还不擅长处理模糊的、需要人类常识判断的任务比如“帮我判断这个合同有没有法律风险”它可能会给出看似合理但实际错误的建议。另外Agent 的可靠性高度依赖于工具的质量。如果工具返回的数据格式不规范或者 API 经常超时Agent 的表现就会大打折扣。热搜词里有一条“dify的sql查询内容太多导致llm返回不稳定”说的就是这个问题的典型场景——当工具返回的数据量过大时LLM 的上下文会被撑爆导致输出质量下降甚至报错。3. 核心技术点拆解Function Calling、ReAct 与 MCP3.1 Function Calling让 LLM 学会“点菜”Function Calling 是 Agent 最基础的能力。它的本质是让 LLM 能够输出一个结构化的 JSON告诉外部系统“我要调用哪个函数参数是什么”。你可以把它理解成在餐厅点菜。菜单上写着各种菜名和配料选项你只需要告诉服务员“我要一份宫保鸡丁不要花生微辣”。服务员不需要知道厨房怎么做菜他只需要把你的点单准确传递给厨房。Function Calling 就是 LLM 的“点菜”能力——它不需要知道 API 内部怎么实现只需要输出一个符合格式的调用请求。在实际操作中你需要先定义好工具的 schema。比如一个查询天气的工具schema 可能是这样的{ name: get_weather, description: 查询指定城市的当前天气, parameters: { type: object, properties: { city: { type: string, description: 城市名称如北京、上海 }, unit: { type: string, enum: [celsius, fahrenheit], description: 温度单位 } }, required: [city] } }这个 schema 告诉 LLM有一个叫 get_weather 的工具需要传入 city 参数可选传入 unit 参数。当用户问“北京今天多少度”时LLM 就会输出类似{name: get_weather, arguments: {city: 北京, unit: celsius}}的 JSON。你的程序接收到这个 JSON 后去调用真实的天气 API把结果返回给 LLMLLM 再生成自然语言的回复。这里有一个关键细节description 字段的质量直接决定了 LLM 能否正确选择工具。我见过很多新手把 description 写得很随意比如“查询天气”结果 LLM 在多个相似工具之间反复横跳。好的 description 应该包含这个工具做什么、什么时候用、参数的含义、返回值的格式。写得越清楚LLM 的调用准确率越高。3.2 ReAct思考与行动的循环ReAct 是 Reasoning Acting 的缩写它定义了 Agent 的工作循环。这个循环可以简化为Thought → Action → Observation → Thought → Action → Observation → ... → Final Answer。用生活化的例子来解释你要做一道红烧肉。第一步是 Thought——“我需要先买五花肉和调料”。第二步是 Action——“去超市买肉”。第三步是 Observation——“超市的五花肉卖完了只有前腿肉”。第四步是 Thought——“前腿肉也可以做但口感会差一点需要多炖一会儿”。第五步是 Action——“买前腿肉和调料回家”。第六步是 Observation——“肉已经下锅需要炖 40 分钟”。这个循环一直持续到菜做好为止。在 Agent 开发中ReAct 循环通常由框架自动管理。你只需要定义好工具列表和系统提示词框架会负责解析 LLM 的输出、执行工具、把结果拼回上下文。但理解这个循环的每一步对于调试非常重要。当 Agent 表现异常时你需要能看懂它是在哪一步出了问题——是 Thought 阶段选错了工具还是 Action 阶段参数传错了还是 Observation 阶段结果解析失败了。热搜词里有一条“react 面经”和“react面试题”虽然这里的 React 大概率指的是前端框架 React但有趣的是Agent 领域的 ReAct 和前端 React 在“响应式”这个理念上有相通之处。前端的 React 是数据变化驱动 UI 更新Agent 的 ReAct 是观察结果驱动下一步行动。两者都是“事件驱动”的思路。3.3 MCPAgent 与工具的标准化接口MCP 是 Model Context Protocol 的缩写它解决的是 Agent 与外部工具之间的标准化通信问题。在 MCP 出现之前每个 Agent 框架都有自己的工具定义方式你为 LangChain 写的工具没法直接用在 AutoGPT 上为 Dify 写的工具也没法迁移到其他平台。MCP 试图统一这个接口。你可以把 MCP 理解成 USB-C 接口。以前每个手机厂商都有自己的充电接口换了手机就得换充电线。USB-C 统一之后一根线可以给手机、平板、笔记本充电。MCP 就是 Agent 世界的 USB-C——只要工具实现了 MCP 协议任何支持 MCP 的 Agent 都能直接调用它。热搜词里出现了“mcp是什么”、“mcp协议”、“mcp server”、“mcp开发 workbuddy”、“蓝湖mcp”、“figma mcp怎么运用在trae”、“playwright mcp”、“blender mcp”、“codex联动burp mcp”等一系列相关词。这说明 MCP 的生态正在快速扩展从设计工具Figma、蓝湖到浏览器自动化Playwright到 3D 建模Blender都在接入 MCP。MCP 的核心概念包括Server提供工具的一方、Client调用工具的一方、Resource可读取的数据源、Tool可执行的函数。一个 MCP Server 可以同时暴露多个 Tool 和 ResourceClient 通过标准协议发现并调用它们。这种设计让工具的复用变得非常方便——你写一个 MCP Server所有支持 MCP 的 Agent 都能用。3.4 三者的关系与协作方式Function Calling、ReAct、MCP 不是互相替代的关系而是层层递进的关系。Function Calling 是底层能力让 LLM 能输出结构化的调用请求。ReAct 是中层框架定义了“思考-行动-观察”的循环逻辑。MCP 是上层协议标准化了工具的定义和发现方式。一个完整的 Agent 工作流程可能是这样的用户提出需求 → LLM 通过 ReAct 循环进行思考 → 决定调用某个工具 → 通过 Function Calling 输出调用请求 → 如果工具是通过 MCP 注册的则通过 MCP 协议转发请求 → 工具执行并返回结果 → 结果通过 MCP 返回 → LLM 观察结果并继续循环。理解这三者的关系你就理解了 Agent 开发的主干。剩下的都是在这个主干上添枝加叶——比如加记忆模块、加规划模块、加多 Agent 协作等。4. 实操过程从零搭一个能查数据库的 Agent4.1 环境准备与工具选型在开始写代码之前先说一下工具选型。目前主流的 Agent 开发框架有 LangChain、LlamaIndex、AutoGen、CrewAI 等。如果你是新手我建议从 LangChain 入手因为它的文档最全、社区最大、遇到问题最容易找到答案。如果你更倾向于低代码方案Dify 和 Coze 也是不错的选择它们提供了可视化的 Agent 编排界面。我这次实操用的是 Python LangChain OpenAI 的 API。你需要准备的东西包括一个 OpenAI API Key或者兼容 OpenAI 接口的其他模型服务、Python 3.9 以上的环境、一个可以查询的数据库我用的是 SQLite方便演示。安装依赖的命令如下pip install langchain langchain-openai langchain-community sqlalchemy这里有一个注意事项API Key 千万不要硬编码在代码里。热搜词里有一条“使用llm时如何防止密钥等鉴权信息泄露”这是非常实际的问题。我推荐用环境变量或者 .env 文件来管理密钥并且在 .gitignore 里排除 .env 文件。import os from dotenv import load_dotenv load_dotenv() api_key os.getenv(OPENAI_API_KEY)4.2 定义工具让 Agent 能查数据库第一步是定义一个查询数据库的工具。我用 SQLite 建一个简单的销售表import sqlite3 conn sqlite3.connect(sales.db) cursor conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS sales ( id INTEGER PRIMARY KEY, product TEXT, amount REAL, sale_date TEXT ) ) conn.commit()然后定义工具函数。这里我用 LangChain 的tool装饰器from langchain.tools import tool tool def query_sales(sql: str) - str: 执行 SQL 查询并返回结果。输入必须是合法的 SQLite SELECT 语句。 返回格式为 JSON 字符串包含 columns 和 rows 两个字段。 如果查询出错返回错误信息。 try: cursor.execute(sql) columns [desc[0] for desc in cursor.description] rows cursor.fetchall() result {columns: columns, rows: rows[:50]} return str(result) except Exception as e: return f查询出错: {str(e)}注意这里的 docstring 写得很详细因为 LangChain 会把 docstring 作为工具的 description 传给 LLM。description 的质量直接影响 LLM 能否正确使用这个工具。4.3 构建 Agent 并配置 ReAct 循环接下来构建 Agent。LangChain 提供了create_react_agent函数可以快速创建一个基于 ReAct 循环的 Agentfrom langchain_openai import ChatOpenAI from langchain.agents import create_react_agent, AgentExecutor from langchain import hub llm ChatOpenAI(modelgpt-4o, temperature0) tools [query_sales] prompt hub.pull(hwchase17/react) agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, max_iterations10, handle_parsing_errorsTrue )这里的几个参数需要解释一下。temperature0是为了让 LLM 的输出更稳定减少随机性。max_iterations10是防止 Agent 陷入死循环最多执行 10 轮 ReAct 循环就强制停止。handle_parsing_errorsTrue是当 LLM 输出的格式不符合预期时自动把错误信息返回给 LLM 让它重试而不是直接崩溃。verboseTrue会打印出每一步的 Thought、Action、Observation方便调试。在生产环境中可以关掉但在开发阶段强烈建议打开。4.4 运行测试与结果分析现在可以运行了result agent_executor.invoke({ input: 上个月销售额最高的三个产品是什么总销售额是多少 }) print(result[output])运行后你会看到类似这样的输出Thought: 我需要查询上个月的销售数据按产品分组计算总销售额然后排序取前三。 Action: query_sales Action Input: SELECT product, SUM(amount) as total FROM sales WHERE sale_date 2024-05-01 AND sale_date 2024-06-01 GROUP BY product ORDER BY total DESC LIMIT 3 Observation: {columns: [product, total], rows: [(产品A, 15000), (产品B, 12000), (产品C, 9000)]} Thought: 我已经拿到了前三名的数据现在需要计算总销售额。 Action: query_sales Action Input: SELECT SUM(amount) FROM sales WHERE sale_date 2024-05-01 AND sale_date 2024-06-01 Observation: {columns: [SUM(amount)], rows: [(36000,)]} Thought: 我现在有了所有需要的信息可以给出最终答案了。 Final Answer: 上个月销售额最高的三个产品分别是产品A15000、产品B12000、产品C9000。上个月总销售额为 36000。这个过程中LLM 自主完成了两次工具调用第一次查排名第二次查总额最后汇总成自然语言回答。这就是 Agent 的核心价值——它不需要你写死查询逻辑而是根据问题动态生成 SQL。4.5 参数调优与性能优化在实际使用中有几个参数需要根据场景调整。max_iterations的设置很关键。设得太小复杂任务可能没完成就被强制停止设得太大如果 Agent 陷入死循环会浪费大量 token。我的经验是简单查询任务设 5 就够复杂分析任务设 10-15需要多步推理的任务可以设到 20。max_execution_time可以限制整个 Agent 的执行时间防止某个工具调用卡死导致整个流程挂起。一般设 60-120 秒比较合理。还有一个容易被忽略的参数是early_stopping_method。当 Agent 达到 max_iterations 时可以设置为 force 强制输出当前结果或者设置为 generate 让 LLM 根据已有信息生成一个总结。我通常用 generate因为即使没完全查完LLM 也能给出部分有用的信息。5. 常见问题与排查技巧实录5.1 Agent 不调用工具怎么办这是最常见的问题。你问了一个明明需要查数据库的问题但 Agent 直接凭训练数据回答了根本没有调用工具。原因通常有三个。第一是工具的 description 写得太模糊LLM 不确定这个工具是否适用于当前问题。解决方法是把 description 写得更具体明确说明“当用户询问销售数据时使用此工具”。第二是系统提示词没有强调要使用工具。你可以在 prompt 里加一句“你必须使用提供的工具来获取信息不要依赖你的训练数据”。第三是 LLM 本身的能力不够。一些小模型对 Function Calling 的支持不好换一个更强的模型通常能解决。5.2 工具调用参数错误怎么排查Agent 调用了工具但参数传错了比如 SQL 语法错误、日期格式不对、字段名拼错。这类问题的排查思路是先看 verbose 输出里的 Action Input确认 LLM 生成的参数是什么然后手动执行这个参数看报什么错最后根据错误信息调整工具的 description 或增加参数校验。我遇到过一个典型情况LLM 生成的 SQL 里用了DATE_FORMAT函数但 SQLite 不支持这个函数。解决方法是在工具的 description 里明确说明“本工具使用 SQLite 语法不支持 MySQL 特有函数”。加了这句话之后LLM 就会改用 SQLite 兼容的写法。5.3 返回结果太大导致 LLM 不稳定热搜词里有一条“dify的sql查询内容太多导致llm返回不稳定”这是非常典型的问题。当工具返回的数据量超过 LLM 的上下文窗口时输出质量会急剧下降甚至直接报错。解决方法有几个。第一是在工具层面做限制比如LIMIT 50只返回前 50 条记录。第二是在返回结果时做摘要比如只返回统计信息而不是原始数据。第三是使用分页机制让 Agent 可以分批获取数据。第四是换用支持更长上下文的模型。我在实际项目中通常组合使用前两种方法工具默认加 LIMIT同时在 description 里告诉 LLM“如果数据量较大请先查询汇总信息再决定是否需要明细”。5.4 常见问题速查表问题现象可能原因排查方法解决方案Agent 不调用工具description 模糊、prompt 未强调检查 verbose 输出优化 description、加强 prompt参数格式错误LLM 对工具理解有误查看 Action Input在 description 中补充格式说明返回结果过大未做数据量限制检查工具返回值加 LIMIT、做摘要、分页循环次数超限任务太复杂或陷入死循环查看 verbose 输出调整 max_iterations、优化 promptAPI 调用超时网络问题或工具响应慢检查网络和工具日志设置超时、增加重试机制密钥泄露风险硬编码在代码中检查代码和配置文件使用环境变量、.env 文件5.5 独家避坑技巧第一个技巧在开发阶段把每次工具调用的输入和输出都记录到日志文件里。这样当 Agent 表现异常时你可以回溯整个决策过程快速定位问题。我用的方法是在工具函数里加一行logging.info(fTool called with: {sql})。第二个技巧给工具加一个“干跑”模式。在真正执行 SQL 之前先用EXPLAIN语句检查一下这个查询是否合法、是否会全表扫描。如果查询有问题直接返回错误信息给 LLM让它重新生成。这样可以避免执行到一半才发现问题。第三个技巧对于涉及敏感数据的工具加一层权限校验。比如查询用户信息的工具应该检查当前请求是否有权限访问该用户的数据。热搜词里“使用llm时如何防止密钥等鉴权信息泄露”提醒我们Agent 调用工具时可能会把敏感信息暴露在日志或上下文中需要特别注意。6. Agent 开发的进阶方向6.1 多 Agent 协作单个 Agent 的能力有限当任务复杂到需要多个专业角色协作时就需要多 Agent 系统。比如一个电商分析场景可能需要一个“数据查询 Agent”负责查数据库一个“分析 Agent”负责做统计一个“报告 Agent”负责生成图表和文字。这三个 Agent 各司其职通过消息传递协作完成任务。热搜词里的“harness和agent区别”其实就是在讨论这个层面的问题。Harness 通常指的是管理多个 Agent 的调度框架它负责分配任务、协调通信、处理冲突。Agent 是执行单元Harness 是管理层。6.2 记忆与知识库Agent 的记忆能力是决定它能否处理长周期任务的关键。短期记忆靠上下文窗口长期记忆则需要外挂知识库。热搜词里的“llm wiki知识库”、“karpathy llm wiki”就是在讨论如何构建和维护这类知识库。常见的做法是用向量数据库存储文档的 embedding当 Agent 需要某方面知识时先做相似度检索把最相关的片段拼到上下文里。这种方法叫 RAGRetrieval-Augmented Generation是目前最主流的长期记忆方案。6.3 MCP 生态的扩展MCP 的生态正在快速扩展。从热搜词可以看到Figma、蓝湖、Playwright、Blender、Burp 等工具都在接入 MCP。这意味着未来 Agent 可以调用的工具会越来越丰富从设计到开发到测试到安全覆盖整个工作流。如果你有自己的工具或服务可以考虑把它封装成 MCP Server。这样任何支持 MCP 的 Agent 都能直接调用你的服务不需要为每个框架单独适配。MCP Server 的开发并不复杂核心就是实现几个标准接口列出工具、调用工具、返回结果。6.4 可靠性工程Agent 的可靠性是一个系统工程。除了前面提到的参数调优和错误处理还需要考虑重试机制、降级策略、监控告警、成本控制。重试机制指的是当工具调用失败时自动重试几次。降级策略指的是当某个工具不可用时Agent 能否用其他方式完成任务。监控告警指的是实时跟踪 Agent 的成功率、延迟、token 消耗等指标。成本控制指的是设置 token 预算上限防止 Agent 陷入死循环烧掉大量费用。我在实际项目中的体会是Agent 开发的前 20% 时间花在让它跑起来后 80% 时间花在让它稳定运行。可靠性工程才是真正拉开差距的地方。7. 从能力全景到落地实践的个人体会回过头来看Agent 这个领域最迷人的地方在于它把 LLM 从“聊天工具”变成了“生产力工具”。但这个过程不是一蹴而就的需要你对能力边界有清晰的认知对技术细节有扎实的掌握对异常情况有充分的预案。我刚开始接触 Agent 的时候也走过弯路。最早我试图用一个超长的 prompt 让 LLM 完成所有事情结果发现它经常“忘记”中间的步骤。后来我学会了用 ReAct 循环把任务拆解每一步只做一件事成功率大幅提升。再后来我接触到 MCP发现工具的定义和复用变得前所未有的方便以前为每个项目重写工具代码的时间省下来了。如果你正在入门 Agent 开发我的建议是先不要急着学框架先想清楚你要解决什么问题。是自动查询数据是自动操作浏览器是自动生成报告想清楚目标之后再去选工具、学技术。技术是手段不是目的。最后分享一个我最近在用的调试技巧把 Agent 的每一步 Thought、Action、Observation 都打印出来然后用不同颜色标注。Thought 用蓝色Action 用绿色Observation 用黄色错误用红色。这样一眼就能看出 Agent 是在哪一步出了问题。这个习惯帮我节省了大量排查时间也让我对 ReAct 循环的理解越来越深。