「工具税」:用最小权限 MCP 在花钱之前砍掉 Agent 的 Token 账单
💡 工具推荐:AI Token 计数器、API 密钥轮换、API 限流计算器
多数 AI 团队在排查成本时,都会先看模型单价、缓存命中率、上下文长度,很少有人去看提示词里那份「工具菜单」。Okta 的 AI 安全负责人 Harish Peri 与技术、数据与智能负责人 Jenna Cline 在官方 newsroom 里给这份菜单带来的成本起了个名字——工具税(tool tax)。每一轮对话,MCP 服务器暴露的每一个工具都会以 schema、名称、描述与参数的形式进入模型提示词,无论模型最终是否调用它。它的特点是不以「被拒绝的调用」或「安全事件」的形式出现,而是以一张很难解释清楚的 token 账单出现。
一、把「工具税」定义清楚
Okta 开篇的观察很朴素:每个 AI Agent 的模型调用里,都附带一份它可能用到的全部工具菜单,哪怕其中大部分它永远不会碰。无论 Agent 连接的是 Google Workspace、Slack,还是一个多年累积上百个工具的内部 MCP 服务器,情况都一样。每个被暴露的工具都会以 schema、名称、描述与参数的形式渲染进模型的提示词,并且每一轮都发生一次。你要为模型推理这些工具付费,无论它是否调用。Okta 把这个成本称为工具税,并指出它之所以长期隐形,是因为它既不出现在被拒绝的调用里,也不出现在安全事件里——它出现在一张难以解释的 token 账单上。
# The tool tax, in one function. Every exposed tool costs tokens on
# every turn, because its schema rides along in the prompt.
def tool_schema_tokens(tools):
"""Roughly: each tool contributes a name, description and parameter
schema -- every turn, whether or not it is ever called."""
return sum(len(t.name) + len(t.description) + schema_size(t.params)
for t in tools)
def monthly_tool_tax(tools, turns_per_conversation, conversations):
return (tool_schema_tokens(tools)
* turns_per_conversation
* conversations)
# Okta's point: this line does not appear as a rejected call or a
# security incident. It appears as a token bill that is hard to explain.先缩清单,再谈限流
二、为什么事后拒绝救不回任何 token
很多人第一反应是「加一层校验,不合法就不让它调用」。Okta 指出这条路省不下钱:拒绝一次未授权的调用并不能退token,因为在模型尝试任何动作之前,那些 token 已经在提示词阶段花掉了。更麻烦的是善后成本——一旦 Agent 已经在使用一个它本不该访问的工具,回滚本身就是一个项目:需要有人发现、调查、撤销权限。而这期间 token 照花不误。Okta 的结论因此是:在上游就把范围收窄,意味着事后根本没有东西需要追回。
# The failure mode. Rejecting an unauthorised call after the fact
# does not refund anything: the schema was already in the prompt
# before the model tried anything.
def post_hoc_rejection_flow(agent, tool_call):
tokens_already_spent = True # paid in the prompt phase
log_incident(tool_call) # someone must investigate
revoke_access(tool_call.tool) # a project of its own
return {"refund": None if tokens_already_spent else "n/a",
"tokens_recovered": 0}
# Okta's conclusion: scoping upstream means there is nothing to claw back.三、在身份层收窄,而不是在网关层罚款
Okta 的机制是在 Agent 连接 MCP 服务器的那一刻裁剪工具列表:管理员在 Okta 控制台里配置某个身份被授权使用哪些工具,Okta 只返回裁剪后的集合,而不是服务器暴露的全部内容。这带来三个连锁效果:更短的列表在每一轮被注入提示词,于是在 Agent 尝试调用之前就降低了每轮支出;未授权的工具根本不在模型能看到的列表里;并且在任何工具真正执行之前,范围会被再次校验。值得注意的是第三点——这不是把安全换成省钱,而是同一套授权数据同时承担了「缩小提示词」和「缩小爆炸半径」两个作用。
# Scoping upstream, at the identity layer. The admin configures which
# tools a given identity is entitled to; Okta returns only the scoped
# set rather than everything the server exposes.
def tools_returned_to_model(identity, mcp_server):
catalogue = mcp_server.exposed_tools()
entitled = identity.entitlements_for(mcp_server)
return [t for t in catalogue if t.name in entitled]
# Consequences of the shorter list:
# 1. fewer schema tokens per turn, before any call is attempted
# 2. unauthorised tools are absent from what the model can even see
# 3. scope is checked again at runtime before any call executesschema 成本随工具数量近似线性变化
四、数字与它必须附带的前提
Okta 给出的量化结论是:在覆盖多种真实权限分布的内部建模中,某些场景把可见工具数削减了 90% 以上,工具 schema 成本大致同比例下降。这里必须原样带上它的前提,否则数字没有意义。这些数字全部来自 Okta 内部建模,只使用 Okta 产品数据与公开厂商文档,没有使用任何客户数据;建模设定了一个接入企业工具目录的 MCP 客户端,定义了几个代表性用户分群(helpdesk 只读、helpdesk 操作员、应用管理员、品牌与邮件管理员、超级管理员),并按各分群假设的月流量占比加权;由于每个工具都会在每一轮向提示词贡献名称、描述与参数 schema,schema 的 token 成本与工具数量近似线性,因此文章报告的是百分比而不是金额,实际结果会随工具目录、权限分布与模型选择而变化。
# What the internal modeling found, with its caveats attached. The
# figures come from Okta internal modeling on product data and public
# vendor documentation only -- no customer data. They are reported as
# percentages, not dollars, because absolute figures vary by
# deployment.
MODELING = {
"reduction_reported_as": "percentages, not dollars",
"user_segments": ["helpdesk read-only", "helpdesk operator",
"app admin", "brand and email admin", "super admin"],
"weighting": "assumed share of monthly traffic per segment",
"headline": "some scenarios cut visible tools by more than 90%",
}
def schema_cost_reduction(tool_count_before, tool_count_after):
ratio = 1 - tool_count_after / tool_count_before
return {"tool_count_reduction": ratio,
"schema_cost_reduction_estimate": ratio} # near-linear五、网关与身份层:分工,而不是竞争
Okta 专门用一节讲清楚它和网关的关系:网关按 key、团队或分组来限制支出,这是它有数据能支持的粒度;对路由和限流来说,网关是正确的层。但按组的信息无法告诉它某一个具体 Agent、或 Agent 背后那个人,究竟被授权触碰什么。所以网关只能在一笔支出变贵之后限制它,无法阻止它变贵——而「谁拥有网关,谁就默认成了 token 警察」,有人要设限额、要在团队反弹时辩护、要在用户中途撞墙时做决定。身份层的能力在于粒度:用按用户与按 Agent 的授权,而不是分组关系来过滤工具列表。Okta 的总结很精炼——网关计量流过去的东西,身份层减少需要计量的东西。
# Gateway versus identity layer: complementary, different grains.
# A gateway meters what already happened. An identity layer shrinks
# what there is to meter.
LAYERS = {
"gateway": {"grain": "key / team / group",
"job": "rate-limit, route, cap spend after the fact"},
"identity": {"grain": "per user, per agent",
"job": "decide which tools exist in the prompt at all"},
}
def who_owns_token_policing(has_identity_layer):
return "nobody, ideally" if has_identity_layer else "whoever owns the gateway"事后拒绝一次调用,省不回任何 token
六、落地顺序:先算账,再收窄,最后才限流
如果要把这套思路用在真实环境里,顺序很重要。第一步是算账:用工具数量乘以每轮 schema 成本,再乘以会话轮数与会话量,把「工具税」变成一个可以摆上会议室的数字——很多团队会在这一步发现这笔钱比想象中大得多。第二步是收窄:按身份把工具清单裁剪到真正被授权的子集,并把范围校验放到运行时调用之前,而不是之后。第三步才是限流:在前两步完成之后,网关的支出上限才会从「唯一手段」变成「兜底手段」,也不再需要网关团队去当 token 警察。这套顺序的价值在于:它把一件成本问题,变成了一个你已经拥有数据的权限问题。
📌 常见问题 FAQ
什么是「工具税」(tool tax)?
Okta 的定义是:AI Agent 的每一次模型调用里,都包含一份它可能用到的全部工具菜单——包括那些它永远不会碰的工具。每个 MCP 服务器暴露的工具都会以 schema、名称、描述与参数的形式被渲染进提示词,而且每一轮都会发生。你必须付费让模型去推理这些工具,无论它是否真的调用。
为什么事后拒绝一次工具调用没有用?
Okta 的解释是:拒绝一次未授权的工具调用,并不能把那部分 token 要回来——它们已经在提示词阶段、在模型尝试任何事情之前就花掉了。而且一旦 Agent 已经在使用一个它不该访问的工具,事后回收本身就是一个项目:需要有人发现、调查并撤销权限。token 无论如何都已经花掉了。
Okta 的做法具体是什么?
Okta 在 Agent 连接 MCP 服务器的那个点上裁剪工具列表:管理员在 Okta 控制台里配置某个身份被授权使用哪些工具,Okta 只返回被裁剪后的集合,而不是服务器暴露的全部工具。更短的列表在每一轮注入提示词,因此在 Agent 尝试调用之前就降低了每轮的 token 支出。未授权的工具根本不在模型看到的列表里,并且在任何工具调用真正执行之前会再次做一次范围校验。
建模得到的数字是什么,有哪些前提?
Okta 称在覆盖多种真实权限分布的内部建模中,部分场景把可见工具数削减了 90% 以上,而工具 schema 成本大致同比例下降。前提必须说清楚:这些数字来自 Okta 内部建模,只使用 Okta 产品数据与公开厂商文档,未使用任何客户数据;建模定义了代表性用户分群(helpdesk 只读、helpdesk 操作员、应用管理员、品牌与邮件管理员、超级管理员),并按各分群假设的月流量占比加权;因为每个工具都会在每一轮向提示词贡献名称、描述与参数 schema,schema 的 token 成本与工具数量近似线性,所以文章用百分比而非具体金额来报告降幅。
这和 API 网关的职责冲突吗?
Okta 的立场是不冲突,而是分工不同。网关按 key、团队或分组来限制支出,这是它能拿到的最细粒度数据;对路由和限流来说,网关是正确的层级。但网关计量的是已经发生的事情——输入 token、输出 token、花掉的钱,它能在一次决策变贵之后限制损失,却无法阻止决策本身变贵。身份层有能力做到后者:用按用户、按 Agent 的授权而不是分组成员关系来过滤工具列表,从而把「需要被计量的东西」先变小。
🔧 推荐工具
📚 参考资料
- Okta Newsroom — Fewer tools, fewer tokens: How Okta cuts agent tool-selection costs before they happen
- Okta — Okta for AI Agents: Reduce Token Spend & Tool Costs (datasheet)
- Okta — Blueprint for the secure agentic enterprise
- Okta Newsroom — Oktane 2026: AI agents are in the enterprise, now what? (2026-09-25)