了解模型如何请求工具、应用程序如何安全地执行它们,以及如何为生产级 AI 系统设计有边界、可观测的操作。

由 The Forward Deployed 编辑团队审阅

模型本身只能生成文本。它无法查询今天的价格、检索数据库或发送电子邮件。工具使用(也称为函数调用)正是将文本生成器转变为能够与外部世界交互的东西的关键:你描述允许它调用的函数,模型决定何时调用以及使用什么参数。它是让助手真正“做事”的模块,也是下一页(Agent)构建循环的基础。

为什么这就是这项工作的核心——以及信任边界在哪里

工具使用是让 LLM 应用不再只是一个聊天机器人、开始真正有用的方式:它可以检索、计算、查询记录、提交工单。但请注意上面定义中的边界,因为它就是整个安全故事的关键。模型从不自己执行任何东西。它只是发出请求,而由你的代码决定是否以及如何运行。这个边界就是你执行一切管控的地方:验证参数、检查权限,并对任何不可逆的操作要求人工介入。理解工具使用的前沿部署工程师会把模型的工具请求当作需要检查的不可信输入,而不是必须服从的命令。

在继续阅读之前:假设你给助手一个 send_email 工具。在模型请求调用它和邮件真正发出之间,必须有什么环节?为什么“什么都不需要,这就是工具的意义”是危险的答案?

在请求和发送之间必须有一道护栏:验证参数,并且对于像发送邮件这样不可逆的操作,设置人工检查点。“什么都不需要”是危险的,因为模型是概率性的。它最终会请求把错误的邮件发给错误的人,而工具边界是在它演变成现实世界事件之前唯一能拦截它的地方。

完整的往返流程

  • 描述工具。每个工具都有一个名称、一段清晰的描述(模型会阅读它来决定何时使用),以及一个参数模式(schema)。
  • 模型请求一次调用。根据对话内容,模型返回一个结构化的工具调用(工具名称和参数),而不是最终答案。
  • 你的代码验证并执行。根据模式和你的规则检查参数,执行权限控制,对于任何不可逆的操作,暂停等待批准。然后再运行它。
  • 把结果反馈回去。将工具的输出返回给模型,模型继续运行,可能会调用另一个工具或生成最终答案。

一个问题可能会多次经过这个循环。当它自主地朝着某个目标循环运行时,你就构建了一个 Agent。那就是下一页的内容。

一个工具定义,以及围绕它的关卡

下面是

send_email

工具(来自上面的问题),以如下形状定义

Anthropic's tool-use API

需要:一个名称、一段供模型读取的描述,以及参数的 JSON Schema。(仅为示例。)

{
  "name": "send_email",
  "description": "Send an email from the support mailbox. Use only when the user has explicitly asked for an email to be sent and has confirmed the recipient. Sending is irreversible.",
  "input_schema": {
    "type": "object",
    "properties": {
      "to":      { "type": "string", "description": "Recipient address. Must be a contact on this account." },
      "subject": { "type": "string", "maxLength": 120 },
      "body":    { "type": "string", "description": "Plain-text body. No pricing or legal commitments." }
    },
    "required": ["to", "subject", "body"]
  }
}

注意,描述中包含了运行规则(“仅当用户明确要求时”、“已确认收件人”)。这段文字是模型判断何时使用该工具的唯一指引,因此工具描述需要像提示词一样精心设计(下文会详述)。Schema 是可被机器校验的那一半,而你的代码——绝不是模型——会将每个提议的调用包裹在闸门中:

# the gate every tool call passes through (illustrative)
call = response.tool_use                       # model proposes: name + args
if not validates(call.args, TOOLS[call.name].input_schema):
    return tool_result(error="malformed arguments")  # reject; the model can retry
if not permitted(current_user, call.name, call.args):
    return tool_result(error="not permitted")  # the user's authority, never the model's
if TOOLS[call.name].irreversible:
    await_human_approval(call)                 # checkpoint before send_email fires
result = TOOLS[call.name].run(call.args)
return tool_result(result)                     # feed back; the model continues

在模型的请求与实际发送之间有三道检查,每一道都针对一种不同的失败:Schema 校验捕获格式错误的参数,权限检查将调用限定在该用户被允许的范围内,而不可逆性闸门会扣留任何具有现实世界后果的操作,直到有人批准。只有到那时,工具才会运行,结果才会返回。

面试官会考察什么

  • 工具描述就是提示词。 模型根据工具的描述来决定是否调用它,因此模糊的描述意味着模型会用错工具或跳过正确的工具。描述是需要精心设计的。
  • 参数不可信。 模型可能请求带有格式错误或危险参数的调用(没有过滤条件的删除、发往错误地址的邮件)。要像对待用户输入一样严格校验它们,因为从功能上讲它们就是用户输入。
  • 操作需要设界。 可逆、低成本的工具可以自动运行;不可逆或影响范围大的操作需要人工检查点。防护栏页面中的操作防护栏正是用在这里的。

差 / 好 / 优秀——“助手如何查询信息或执行操作?”

差——“模型调用它需要的 API。” 这种说法把模型当作执行者,既在技术上不正确,也是安全漏洞。这会让面试官认为你没有用工具构建过系统。

好——“我定义带 Schema 的函数;模型请求调用,我的代码执行它。” 机制正确,扎实。不足之处:没有提到校验模型请求的参数,也没有提到对无需人工介入即可运行的操作设界。

优秀——“我提供带有清晰描述和参数 Schema 的工具;模型返回结构化的调用,而我的代码将该调用视为不可信输入——校验参数、执行用户的权限、自动运行可逆的工具,并将不可逆的操作置于人工检查点之后。工具边界就是安全所在。” 你描述了完整的往返流程,并把防护栏放在了边界上。

面试中要带上的要点

当一个设计让系统能够执行操作时,请将工具使用描述为信任边界:模型发起请求,你的代码进行校验并决策,不可逆的操作需要人工介入。将模型的工具调用视为你的代码必须校验的不可信输入,正是区分一个安全的执行系统与一个随时可能给错误客户发邮件的演示的关键。

下一篇: Agent 与编排。当你让模型循环使用工具以达成目标时会发生什么,以及什么时候不该这样做。

下一篇:Agent 与编排