Grok Build · 工具系统 —— Agent 的双手 章节摘要:前三章我们看清了 Agent 如何「思考」——从循环到采样。本章转向 Agent 如何「动手」。一个只会说话的模型算不上助手,真正的助手要能读文件、跑命令、改代码、搜索资料。这些能力在 Grok Build 里被组织成一个工具系统:每个能力是一个「工具」,有明确的接口、参数、返回值,模型通过结构化的方式决定何时调用、调用哪个、传什么参数。本章会从工具系统的契约(Tool trait)讲起,拆解那个让不同工具能塞进同一个注册表的对象安全设计、流式执行的不变量、内置工具的全景、工具调用的完整生命周期、资源注入模式,最后给出写一个自定义工具的思路。理解工具系统,你就理解了 Agent 「能干活」的全部秘密。
章节摘要:前三章我们看清了 Agent 如何「思考」——从循环到采样。本章转向 Agent 如何「动手」。一个只会说话的模型算不上助手,真正的助手要能读文件、跑命令、改代码、搜索资料。这些能力在 Grok Build 里被组织成一个工具系统:每个能力是一个「工具」,有明确的接口、参数、返回值,模型通过结构化的方式决定何时调用、调用哪个、传什么参数。本章会从工具系统的契约(Tool trait)讲起,拆解那个让不同工具能塞进同一个注册表的对象安全设计、流式执行的不变量、内置工具的全景、工具调用的完整生命周期、资源注入模式,最后给出写一个自定义工具的思路。理解工具系统,你就理解了 Agent 「能干活」的全部秘密。
阅读完本章,你应当能够:
整章逻辑可浓缩为一句话:工具系统用一个统一契约把「读文件、跑命令、改代码」等异构能力组织起来,让模型能结构化地调用它们,把「会聊天」变成「会干活」。
讲清 Rust 对象安全的难题,以及 Grok Build 如何用「泛型 Tool trait + 对象安全 ToolDyn + 毯子 impl」破解——工具作者写强类型代码,框架做动态分发。
工具执行不是返回单个值,而是返回一条流:零或多个 Progress(进度),最后有且仅有一个 Terminal(最终结果)。本节讲清这个不变量与它的意义。
Grok Build 内置 50+ 工具,分 GrokBuild、Codex、OpenCode 等命名空间。本节讲清注册表如何编译期组装,以及 apply_patch 等移植工具的来历。
从模型生成 tool_call 到结果回填历史的完整流程,包括鉴权介入点、流式回显、结果标准化。
工具不各自持有终端、文件系统等资源,而是从框架的共享资源池按需取用。本节讲清这个模式的设计与好处。
虽然 Grok Build 不接受外部贡献,但通过 out-of-tree tool pack 机制,你可以在自己的 fork 里注册自定义工具。本节给出实现思路。
本章遵循「理解契约 → 认识流式 → 看清库存 → 走完生命周期 → 理解资源 → 动手扩展」的认知路径:
契约 (01) ──Tool trait,工具系统的接口根基 │ ▼ ToolStream (02) ──执行的统一形态 │ ▼ 注册表 (03) ──内置工具有哪些 │ ▼ 生命周期 (04) ──一次调用的完整流程 │ ▼ 资源模式 (05) ──工具如何拿到终端、FS 等 │ ▼ 自定义 (06) ──如何加自己的工具 │ ▼ 第 6 章:扩展生态(MCP/插件/Skills/沙箱)
每一节都为下一节铺垫:不理解契约,ToolStream 与注册表就无从谈起;不认识流式,生命周期的「实时回显」就缺乏机制;不看清库存,生命周期里的「按名查找」就抽象;不走过生命周期,资源注入的时机就模糊;不理解资源模式,自定义工具就无从下手。
前置知识:
本章为后续章节奠定的基础:
若希望进一步了解 Rust 的对象安全与动态分发,可参考 Rust Reference 的 Trait Object 部分,以及 serde derive 与 schemars(JSON Schema 生成)的文档——它们是理解工具参数如何自动生成 Schema的关键。