AI Agent工具调用token消耗太多不准确怎么办?Anthropic官方的大模型工具使用(MPC)优化:tokens消耗降低98.7%

最近,在开发 AI Agent 的过程中,我越来越感受到工具集成带来的挑战。AI Agent 通常需要连接到多个外部系统,比如 Google Drive 或 Salesforce,但在传统方式下,每个工具的定义和调用结果都会占用大量上下文窗口空间,导致响应变慢、成本上升。我原本计划通过优化提示来缓解这个问题,但昨天(2025年11月4日)读到 Anthropic 发布的博客后,发现了一个更根本的解决思路:让 AI Agent 通过编写代码来调用工具,而不是直接进行工具调用

这种方法基于 MCP(Model Context Protocol,模型上下文协议)标准,能显著降低 token 消耗,同时保持系统的可扩展性。下面,我将结合原文逻辑,分享我的理解和改写版本,既作为这次技术洞察的记录,也为后续实验提供参考。


简答说一下,Anthropic 在 2024 年 11 月推出了 MCP,这是一个开放标准,旨在简化 AI Agent 与外部工具和数据的连接,避免传统自定义集成方式带来的碎片化问题。具体也可以参考此前DataLearnerAI的文章的介绍:https://www.datalearner.com/blog/1051732674414984

[TOC]

MCP 简介与当前痛点

MCP 是由 Anthropic 开发的开放标准,用于连接 AI Agent 与外部系统。传统上,为 AI Agent 对接每一个工具或数据源都需要定制化集成,这不仅导致碎片化,还会带来大量重复工作,难以构建真正可扩展的系统。MCP 则提供了一种通用协议:开发者只需在 AI Agent 中实现一次 MCP,就能接入整个生态的集成。自 2024 年 11 月推出以来,MCP 的采用速度非常快:社区已构建了数千个 MCP 服务器,主流编程语言都有相应的 SDK 支持,整个行业已将其视为连接 AI Agent 到工具和数据的默认标准。如今,开发者可以轻松构建连接数百甚至数千个工具的 AI Agent,这些工具分布在数十个 MCP 服务器上。然而,随着工具数量的增长,将所有工具定义预加载到上下文中,并通过上下文窗口传递中间结果,会显著拖慢 AI Agent 的速度并增加成本。

这篇博客探讨了如何通过代码执行环境,让 AI Agent 更高效地与 MCP 服务器交互,从而处理更多工具,同时使用更少的 token。

工具导致的 token 过度消耗

在大规模使用 MCP 扩展 AI Agent 时,我们通常有两种常见模式,这两种模式会显著增加 AI Agent 的成本和延迟:

  1. 工具定义过载上下文窗口
    第一种模式是通过工具定义的方式使用。大多数 MCP 客户端会将所有工具定义预先加载到模型上下文中,并使用直接工具调用的语法暴露给模型。例如,一个 Google Drive 工具的定义可能如下:
gdrive.getDocument
    Description: Retrieves a document from Google Drive
    Parameters:
        documentId (required, string): The ID of the document to retrieve
        fields (optional, string): Specific fields to return
    Returns: Document object with title, body content, metadata, permissions, etc.

另一个 Salesforce 工具定义如下:

salesforce.updateRecord
    Description: Updates a record in Salesforce
    Parameters:
        objectType (required, string): Type of Salesforce object (Lead, Contact, Account, etc.)
        recordId (required, string): The ID of the record to update
        data (required, object): Fields to update with their new values
    Returns: Updated record object with confirmation

尽管这种定义方式可以让大模型轻松理解和使用各种工具,大幅提升扩展能力,但这些描述本身会占用上下文窗口的空间,延长响应时间并提高成本。如果 AI Agent 连接了数千个工具,在处理请求之前就需要处理数十万 token 的定义信息。

  1. 中间工具结果消耗额外 token
    第二种模式是在执行过程中获取 MCP 工具的结果。大多数 MCP 客户端允许模型直接调用 MCP 工具。例如,你可能让 AI Agent “从 Google Drive 下载会议记录,并附加到 Salesforce 的潜在客户中”。模型会进行类似这样的调用:
TOOL CALL: gdrive.getDocument(documentId: "abc123")
→ returns "Discussed Q4 goals...\n[full transcript text]"
(loaded into model context)

TOOL CALL: salesforce.updateRecord(
    objectType: "SalesMeeting",
    recordId: "00Q5f000001abcXYZ",
    data: { "Notes": "Discussed Q4 goals...\n[full transcript text written out]" }
)
(model needs to write entire transcript into context again)

显然,这种方式会导致每个中间结果都必须通过模型传递。在这个例子中,整个会议记录内容实际上流动了两次。对于一个 2 小时的销售会议记录,这可能意味着额外处理 50,000 个 token。对于更大的文档或复杂数据结构,甚至可能超过上下文窗口限制,导致工作流中断。模型在工具调用之间复制数据时,也更容易出错。

MCP 客户端通常会将工具定义加载到模型的上下文窗口中,并协调消息循环,其中每个工具调用及其结果都会在操作之间通过模型传递。

通过 MCP 的代码执行提升上下文效率

随着代码执行环境在 AI Agent 中越来越常见,一个可行的解决方案是将 MCP 服务器呈现为代码 API,而不是直接工具调用。AI Agent 可以编写代码来与 MCP 服务器交互。这种方法解决了上述两个挑战:AI Agent 只需加载当前任务所需的工具,并在执行环境中处理数据,然后再将结果返回给模型。

一种实现方式是从连接的 MCP 服务器生成一个文件树,列出所有可用工具。以下是一个 TypeScript 示例:

servers
├── google-drive
│   ├── getDocument.ts
│   ├── ... (other tools)
│   └── index.ts
├── salesforce
│   ├── updateRecord.ts
│   ├── ... (other tools)
│   └── index.ts
└── ... (other servers)

每个工具对应一个文件,例如:

// ./servers/google-drive/getDocument.ts
import { callMCPTool } from "../../../client.js";

interface GetDocumentInput {
  documentId: string;
}

interface GetDocumentResponse {
  content: string;
}

/* Read a document from Google Drive */
export async function getDocument(input: GetDocumentInput): Promise<GetDocumentResponse> {
  return callMCPTool<GetDocumentResponse>('google_drive__get_document', input);
}

这样一来,前面提到的 Google Drive 到 Salesforce 的例子就可以改写成如下代码:

// Read transcript from Google Docs and add to Salesforce prospect
import * as gdrive from './servers/google-drive';
import * as salesforce from './servers/salesforce';

const transcript = (await gdrive.getDocument({ documentId: 'abc123' })).content;
await salesforce.updateRecord({
  objectType: 'SalesMeeting',
  recordId: '00Q5f000001abcXYZ',
  data: { Notes: transcript }
});

AI Agent 通过探索文件系统来发现工具:列出 ./servers/ 目录找到可用服务器(如 google-drivesalesforce),然后读取特定工具文件(如 getDocument.tsupdateRecord.ts)来理解接口。这样,AI Agent 只需加载当前任务所需的定义,从而将 token 使用量从 150,000 减少到 2,000,节省了 98.7% 的时间和成本

Cloudflare 也发布了类似的发现,将这种 MCP 的代码执行称为 “Code Mode”。其核心洞察是相同的:LLM 擅长编写代码,开发者应利用这一优势构建更高效的 AI Agent 与 MCP 服务器交互方式

MCP 代码执行的益处

MCP 的代码执行通过按需加载工具、在模型前过滤数据,并在单步中执行复杂逻辑,来更高效地使用上下文。此外,它还带来了安全性和状态管理方面的益处。

渐进式披露
模型擅长导航文件系统。将工具呈现为文件系统中的代码,使得模型可以按需读取定义,而不是预先全部加载。
另一种方式是在服务器中添加一个 search_tools 工具来查找相关定义。例如,在处理 Salesforce 服务器时,AI Agent 可以搜索 “salesforce”,仅加载所需的工具。在 search_tools 工具中包含 detail level 参数,让 AI Agent 选择细节级别(如仅名称、名称加描述,或完整定义带 schema),有助于节省上下文并高效查找工具。

上下文高效的工具结果
处理大型数据集时,AI Agent 可以在代码中过滤和转换结果,再返回给模型。考虑从 10,000 行电子表格中获取数据的例子:

// Without code execution - all rows flow through context
TOOL CALL: gdrive.getSheet(sheetId: 'abc123')
        → returns 10,000 rows in context to filter manually

// With code execution - filter in the execution environment
const allRows = await gdrive.getSheet({ sheetId: 'abc123' });
const pendingOrders = allRows.filter(row => 
  row["Status"] === 'pending'
);
console.log(`Found ${pendingOrders.length} pending orders`);
console.log(pendingOrders.slice(0, 5)); // Only log first 5 for review

AI Agent 只看到 5 行数据,而不是 10,000 行。类似的模式适用于聚合、跨数据源的连接,或提取特定字段,从而避免膨胀上下文窗口。

更强大且上下文高效的控制流
循环、条件和错误处理可以用熟悉的代码模式实现,而不是链式单个工具调用。例如,为 Slack 中的部署通知编写代码:

let found = false;
while (!found) {
  const messages = await slack.getChannelHistory({ channel: 'C123456' });
  found = messages.some(m => m.text.includes('deployment complete'));
  if (!found) await new Promise(r => setTimeout(r, 5000));
}
console.log('Deployment notification received');

这比在 AI Agent 循环中交替执行 MCP 工具调用和 sleep 命令更高效。
此外,能够编写条件树并执行,也节省了“首 token 时间”延迟:无需等待模型评估 if 语句,代码执行环境即可直接处理。

隐私保护操作
AI Agent 使用 MCP 代码执行时,中间结果默认保留在执行环境中。只有显式日志或返回的数据才会传给 AI Agent。这意味着不希望与模型共享的数据可以在工作流中流动,而不会进入模型上下文。
对于更敏感的工作负载,AI Agent harness 可以自动标记化敏感数据。例如,从电子表格导入客户联系信息到 Salesforce:

const sheet = await gdrive.getSheet({ sheetId: 'abc123' });
for (const row of sheet.rows) {
  await salesforce.updateRecord({
    objectType: 'Lead',
    recordId: row.salesforceId,
    data: { 
      Email: row.email,
      Phone: row.phone,
      Name: row.name
    }
  });
}
console.log(`Updated ${sheet.rows.length} leads`);

MCP 客户端会拦截数据,并在到达模型前标记化 PII:

// What the agent would see, if it logged the sheet.rows:
[
  { salesforceId: '00Q...', email: '[EMAIL_1]', phone: '[PHONE_1]', name: '[NAME_1]' },
  { salesforceId: '00Q...', email: '[EMAIL_2]', phone: '[PHONE_2]', name: '[NAME_2]' },
  ...
]

然后,在另一个 MCP 工具调用中,通过 MCP 客户端查找解标记化。真实的电子邮件、电话和姓名从 Google Sheets 流动到 Salesforce,但从未经过模型。这防止了 AI Agent 意外日志或处理敏感数据。你也可以用此方式定义确定性安全规则,选择数据流动的来源和去向。

状态持久化和技能
代码执行结合文件系统访问,让 AI Agent 在操作之间维护状态。AI Agent 可以将中间结果写入文件,实现恢复工作和跟踪进度:

const leads = await salesforce.query({ 
  query: 'SELECT Id, Email FROM Lead LIMIT 1000' 
});
const csvData = leads.map(l => `${l.Id},${l.Email}`).join('\n');
await fs.writeFile('./workspace/leads.csv', csvData);

// Later execution picks up where it left off
const saved = await fs.readFile('./workspace/leads.csv', 'utf-8');

AI Agent 还能将自己的代码持久化为可复用函数。一旦为任务开发出有效代码,它可以保存以备后用:

// In ./skills/save-sheet-as-csv.ts
import * as gdrive from './servers/google-drive';
export async function saveSheetAsCsv(sheetId: string) {
  const data = await gdrive.getSheet({ sheetId });
  const csv = data.map(row => row.join(',')).join('\n');
  await fs.writeFile(`./workspace/sheet-${sheetId}.csv`, csv);
  return `./workspace/sheet-${sheetId}.csv`;
}

// Later, in any agent execution:
import { saveSheetAsCsv } from './skills/save-sheet-as-csv';
const csvPath = await saveSheetAsCsv('abc123');

这与 “Skills” 概念紧密相关:Skills 是模型用于提升特定任务性能的可复用指令、脚本和资源文件夹。将 SKILL.md 文件添加到这些保存函数中,即可创建结构化技能,供模型引用使用。随着时间的推移,这让 AI Agent 能够构建一个高级能力工具箱,逐步演进其所需支架。

Skills也是Anthropic近期提出的工具使用方法,相比较MCP解决大模型工具访问的问题,Skills重点关注大模型的工具使用问题,具体也可以参考此前的DataLearnerAI的文章的介绍:https://www.datalearner.com/blog/1051760674512378

需要注意的是,代码执行也引入了自身的复杂性。运行 AI Agent 生成的代码需要安全的执行环境,包括沙箱、资源限制和监控。这些基础设施需求增加了运营开销和安全考虑,而直接工具调用则避免了这些。因此,代码执行带来的益处——降低 token 成本、更低延迟、更好的工具组合能力——需要与实现成本进行权衡

总结

MCP 为 AI Agent 连接众多工具和系统提供了基础协议。但一旦连接过多服务器,工具定义和结果会消耗过多 token,降低 AI Agent 效率。
虽然这些问题——上下文管理、工具组合、状态持久化——感觉新颖,但软件工程领域已有成熟的解决方案。代码执行将这些模式应用到 AI Agent 中,让它们能够用熟悉的编程结构更高效地与 MCP 服务器交互。如果你实现了这种方法,建议与 MCP 社区分享你的发现。

欢迎关注 DataLearner 官方微信,获得最新 AI 技术推送

DataLearner 官方微信二维码