Task 系统总览
目标
这页回答:
Claude Code 里,子 agent / 远程 agent 为什么不只是“跑完就完”,而要挂进 Task 系统?Task 层到底负责什么?
关键文件:
src/tasks/LocalAgentTask/LocalAgentTask.tsxsrc/tasks/RemoteAgentTask/RemoteAgentTask.tsx
一句话结论
runAgent()负责“执行”,而 Task 系统负责“生命周期管理”。
也就是:
- agent 怎么跑 →
AgentTool/runAgent - agent 作为后台任务如何注册、跟踪、通知、恢复、停止 →
Task层
Task 不是推理层,是 orchestration / lifecycle 层。
1. 为什么需要 Task 层?
如果 agent 只有同步运行,那工具执行完直接回一个 tool_result 就够了。
但这里系统支持:
- 后台 agent
- foreground agent 随时 background 化
- remote agent
- task notification
- output file
- 恢复 / resume
- kill
- 进度追踪
一旦有这些需求,单纯靠 runAgent() 就不够了。
所以 Task 层本质上是在回答:
这个 agent 作为一个“持续中的任务”如何被系统管理?
2. LocalAgentTask:本地子 agent 的生命周期层
它管理什么?
LocalAgentTaskState 里能看到它关心的字段很多:
agentIdpromptselectedAgentstatusabortControllerprogressmessagespendingMessagesisBackgroundedretaindiskLoadedevictAfter
这说明本地 agent task 不是一个简陋状态机,而是同时承担:
- 运行态跟踪
- 面板/UI 展示
- transcript 保持
- 用户继续发消息
- 结束后延迟驱逐
3. LocalAgentTask 的三种核心注册方式
A. registerAsyncAgent()
直接注册一个后台 agent。
特点:
- 一上来就是
isBackgrounded: true - 会初始化 output file symlink 到 transcript
- 会创建 abortController
- 会注册 cleanup
- 会把 task state 放进 AppState
这对应“从一开始就后台跑”的 agent。
B. registerAgentForeground()
注册一个前台 agent,但允许稍后 background 化。
特点:
- 初始
isBackgrounded: false - 会返回一个
backgroundSignalpromise - 可以设置
autoBackgroundMs
这正好对应 AgentTool 同步子 agent 那条线:
- 先前台跑
- 运行太久时,用户或系统可切后台
C. backgroundAgentTask()
把一个前台 agent 标记成后台,并 resolve 它的 backgroundSignal。
这让上层 agent loop 能感知:
- 现在该从前台等待模式切到后台通知模式了
4. LocalAgentTask 的进度系统
LocalAgentTask 不是只记录“running / done”。 它还会维护一个比较细的进度模型:
toolUseCounttokenCountlastActivityrecentActivitiessummary
这套进度怎么来的?
通过:
createProgressTracker()updateProgressFromMessage()getProgressUpdate()
它会从 assistant message 中提取:
- usage token
- 最近调用过的工具
- 工具输入
- activity description
所以 task progress 不是瞎猜,而是从真实 agent transcript 里增量提取出来的。
5. LocalAgentTask 为什么要有通知机制?
函数:
enqueueAgentNotification()
它会构造一段标准化 task-notification XML:
task_idoutput_filestatussummary- 可选
result - 可选
usage - 可选
worktree
然后通过:
enqueuePendingNotification({ mode: 'task-notification' })放进消息队列。
这意味着什么?
后台 agent 完成后,不是直接神秘地“出现在用户眼前”。 而是通过统一消息机制,把任务完成信号重新送回主对话循环。
这点很关键: 后台任务的完成事件最终也被当成对话输入来消费。
6. LocalAgentTask 的结束路径
完成
completeAgentTask(result, setAppState)
做的事:
- status → completed
- 保存 result
- 清理 abort / cleanup 句柄
- 设置 endTime
- 安排 evict
但注意:
- 真正通知不是它发
- 通知由
AgentTool侧调用enqueueAgentNotification()完成
失败
failAgentTask(...)
类似,只是 status → failed。
终止
killAsyncAgent(...)
会:
- abort controller
- unregister cleanup
- status → killed
- 释放 output
7. 为什么 LocalAgentTask 里还有 pendingMessages?
这是个很有意思的点。
它支持:
- 用户在 agent 运行中通过
SendMessage往 task 里塞消息 - 消息先暂存到
pendingMessages - 再在合适时机由 agent loop drain
这说明 task 不只是“运行状态容器”, 它还承担了:
给正在运行中的 agent 做中途通信缓冲。
8. RemoteAgentTask:远程 agent 的生命周期层
远程任务这边的状态完全不同。
RemoteAgentTaskState 关注的是:
sessionIdremoteTaskTypecommandtitlelogtodoListpollStartedAtisRemoteReviewreviewProgressisUltraplan
这说明 remote task 的核心不是“本地执行过程”,而是:
一个远端 session 的本地镜像与轮询控制。
9. registerRemoteAgentTask() 做什么?
它会:
- 生成 taskId
- 初始化 output file
- 创建
RemoteAgentTaskState - 注册进 AppState
- 把 metadata 持久化到 session sidecar
- 启动
startRemoteSessionPolling()
为什么要写 sidecar?
因为 remote task 能跨会话恢复。
也就是说,本地程序重开后,系统还能:
- 扫到之前没结束的 remote task
- 重新连上对应 remote session
- 继续轮询状态
这就是 remote task 和本地 task 的一个大差别: 它天然带有恢复需求。
10. RemoteAgentTask 的核心是轮询器
函数:
startRemoteSessionPolling()
这东西非常关键。
它会周期性:
pollRemoteSessionEvents(...)- 追加新日志
- 更新 task state
- 判断 session 是否 archived / completed / failed / timed out
- 特判 remote review / ultraplan / long-running task
- 发出 notification
这说明 remote task 的完成不是本地函数返回驱动的
而是:
- 由远端 session 的事件流驱动
- 本地通过 poller 做状态归约
这已经是另一种 orchestration 模式了。
11. RemoteAgentTask 的通知和 LocalAgentTask 类似,但语义不同
enqueueRemoteNotification() 也会发 task-notification XML,
但它更偏:
- 远程任务已完成 / 失败 / 停止
- output_file 在哪
- summary 是什么
另外还有专门分支:
enqueueUltraplanFailureNotification()- remote review completion / failure notification
说明 remote task 不只是“通用 agent”,还承载特定产品形态。
12. Remote task 为什么复杂?
因为它要处理很多本地 agent 不需要的事:
- 远端 API 出错
- 远端 session archived
- 轮询 idle 抖动
- review timeout
- 从 hook_progress / assistant text 中提取结果 tag
- sidecar 恢复
- archive remote session
所以 RemoteAgentTask 本质上已经像一个小型“远程作业控制器”。
13. 这两类 Task 的本质区别
LocalAgentTask
像:
- 本地异步子 agent 的任务记录 + UI / 通知 / kill 外壳
RemoteAgentTask
像:
- 远程 session 的本地代理对象 + poller + resume 机制
两者共同点:
- 都挂进统一 Task 框架
- 都有 status / notification / output_file
- 都能 kill / complete / fail
两者差异:
- Local 以本地执行流为核心
- Remote 以远程 session 轮询与恢复为核心
14. Task 系统和 Agent 系统如何分工
这点一定要分清。
Agent 系统负责
- prompt
- tool pool
- subagent context
- query loop
- agent result
Task 系统负责
- 注册
- 状态
- 后台化
- 进度
- 通知
- 输出文件
- resume
- kill
- 清理
所以 Task 不是 agent 的替代,而是 agent 的壳。
当前结论
Claude Code 的 Task 系统可以理解成:
把“一个正在运行或等待完成的 agent 工作单元”提升为一等对象。
这样系统才能稳定支持:
- background agents
- fork workers
- remote sessions
- resume / restore
- UI 面板与通知
如果没有 Task 层,agent 只能停留在“同步工具调用”这个初级阶段。
而现在这套设计,已经明显是面向长期运行、多任务并存、可恢复执行的。