
《Agent Runtime 工程化》第四章 工具系统设计:4.6 权限预览
高风险工具执行前,应给用户看到 preview。 写文件要给 diff preview;执行命令要给 command preview;联网请求要给域名、方法、数据范围;安装依赖要给包名、版本、lockfile 影响;数据库操作要给目标库、表、迁移摘要。 图 42:工具系统的风险矩阵。风险来自能力、参

高风险工具执行前,应给用户看到 preview。 写文件要给 diff preview;执行命令要给 command preview;联网请求要给域名、方法、数据范围;安装依赖要给包名、版本、lockfile 影响;数据库操作要给目标库、表、迁移摘要。 图 42:工具系统的风险矩阵。风险来自能力、参

工具失败不应只有 error: string。至少分为: 类型 例子 Runtime 行为 INVALIDARGUMENTS 参数缺字段、类型错 反馈模型重新调用 NOTFOUND 文件不存在 提示可选路径或要求搜索 PERMISSIONDENIED 用户拒绝或策略拒绝 停止或让模型寻找低风险方案

并行工具调用可以提升效率,但也会放大风险。原则很简单:只读工具可以并行,写入工具谨慎串行,高风险工具必须等待审批结果。 并行前检查三件事: 1. 工具是否只读; 2. 是否访问同一资源; 3. 输出是否会共同挤占上下文预算。 例如,同时读三个文件通常安全;同时修改同一个文件不安全;一个 search

工具一旦进入 trace 和 eval,就不能随意改语义。比如 readfile 原来默认返回全文,后来默认只返回前 200 行;这会影响模型行为,也会影响 replay 结果。 版本演进的策略: 工具名稳定时,小改动写入 version 和 changelog; 输入 schema 增加可选字段通

TypeScript 生态里,Zod 常用于运行时校验;模型和协议层常使用 JSON Schema。工程上可以用 Zod 编写工具输入,再转换为 JSON Schema 提供给模型或 MCP。 注意两点。 第一,schema 要表达约束,而不是只写类型。string 太宽,path、command、
Tool Registry 不是一个 Map<string, Function。它至少保存以下信息: 这些字段不是装饰。description 会影响模型是否选择工具;inputSchema 负责校验;riskLevel 进入权限审批;timeoutMs 进入执行器;outputPolicy 进入上

这一章开始给工具'上户口':它们不能只是函数列表。 在 demo 里,工具是几个函数。在生产 Agent Runtime 里,工具是一套能力治理系统。它既要让模型知道'能做什么',也要让 runtime 知道'什么能做、什么不能做、怎么做、失败了算什么、谁批准过、结果能不能进上下文'。

Agent 能根据用户请求读文件、总结、继续追问或停止。非法工具参数不会让程序崩溃;工具失败会变成模型可理解的 observation;超过最大步数会停止并给出原因。完成这一章,你已经有了 runtime 的胚胎。

写一个 miniagent: 支持 listfiles; 支持 readfile; 支持 shellreadonly; 支持最多 10 轮工具调用; 支持流式输出 runtime event; 非法 tool args 能被拦截并反馈给模型; 每次 run 输出一份简单 JSON trace。 任务

第一类失败是非法参数。模型传了不存在的路径、错误类型、缺字段。处理方式是 schema 校验 + observation 反馈。 第二类失败是工具不存在。模型调用了没注册的工具。处理方式是返回 UNKNOWNTOOL,并把可用工具列表简短提示给模型。 第三类失败是输出过大。处理方式是截断、摘要、引用

第三章 最小 Agent Loop:3.6 一个 miniagent 的目录 建议项目结构: 不要急着做框架。先让每个模块的职责一眼能看懂。等你知道重复在哪里,再抽象。

本阶段建议只实现三个工具。 listfiles:列目录。只读,但要限制在 workspace 内。 readfile:读文件。只读,但要限制大小和行数。 shellreadonly:执行只读 shell 命令。只允许白名单命令,例如 pwd、ls、find、rg、cat、sed、wc。不要在入门阶段

没有最大步数的 Agent Loop 是一个事故邀请函。模型可能重复读同一个文件,也可能在工具失败后不断尝试相同参数。最小 runtime 必须有 maxSteps。 但 maxSteps 只是硬刹车,还需要软停止条件: 模型返回 final answer; 模型没有工具调用; 连续 N 次工具调用

一次工具调用 roundtrip 包含六步: 1. Runtime 把工具描述和上下文发给模型。 2. 模型返回 tool call。 3. Runtime 校验工具名和参数。 4. Runtime 判断是否允许执行。 5. Tool Executor 执行工具,得到 result。 6. Runt

工具 schema 有两个读者。模型用它决定怎么调用工具,runtime 用它判断调用是否合法。 以 readfile 为例: 不要把 schema 发给模型后就放心。模型返回的参数必须再次校验。校验失败不该让程序崩溃,应当变成一条 observation: 这很关键。工具参数错了,并不总是任务失败
最小 runtime 需要四类接口。 第一是 LLM Client。它隐藏不同模型供应商的请求格式,向 runtime 返回统一的 ModelResponse。 第二是 Message Store。它保存用户消息、模型消息、工具调用和工具结果。 第三是 Tool Registry。它告诉模型有哪些工

现在可以动手了:把模型、工具和观察结果接成一个受控循环。 最小 Agent Loop 是本书第一座桥。过了这座桥,你就不再只是调用一次模型,而是在写一个会观察、会行动、会停止的运行系统。这个系统可以非常小,但边界必须正确。

你不只是会 await,而是能解释异步任务如何取消、如何防泄漏、如何处理流式输出、如何把长日志变成模型可用的观察结果。做到这里,才有资格写第三章的最小 Agent Loop。

实现一个可取消的命令执行器: 支持 cwd; 支持 stdout/stderr 流式事件; 支持 timeout; 支持 AbortSignal; 支持最大输出限制; 返回 exit code、signal、duration; 中断后清理子进程。 用三个命令测试它:

很多系统把重试当作可靠性的同义词。对 Agent Runtime 来说,重试之前先问一句:上一次有没有留下副作用? 如果模型请求超时,重试通常安全。如果读文件失败,重试也通常安全。如果写文件执行到一半,重试可能覆盖用户改动。如果 npm install 被中断,重试前要检查 lockfile 和目录