从 Background Tasks 到 Cron Scheduler 再到 Agent Teams:Agent Harness 的异步化与多 Agent 协作演进
从 Background Tasks 到 Cron Scheduler 再到 Agent Teams:Agent Harness 的异步化与多 Agent 协作演进
在前面的章节中,Agent 已经具备:
- Tool Calling
- Hooks
- Todo Planning
- Subagent
- Skill Loading
- Context Compact
- Memory
- Error Recovery
- Task System
此时的 Agent 已经能够独立完成复杂任务。
但还有三个明显瓶颈:
问题一:等待
Agent 执行:
1 | npm install |
可能需要 5 分钟。
执行:
1 | pip install torch |
可能需要十几分钟。
这期间 Agent 什么都做不了。
问题二:只能手动触发
Agent 只能这样工作:
1 | 用户说一句 |
无法做到:
1 | 每天 9 点跑测试 |
问题三:单 Agent 注意力有限
当任务变成:
1 | 重构整个后端 |
一个 Agent 的上下文根本装不下。
因此:
1 | s13 解决等待 |
最终把 Harness 从同步单体结构推进到异步协同结构。
第一部分:s13 Background Tasks
为什么需要 Background
s12 的执行模型是:
1 | Agent |
例如:
1 | run_bash("npm install") |
Agent 会一直阻塞。
问题在于:
1 | 安装依赖期间 |
却被迫等待。
所以 s13 引入:
1 | Background Task |
思想非常简单:
慢任务丢后台,Agent 继续工作。
如何判断后台执行
核心函数:
1 | should_run_background() |
优先看模型是否明确要求:
1 | run_in_background=True |
例如:
1 | bash( |
如果模型没有指定,则退化为启发式判断:
1 | install |
出现这些关键词就认为可能是慢任务。
后台任务注册表
s13 引入三个全局对象:
1 | background_tasks |
结构:
1 | background_tasks = { |
类似:
1 | ConcurrentHashMap<String, Task> |
只是教学版使用 Python dict + Lock。
start_background_task
核心流程:
1 | def start_background_task(block): |
生成:
1 | bg_0001 |
然后启动线程:
1 | threading.Thread( |
线程执行:
1 | execute_tool(block) |
完成后:
1 | background_results[bg_id] |
保存结果。
collect_background_results
后台完成后不会自动打断 Agent。
而是在下一轮收集:
1 | collect_background_results() |
生成:
1 | <task_notification> |
然后注入消息。
于是 Agent 看到:
1 | npm install 完成了 |
再决定下一步。
本质
s13 的本质:
1 | 同步调用 |
从:
1 | 调用 → 等待 → 返回 |
变成:
1 | 调用 → 占位返回 |
第二部分:s14 Cron Scheduler
Background 解决不了定时问题
虽然有后台任务:
1 | Agent 不用等待 |
但仍然需要:
1 | 人工触发 |
例如:
1 | 帮我每天9点跑测试 |
Background 做不到。
所以引入:
1 | Scheduler |
CronJob
s14 增加:
1 |
|
例如:
1 | CronJob( |
表示:
1 | 每天上午9点 |
Cron 表达式
经典 Unix 格式:
1 | min hour day month week |
例如:
1 | 0 9 * * * |
每天9点
1 | */5 * * * * |
每5分钟
Scheduler Thread
核心循环:
1 | cron_scheduler_loop() |
独立线程:
1 | while True: |
每秒检查一次。
它与 Agent Loop 完全解耦。
即使:
1 | Agent 正在工作 |
Scheduler 都持续运行。
Cron Queue
Scheduler 不直接执行任务。
只负责:
1 | cron_queue.append(job) |
因此形成:
1 | Scheduler |
生产者消费者模型。
Queue Processor
负责检测:
1 | cron_queue |
是否有内容。
如果:
1 | Agent 空闲 |
自动启动:
1 | agent_loop |
无需用户输入。
Durable
Cron 支持:
1 | durable=True |
写入:
1 | .scheduled_tasks.json |
例如:
1 | { |
下次启动:
1 | load_durable_jobs() |
恢复。
本质
s14 本质上实现:
1 | 事件驱动 |
过去:
1 | 用户输入 |
现在:
1 | 时间到 |
Agent 开始拥有:
1 | 主动性 |
第三部分:s15 Agent Teams
单 Agent 的极限
即使有:
1 | Task System |
仍然只有一个 Agent。
问题:
1 | 数据库改造 |
全部塞进一个上下文。
迟早:
1 | 上下文爆炸 |
为什么 Subagent 不够
s06 已经有:
1 | task() |
生成:
1 | spawn_subagent() |
但 Subagent:
1 | 干完活就销毁 |
不能持续协作。
Team 的核心思想
从:
1 | Lead |
变成:
1 | Lead |
多个 Agent 同时工作。
MessageBus
核心组件:
1 | class MessageBus |
每个 Agent 一个收件箱:
1 | .mailboxes/ |
发送消息:
1 | BUS.send( |
本质:
1 | append json line |
收件箱机制
读取:
1 | read_inbox() |
然后:
1 | unlink() |
删除文件。
即:
1 | 读取即消费 |
类似:
1 | RabbitMQ |
的简化版。
spawn_teammate
Lead 调用:
1 | spawn_teammate( |
启动线程:
1 | Thread( |
然后:
1 | Alice Agent Loop |
开始运行。
Teammate 的上下文
每个 Agent:
1 | messages |
完全独立。
例如:
1 | Alice 专注数据库 |
互不干扰。
Lead Inbox Injection
Lead 每轮检查:
1 | BUS.read_inbox("lead") |
如果收到:
1 | Alice: |
则自动注入:
1 | history.append( |
让 Lead 知道结果。
一个完整协作流程
Lead:
1 | 重构整个系统 |
↓
创建:
1 | Alice → 数据库 |
↓
三个 Agent 并行运行。
↓
Alice:
1 | schema.sql 完成 |
发送:
1 | lead mailbox |
↓
Lead 收到。
↓
继续调度。
Team 与 Task System
此时真正形成:
1 | Task System |
架构。
任务系统负责:
1 | 做什么 |
团队系统负责:
1 | 谁来做 |
第四部分:Harness 架构升级
s13 之前:
1 | User |
加入 Background:
1 | User |
加入 Scheduler:
1 | Scheduler |
加入 Teams:
1 | Lead |
最终结构:
1 | Scheduler |
总结
s13 解决:
Agent 必须等待吗?
答案:
1 | 不用等 |
s14 解决:
Agent 必须人工触发吗?
答案:
1 | Scheduler 自动触发 |
s15 解决:
一个 Agent 怎么减轻负担?
答案:
1 | 组建团队 |
因此这三个章节实际上代表 Harness 的三个重大升级:
1 | 同步执行 |
到这里,一个简单的 ReAct Agent 已经演化成具备:
- 后台任务
- 定时任务
- 持久化任务图
- 多 Agent 协作
- 消息总线
能力的完整 Agent Harness。
而这也正是 Claude Code 后半部分架构开始向 Swarm(Agent Team)演化的起点。
