工具、动作与环境。
一个没有工具的模型只能自言自语地思考。工具是智能体能做任何事情的全部原因——而环境是这些工具触及、并可能损坏的一切。本篇把三件事讲精确:工具在传输层上究竟是什么、一个工具定义如何比你的提示词更能塑造模型的行为、以及为什么通常是环境(而非模型)才是智能体变得危险的地方。
工具是模型被允许去请求调用的一个函数。
剥去神秘感:工具就是你代码库里一个普通的函数,外加一段模型能读的描述。模型永远不能自己运行它。模型输出一个运行它的请求;你的外壳程序决定是否以及如何满足那个请求。一个工具恰好有三个部分:
- 一个名称,模型用它来指代这个工具(
search_orders)。 - 一个 schema:它接受的输入,带类型,这样模型才知道该产生什么参数(
{order_id: string})。 - 一段自然语言描述:它做什么、何时使用、返回什么,以及关键的——它不得用于什么。
# What the model is shown (the contract): { "name": "issue_refund", "description": "Refund a paid order. Use ONLY after verifying the" " order exists and was not already refunded. Max $200;" " above that, escalate to a human instead.", "input_schema": { "order_id": "string", "amount_usd": "number" } } # What the harness actually runs when the model asks for it: def issue_refund(order_id, amount_usd): if amount_usd > 200: # enforce the limit in CODE, raise RefundTooLarge() # not just in the description return payments.refund(order_id, amount_usd)
最重要的单一习惯就在最后那条注释里。描述把规则告诉模型;函数强制执行规则。模型有时会忽略描述——对一个概率系统而言,描述是一个建议。代码不是建议。绝不要依赖模型遵守一个你本可以在工具自身里强制执行的约束。
两类动作,以及为什么这个区分就是一切。
智能体能调用的每个工具都落入两类之一,而几乎所有智能体安全问题都可以归结为你面对的是哪一类:
- 读动作(传感器)。它们观察环境而不改变它:
search_web、read_file、query_database(一条 SELECT)、get_weather。一个错误读动作的最坏情况是浪费一轮和一个误导性的观察。可恢复。 - 写动作(执行器)。它们改变环境:
send_email、delete_file、execute_trade、deploy。一个错误写动作的最坏情况是一个已经发生了的真实世界后果。往往不可廉价恢复。
这直接映射到上一篇的自主性阶梯:读动作通常能在高自主性下运行,因为它们可逆;写动作恰恰是那些应该藏在批准闸门或硬性代码上限之后的。由此得出一条实用设计规则:只给智能体任务真正需要的最小写工具集,并优先选择窄工具而非宽工具。refund_order(id) 远比 run_sql(query) 安全——后者什么都能干,包括你从未打算的事,而你无法对一个能力是"任意"的工具强制执行策略。
窄工具原则再表述一遍:你暴露的每个工具,都是智能体能对世界做的一个动词。一个由 get_balance、list_transactions、flag_for_review 组成的工具箱,定义的是一个无论怎么被提示或攻击都从根本上无法转移资金的智能体。一个单独的 execute_banking_operation 工具,定义的是一个能做银行职员能做的任何事的智能体。工具箱就是智能体的能力边界。像设计一个权限模型那样设计它,因为它就是。
工具描述就是提示词工程——而且通常是杠杆最高的那种。
新手花数小时调系统提示词,却忽视工具描述。这是本末倒置。工具描述是模型关于何时以及如何使用一项能力的唯一信息,而且它正是在决策作出的那一刻被读取的。一段含糊的描述会产生一个任何系统提示词都无法完全修复的失常智能体。
具体来说,同一个函数的这两段描述之间的差别,就是一个可靠智能体和一个不稳定智能体之间的差别:
WEAK: "Searches the knowledge base."
→ Model calls it with vague queries, on the wrong
turns, and over-trusts whatever comes back.
STRONG: "Full-text search over the product help-center
articles ONLY (not pricing, not account data).
Use when the user asks how a feature works. Pass
a focused query of 2-6 keywords, not a sentence.
Returns up to 5 article snippets ranked by
relevance; snippets may be partial — open the
full article before quoting policy."
→ Model knows scope, trigger, input shape, and
the failure mode of the result.
强版本编码了范围(它不覆盖什么)、触发条件(何时去用它)、输入形态(好的参数长什么样)、以及结果注意事项(不要过度信任一个片段)。其中每一项,否则都会成为你当作"模型 bug"去追查的一个行为。它通常不是模型 bug;它是一个规格不足的工具。
环境:智能体真正变危险的地方。
环境是工具所能触及的一切:文件系统、数据库、客户的账户、公共互联网、机器人的周遭。人们很容易执着于模型,而忘了模型永远只是提议——环境才是后果变为真实的地方。环境的三个属性决定了一个在其他方面完全相同的智能体有多危险:
- 可逆性。一个错误动作能被廉价撤销吗?一个 git 工作树高度可逆(你可以 reset)。一封已发出的邮件、一张已扣款的卡、一张被删的生产表、一个物理位移:不可逆。同一个智能体在沙箱里安全,在生产中危险,仅仅因为环境的可逆性。
- 可观测性。工具结果会告诉智能体所发生事情的真相吗?如果
deploy()返回"ok"但部署实际上半途失败了,智能体的下一个决策就建立在一个谎言之上。智能体的好坏只取决于它的观察;一个嘈杂或具欺骗性的环境会破坏循环的反馈。 - 对抗性。智能体读到的内容会包含针对智能体的指令吗?一个浏览网页或阅读用户提交工单的智能体,读的是攻击者可能写过的文本。这就是提示词注入(prompt injection),它之所以存在,是因为智能体的"观察"和它的"指令"是同一个通道——上下文窗口里的文本。(安全那一节会深入讲;概念性的要点属于这里:智能体的环境也是一个攻击面。)
能预防大多数智能体灾难的思维模型:智能体的危险不是模型的属性——而是模型与环境相乘的属性。完全相同的提示词和权重,当工具是对沙箱只读时是一个无害的研究助手,而当某个工具能对一个生产账户电汇资金时就是一个严重的负债。当你评估"这个智能体安全吗?"时,你真正问的是"如果模型错了或被操纵了,这个工具箱能对这个环境做的最坏的事是什么?"用工具箱和环境去回答那个问题,永远不要单凭模型。