
《Agent Runtime 工程化》第七章 权限与安全边界:导读
能力越大,边界越要清楚。本章谈权限和安全。 Agent 的能力来自工具,风险也来自工具。一个不会调用工具的模型,最多说错话;一个能执行命令、写文件、联网、访问数据库的 Agent,可能造成真实损失。Runtime 的安全目标不是把 Agent 绑住,而是让它在明确边界内做事;越过边界时,停下来请人确

能力越大,边界越要清楚。本章谈权限和安全。 Agent 的能力来自工具,风险也来自工具。一个不会调用工具的模型,最多说错话;一个能执行命令、写文件、联网、访问数据库的 Agent,可能造成真实损失。Runtime 的安全目标不是把 Agent 绑住,而是让它在明确边界内做事;越过边界时,停下来请人确

Agent 可以动态接入和移除工具;工具 schema 改变不会把 Agent 弄崩;MCP 工具仍然经过本地权限审批;模型供应商替换不影响 runtime 主循环。完成这一章,你的 miniagent 已经具备生态接入能力。

用 MCP TypeScript SDK 写一个本地 MCP Server,提供两个工具: readprojectfile; searchprojecttext。 然后让 miniagent: 启动时发现 MCP 工具; 将 MCP 工具映射到本地 Tool Registry; 为 MCP 工具加风

模型调用失败时,runtime 可以重试;但要分清失败类型。 网络抖动可以重试;限流需要退避;上下文超限需要重新构建上下文;模型不支持某个 schema 特性,需要 schema 降级;工具调用格式不合法,可以让模型重试一次;安全策略拒绝,不应换模型绕过。 一个清晰的模型错误分类: 类型 处理 RA

模型供应商的工具调用接口并不完全一致。Runtime 应有自己的 provider adapter: 这样做的好处是: 可切换 OpenAI、Anthropic、本地模型或 Vercel AI SDK; 可统一 stream event; 可把 provider 原生 tool call 转成本地

一个实际做法是把 MCP 工具包装成本地统一 ToolDefinition: 注意命名空间。不要让两个 MCP Server 的 search 工具互相覆盖。也不要直接相信工具描述里的'safe''read only'等文字;风险等级应由本地策略、Server 信任级别、工具名称、输入 schema

MCP Tools 规范里,Client 通过 tools/list 发现可用工具,通过 tools/call 调用工具。工具包含名称、描述和输入 schema。Server 声明 tools capability 后,必须响应 tools/list;工具列表可以为空,也可以随时间变化。 对 run

MCP 不是模型协议,也不是 Agent Runtime 的替代品。它解决'工具和上下文如何被发现、描述和调用'。权限、调度、上下文预算、trace、checkpoint 和 eval,仍然是 runtime 的活。 可以这样理解: MCP Server 把能力暴露出来,Runtime 决定这些能力

Agent 迟早要接外部工具。本章讨论怎么接,以及怎么避免被某个供应商或协议绑死。 Agent Runtime 不能永远只使用本地写死的工具。它需要连接数据库、浏览器、设计工具、代码托管平台、内部系统、文档库和企业权限系统。MCP 的出现,正是为了解决 LLM 应用与外部数据、工具之间缺少统一连接方

你应该能解释上下文不足时的降级顺序;能说明 repo map 与直接读文件的关系;能通过 debug report 解释模型为什么知道或不知道某个事实。做到这里,Agent 才有长任务的记忆力。

实现一个 Context Builder: 用户当前消息固定保留; 最近 6 轮完整保留; 旧历史压缩为 summary; 大文件只保留摘要和关键片段; 工具结果按重要度截断; 输出 context debug report。 准备一份 200K token 的模拟历史,压缩进 32K / 64K

建议降级顺序: 1. 删除已确认无关的工具日志; 2. 压缩旧历史; 3. 长工具结果改摘要; 4. 大文件改为结构摘要 + 关键片段; 5. repo map 降级为目录树 + 入口文件; 6. 最后才缩短当前用户意图周边内容。 安全策略、用户明确要求、当前目标、最近失败原因,不应轻易被挤掉。 上

工具结果进入上下文前,应先问: 这是事实结果,还是日志噪声? 后续步骤是否需要逐字引用? 是否有结构化字段可提取? 是否超过预算? 是否包含 secret 或隐私数据? 例如测试失败日志,模型通常需要失败用例、断言信息、文件路径、行号、错误堆栈顶部,而不是全部构建输出。搜索结果通常需要文件路径和匹配

长对话中,不能无限保留全部消息。常用策略是: 最近 N 轮完整保留; 更早历史压缩成 session summary; 用户显式约束永久置顶; 已完成任务结果写入 memory; 失败原因和决策记录保留为 run notes。 滚动摘要有一个风险:摘要会丢细节,甚至引入轻微偏差。因此摘要应该标注来源

coding agent 需要理解仓库。直接把所有文件塞进上下文不可行,所以需要 repo map。 repo map 可以包含: 目录树; 关键入口文件; 导出的函数、类、类型; import/export 关系; 最近修改文件; 测试文件与源文件对应关系; README、配置文件、路由文件摘要。

一个 Context Builder 至少接收: 它输出的不只是 messages,还应输出 debug report: debug report 很朴素,却能救命。没有它,你很难解释模型为什么没看见某个文件、为什么忘记用户刚才的限制、为什么把旧错误当成新事实。 debug report 建议保存到

token budget 不只是技术限制,也是产品预算。一次 run 里,token 影响延迟、成本和可靠性。越长的上下文越不一定越好,因为模型注意力会被稀释,缓存命中也可能下降。 可以把上下文分为六层: 1. 系统与开发者指令; 2. 用户当前意图; 3. 近期完整对话; 4. 当前任务状态和计划
长任务跑久了,问题会变成一句话:有限的 context window 里,到底该放什么? Agent Runtime 的上下文不是聊天记录的简单拼接。它是一份给模型的'案卷':用户意图、当前目标、最近进展、关键文件、工具结果、约束、计划、失败记录、可用工具。案卷太薄,模型会失忆;案卷太厚,会浪费成本

你应该能说明并行工具调用如何与用户确认交织;能处理非法参数、缺字段、路径越界;能把工具失败转换成结构化 observation;能解释为什么工具系统是一套治理层,而不是一串函数。

为 miniagent 增加四个工具: editfile:写文件,但执行前必须生成 diff preview; applypatch:应用 patch,只允许 workspace 内路径; runcommand:执行命令,先做风险分类; searchcode:基于 rg 的只读搜索。 给每个工具加