💡 一句话核心:Agent 越强,越需要"人类刹车"。Draft-Execute 把"说"和"做"分开 — agent 只负责生成方案,人类批准后才真正执行。这是 agent 在企业落地的第一道安全阀。
引导问题:
答案:
传统调用:
没有干预窗口。
Draft-Execute:
每个工具有两个接口:
Draft(input) → DraftSpec:只算、不改状态Execute(draftID) → Result:拿 draft 真做优点:
| 方式 | 描述 | 适合 |
|---|---|---|
| 同步 | HTTP 请求 block 等 approver | 简单、快(几秒内) |
| 异步 | 返回 draftID,approver 在 UI 上审 | 需要长时间、跨时区 |
生产基本都是异步的 — 没人愿意 block 一个 HTTP 连接等半小时。
为什么 expires_at? 超时自动拒绝,避免僵尸 draft。
示例 — Refund tool:
路由:
Draft = plan,Execute = act。分开后每一步可审计。
不是所有 tool 都审批 — 低风险(read)可以免审,高风险必审。可配置。
金融行业要求:两人批准才能执行。实现上加 required_approvers INT 字段。
已 executed 的操作能不能撤销?依赖 tool 是否支持(refund 可以,发邮件不行)。设计时要标注。
status='pending' 条件拦住)FOR UPDATE?跑通 CreateDraft / Approve / Reject / Execute。
实现 RefundTool,写单测:draft 成功 → approve → execute,验证 payments.Refund 被调用。
手动 UPDATE expires_at 到过去,等 reaper 扫一遍,验证状态变 expired。
集成 Slack webhook 作为 Notifier 实现。
Q: 如果 approve 后 execute 失败,draft 状态是什么?
A: 保持 approved,执行失败独立记录。可以加一个 execute_error 字段或 retry 机制。
Q: Agent 可以并发创建多个 draft 吗?
A: 可以,每个 draft 独立。但要防止 agent "刷屏" — 加 rate limit(用户每小时最多 N 个)。
Q: 审批人看什么?preview 字段够吗?
A: 不够。UI 应该展示:
Q: 完全自动化场景(不需要人审)怎么兼容?
A: 在 tool 上加 AutoApprove bool,Service 里判断:
Q: 高风险但紧急场景怎么办?
A: 加"break-glass"机制 — 特定 role 可跳过审批,但必须写理由,事后强制 review。
题目: 给任务列表(大写字母)和冷却时间 n,CPU 每执行完一个任务后同种任务必须等 n 个时间单位才能再执行(期间可执行其他任务或 idle)。返回完成所有任务的最少时间。
思路: 贪心。出现次数最多的任务(频率为 maxCnt)决定了"骨架":有 (maxCnt-1) 个间隔,每个间隔长为 n,再加上最后一批 maxCnt 次数的任务。其他任务可填入间隔空位。若总任务数超过骨架长度,则无需 idle 直接排满。
复杂度: 时间 O(N)(N 为任务数),空间 O(26) = O(1)
变体/面试追问:
题目: 给 k 个已排序的链表,将它们合并为一个排序链表并返回。
思路: 最小堆(container/heap)。将 k 个链表的头节点都入堆,每次弹出最小值节点加入结果链,再将该节点的 next 入堆。直到堆为空。
复杂度: 时间 O(N·log k)(N 为总节点数,k 为链表数),空间 O(k)(堆大小)
变体/面试追问:
题目: 给无序数组 nums 和整数 k,返回数组中第 k 大的元素(不是第 k 个不同的元素)。
思路(快速选择): 类似快排的 partition,每次选一个 pivot 将数组分为两部分。若 pivot 的位置恰好是第 k 大,直接返回;否则递归一侧。期望 O(N)。
思路(最小堆): 维护大小为 k 的最小堆,遍历数组,若当前元素大于堆顶则替换堆顶。最终堆顶即为第 k 大元素。O(N·log k)。
复杂度: 快速选择期望 O(N)/最坏 O(N²),空间 O(1);最小堆 O(N·log k),空间 O(k)
变体/面试追问:
明天是本周最难的一天 — Guardrails。
准备问题: