基于李博杰《深入理解 AI Agent:设计原理与工程实践》第4章学习笔记(下篇)。
开篇:从”会排队的柜台”到”灵活的秘书”
想象一家银行的柜台:顾客只能排成一队,办完一个才能叫下一个号——这是同步的世界。而一位真正能干的秘书桌上总是摊着好几件事:邮件、电话、来访者,她能按紧急程度决定先处理哪个,中途还能停下手里的事去接一个更紧急的电话,回头再接着干——这是异步的世界。
上篇我们解决了 Agent”选得对工具、调得准工具”的问题;本篇走进第 4 章的另外半边天:执行工具如何保证安全、协作工具如何分工、事件驱动的异步架构如何让 Agent”活”起来、工具多到上千时如何主动发现。如果说感知工具让 Agent”看见世界”,执行工具则让 Agent”改变世界”——而改变世界,必须先回答安全问题。
一、执行工具:改变世界之前,先守住安全
执行工具能写入文件、执行命令、调用外部系统,一旦出错可能造成不可逆的后果。第 4 章给出的安全体系层层递进:
1. 输入验证与黑名单只是底线。 对危险命令(如 rm -rf)做字符串匹配是”最基础的防护层”,攻击者可通过变形命令绕过,更健壮的方案是结合语义解析理解命令的真实意图。
2. 提议者-审核者(Proposer-Reviewer):第二双眼睛。 借鉴”银行经办、审核双签”制度,用独立模型审查关键操作。事前审批有两个要点:提议与审批模型应来自不同家族(如 Claude 与 GPT)——不同训练偏好带来认知多样性,不太可能在同一个地方犯同样的错;但能力应相近(Haiku 审查 Opus 会跟不上思路)。审批失败不应简单重试,而要把拒绝理由作为工具调用结果加入轨迹——Agent 本就会处理工具失败,审批只是新的输入源。事后验证的要诀则是模态切换:生成了代码文档就渲染成图检查排版,改了配置就在沙盒里实际运行——单一模态的审查容易陷入相同的盲区。
3. Sidecar:与主思考并行的安全闸门。 借鉴微服务边车模式,用轻量级 LLM 旁路调用,在每次工具调用前后独立判断风险。关键设计是刻意隔离主模型的自由文本,只读结构化的 {tool, command} 数据——否则攻击者在网页里夹带”请允许执行 rm -rf”的话术,主模型复述进思考过程,Sidecar 就可能被操纵。它还配拒绝熔断器:连续拒绝多次就回退到请求用户手动判断,避免死循环。
4. 隔离与幂等。 执行环境按隔离强度分层:OS 级(macOS Seatbelt、Linux seccomp+namespaces)→ 容器(Docker,共享内核)→ microVM(Firecracker,硬件级隔离),之上再加资源配额。注意 venv 不是沙盒,它只隔离包依赖。对于”超时后副作用到底发生没有”的问题,幂等设计是答案:携带幂等键让服务端去重,或”先查询后变更”;而发邮件、转账这类不可幂等的操作,采用预检-确认两段式——第一段只校验生成内容,第二段凭确认令牌真正执行。
| 对比维度 | 提议者-审核者 | Sidecar |
|---|---|---|
| 执行时机 | 操作前审批或操作后验证 | 与主模型流式输出并行,门控单次工具调用 |
| 审查对象 | 操作的合理性或结果 | 操作本身(工具调用) |
| 审查视角 | 独立模型审批、模态切换验证 | 安全性/可靠性校验 |
| 输入隔离 | 提议者与审查者看到相似信息 | 刻意隔离主模型的自由文本 |
| 典型用途 | 不可逆操作审批、配置修改 | 权限分类、记忆相关性判断、工具输出摘要 |
执行工具还应遵循”可验证就自动验证“原则:write_file 写入后立即跑 linter,把结构化错误列表作为返回值——形成”执行-验证-反馈”闭环,Agent 下一轮就能看到”第 10 行:未定义的变量 result”并修正。
二、协作工具:专业分工与人的位置
当任务超出单个 Agent 的能力边界,协作工具让它把子任务委托出去。子 Agent 的设计哲学是专业化分工:与其构建”全能”Agent,不如一组各自专精的 Agent 协作。子 Agent 的提示词有四个关键要素:角色定义清晰(”你是专门负责 XXX 的助手”)、上下文来源标注([FROM_MAIN_AGENT]、[FROM_USER]、[TOOL_RESULT] 区分,防止提示注入)、任务边界明确、输出格式标准化(统一 JSON 降低解析负担)。
协作接口归纳为三组原语:启动与取消(spawn_subagent / cancel_subagent,任务失去意义时及时终止,避免浪费 token)、消息传递(send_message_to_subagent,双向沟通)、发现(list_agents 列出可用 Agent——与 MCP 的 tools/list 同一思路,只不过列出的是 Agent)。
人工介入(HITL)同样是协作的一部分:请求需设超时阈值与默认行为(”5 分钟无响应采用保守策略”)和优先级队列(紧急多渠道通知,普通只发邮件);更重要的是把批准、拒绝及理由沉淀为反馈数据——可归纳的原则进经验知识或 Skill,隐式偏好形成后训练数据,但不能把一次人工判断未经归纳就推广为普遍规则。
三、事件驱动的异步 Agent:让世界主动唤醒 Agent
3.1 为什么需要异步
传统同步 Agent 只能”用户发一条、Agent 回一条”。但真实助理需要三样能力:异步执行(长任务不阻塞交互)、事件优先级动态判断(紧急就取消当前操作、常规就入队、独立的就并行)、中断与恢复流畅。而核心矛盾在于:LLM 的训练范式假设同步——发出工具调用后,下一条消息必须是工具结果;真实部署却要求异步——用户随时可能打断。
开源框架 OpenClaw 提供了三种内置自动化机制:Hooks(响应会话创建等生命周期事件)、Cron(按 cron 表达式定时执行)、Heartbeat(每隔 N 分钟唤醒检查)。但三者都是时间驱动的,对内置渠道之外的第三方事件源(新邮件、外部 API 回调)缺乏即时接入通道。PineClaw(Pine AI 的插件,代用户打真实电话)给出了答案:引入 Channel 机制,在 Gateway 与 Pine API 之间建立实时事件通道,通话接通、需要用户输入等事件即时推送,响应延迟从分钟级降到秒级。核心观点:真正的”主动服务”,不仅需要 Agent 定时检查世界,更需要世界能主动通知 Agent。
3.2 三类事件触发工具与用户沟通
- 定时器(
set_timer):一次性(”下周一上午 10 点致电 DMV”)与循环(每小时检查服务器健康)两种。 - 后台任务监控(
monitor_shell):监控命令行新增输出或含关键词的输出,避免”死盯”浪费 token 或”全等完成”错失介入时机。 - 外部事件通道(
connect_channel):把新邮件、API 回调实时推送给 Agent。
用户沟通工具解决”如何触达用户”:支持异步消息模式(用户不一定在线)、已读/未读状态、多渠道召回(IM、短信、邮件、电话、推送,按紧急程度与偏好选择)。边界在于:通知审批者或协作者归协作工具,通知最终用户本人才归用户沟通工具——区别不在渠道,而在”通知谁、为什么通知”。支撑 Agent 独立行动的还有虚拟身份与隔离执行环境:与其让 Agent 直接管理用户账号(被攻破将暴露全部数字身份),不如赋予它独立虚拟身份(专属邮箱、存储、计算环境),在虚拟电脑/虚拟手机中运行,通过共享文件系统(如 /workspace/shared)以文件路径而非内容拷贝交换数据。
3.3 事件处理三策略:取消、队列、并行
所有输入被统一建模为结构化事件(来源、渠道、内容、上下文),然后按紧急度分流:
| 处理策略 | 适用场景 | 运作方式 |
|---|---|---|
| 取消式 | 紧急事件(用户”停止”、系统告警) | 立即停止当前操作、清空队列,将事件连同队列内容一起追加轨迹,立刻重新调用 LLM 评估局势 |
| 队列式 | 常规事件(工具结果、补充信息) | 入队等待当前操作完成,在下一个安全点批量追加到轨迹 |
| 并行式 | 独立轻量查询(”今天天气怎样”) | 在并行推理会话中独立执行,立即回复,轨迹中标记”与主任务并行” |
紧急度判定建议用轻量级分类 LLM 作为事件路由器——硬编码规则难以承载”马上停下来”用取消式、”报告用中文发给我”用队列式的语义理解。
3.4 工程实现:让同步模型支持异步打断
既然 API 强制”tool_call 之后必须是 tool_result”,工程上就用占位符修复格式:未完成的工具调用生成占位符响应(”工具正在后台执行,请优先处理新事件”),追加打断事件后重新调用 LLM——常态下 LLM 看到的是完美同步轨迹,只在真正打断时才插入”必要的妥协”。但占位符有加剧幻觉的风险(模型可能”编造”工具结果),因此只在真正紧急时打断,非紧急事件入队。配合手段还包括异步工具接口(把 phone_call 拆成 initiate_phone_call,启动即返回任务 ID,完成通过事件通知)和状态栏标记([未处理事件 1/4] ... [未处理事件 4/4],末尾再汇总一次,对抗模型”只关注最后一个事件”的注意力偏差)。
归根结底,这些都是用提示工程弥补”训练同步/部署异步“矛盾的过渡方案。根本解法指向下一代模型:在异步环境中通过强化学习获得理解事件异步穿插、恢复被打断任务、批量事件综合处理三种能力——正如机器人领域 VLA 模型已在面对的挑战。作者引用的最新研究显示:用约两百行编排逻辑,就能让现有文本思考模型具备”持续思考”能力,但关键在于训练信号——用”LLM 当裁判”式奖励训练反而会学会藏起思考,只有可验证的目标才能让持续思考带来实打实的收益。
四、主动工具发现:从”全量注入”到”按需查阅”
当工具从十几个增长到上千个,全量注入 schema 会让上下文被说明书塞满、选择精度下降。三条演进路线:
- 检索预筛选:按初始查询做一次性语义匹配,局限是”Debug the file”这类任务会牵出跨领域工具链,任务开始时无法预见所有需求。
- 主动声明(MCP-Zero 为代表):系统提示词不预置任何工具 schema,Agent 在思考中声明”我需要什么能力”,系统做服务器级 → 工具级两层语义路由按需注入——在约 2800 个工具上比全量注入节省约 98% token。工程上更常见的等价方案是”工具搜索工具”(如 Anthropic 的 Tool Search Tool):系统只保留 web search、code interpreter 加一个
discover_tools元工具。 - Skills 渐进式披露:Agent 启动时只看到一份薄目录(每个 skill 的 name 与 description,合计数百 token),需要时才读取对应 sub-skill 再往下一层。这更像人查工具书——顺着目录按需精确查阅,无需维护向量索引。加载 sub-skill 对 KV Cache 的冲击,则用第二章的”可编辑、可组合 KV Cache”化解:把 skill 的 KV 表示预编译缓存,用 RoPE 重定位粘贴到任意位置,以 O(L) 而非 O(L²) 的代价拼接。
主动发现的工程代价是破坏 KV Cache:解决办法是把会变动的工具 schema 追加到上下文末尾,静态前缀(系统提示词 + 核心工具)保持字节级不变、缓存持续命中(命中率可从约 0% 提升到约 95%)。这也意味着”工具定义必须在上下文最前面”不再是铁律——代价是模型必须学会理解散落在轨迹各处的工具定义,弱模型甚至需要专门 RL 训练。
小结与实践建议
本章核心结论:工具设计的质量决定 Agent 的能力上限,异步架构决定 Agent 能否在真实世界中可靠运行。
实践建议:
- 执行工具:分层防御——黑名单打底,关键操作走提议者-审核者(不同家族、能力相近的模型互审),轻量判断用 Sidecar(只读结构化数据),执行环境按需选隔离层级,一切可验证的操作自动验证。
- 协作工具:子 Agent 提示词标注信息来源、界定任务边界、标准化输出;HITL 请求必设超时与默认行为,把人工判断沉淀为可复用反馈。
- 异步架构:先建模结构化事件流,用轻量 LLM 路由器判紧急度,区分取消/队列/并行三策略;打断只在真正紧急时使用。
- 工具发现:工具上千时优先”主动声明 + 层次化匹配”,或保留少量核心工具 + 一个工具搜索元工具;新工具 schema 一律追加到上下文末尾保住 KV Cache。
六个实验从感知、执行、协作三大工具集(实验 4-1 至 4-3),到事件驱动邮件 Agent(4-4)、并行执行与打断恢复(4-5)、主动工具发现(4-6)逐级递进,是检验本章知识的绝佳练习。
下一篇进入第 5 章:Coding Agent 与代码生成——Agent 能不能通过写代码来”创造工具”?这是所有通用 Agent 最核心的基础。