LocalAgentTask vs RemoteAgentTask
这页回答什么
Claude Code 里的
LocalAgentTask和RemoteAgentTask都属于 Task 系统,但两者到底共享什么、分叉什么、分别解决什么问题?
相关页面:
一句话结论
两者共享的是“长期任务协议”,分叉的是“执行载体”。
LocalAgentTask管本地子 agent 的后台生命周期,RemoteAgentTask管远端 session 的本地代理与轮询恢复。
换句话说:
- Local = 本地执行流外面套一个 task 壳
- Remote = 远端事件流在本地投影成 task 对象
1. 它们为什么会被放进同一个 Task 系统
因为两者都需要这些能力:
- 任务注册
- 状态展示
- output file
- kill / stop
- completion notification
- 与主对话的回流协议
如果没有 Task 层:
- local async agent 只能是一个裸后台 Promise
- remote session 只能是一个散装 poller
而 Claude Code 想要的是:
不管任务跑在本地还是远端,只要它是“持续中的工作单元”,就该是一个一等 task。
2. LocalAgentTask 的核心职责
LocalAgentTask 负责的是:
- 后台本地子 agent 的注册
- 运行态跟踪
- 进度更新
- transcript / output file 管理
- pendingMessages 缓冲
- background / foreground 切换
- 完成/失败/终止状态管理
它围绕的是:
本地
runAgent()已经在跑,Task 负责把它托管起来。
所以 LocalAgentTask 更像:
- lifecycle wrapper
- status shell
- progress envelope
而不是执行器本身。
3. RemoteAgentTask 的核心职责
RemoteAgentTask 负责的是:
- 记录远端 session 身份
- 持久化 sidecar metadata
- 周期轮询远端 event stream
- 把远端日志映射到本地 output file
- 解释 completion / failure / timeout
- resume 后重新接管 still-running session
它围绕的是:
真正的 agent 执行已经发生在远端,本地只保留一个代理对象。
所以 RemoteAgentTask 更像:
- remote session proxy
- poller
- state reducer
- resume controller
4. 共享点:两者都遵守同一套任务协议
A. 都在 AppState 中注册为 task
这样 UI、状态面板、生命周期工具都能统一处理。
B. 都有 output file
任务输出可落盘、可引用、可延迟读取。
C. 都有 status
- running
- completed
- failed
- killed
D. 都能 stop / kill
虽然底层动作不同,但表层任务语义统一。
E. 都最终走 task-notification
这是最关键的公共协议。
无论 local 还是 remote,最终都会:
enqueuePendingNotification(mode='task-notification')
→ query.ts drain queue
→ attachments
→ 后续轮次上下文也就是说:
Task 系统真正统一的是回流协议,而不是底层执行方式。
5. 分叉点:完成信号从哪里来
LocalAgentTask
完成信号来自:
- 本地
runAgent()执行流 finalizeAgentTool()completeAsyncAgent()/failAsyncAgent()/killAsyncAgent()
它的世界观是:
“我知道 agent 在本地跑到了哪一步。”
RemoteAgentTask
完成信号来自:
pollRemoteSessionEvents()拉回的远端事件- 对
result/archived/idle/ hook tag / timeout 的解释
它的世界观是:
“我不知道远端如何一步步运行,但我能从事件流推断它现在的状态。”
所以 Local 是执行流驱动,Remote 是事件归约驱动。
6. 分叉点:是否天然带恢复语义
LocalAgentTask
当然也可以保留状态,但本质上依赖本地进程生命周期。
RemoteAgentTask
从设计上就要求:
- sidecar 持久化
restoreRemoteAgentTasks()- 重新连接 still-running session
因为远端 session 不随本地 CLI 一起消失。
所以 remote task 的“可恢复”不是锦上添花,而是默认约束。
7. 分叉点:进度的来源不同
LocalAgentTask
进度来自本地 agent transcript:
- toolUseCount
- tokenCount
- recent activity
- summary
RemoteAgentTask
进度来自远端 event stream:
- assistant text
- result event
- hook_progress / hook_response
- review-specific JSON tags
这使得 RemoteTask 的进度逻辑往往更脆弱、更产品化,也更依赖特定远端协议。
8. 分叉点:Task 的“壳”厚度不同
LocalAgentTask
壳比较薄。 因为真正复杂的逻辑大多还在:
AgentToolrunAgent()- 本地 query loop
Task 主要负责托管。
RemoteAgentTask
壳更厚。 因为它自己就承担:
- polling
- event accumulation
- completion inference
- timeout handling
- resume
- specialized notification branches
所以 RemoteAgentTask 更像一个小控制器,而不只是壳。
9. 两者如何在用户层表现成同一种东西
虽然内部差异很大,但用户层会看到相似体验:
- 一个任务启动了
- 它有 task id / output file / 状态
- 它完成时会收到通知
- 主 agent 能基于这个结果继续工作
这正是 Task 系统成功的地方:
把两种完全不同的执行模型,压平为一种统一的会话语义。
10. 最简对照表
LocalAgentTask
- 执行位置:本地进程
- 核心驱动:
runAgent()执行流 - 任务角色:后台托管壳
- 进度来源:本地 transcript
- 完成判定:本地函数完成/异常/abort
- 恢复需求:较弱
- 典型风险:本地 cleanup / worktree / kill 协调
RemoteAgentTask
- 执行位置:远端 session
- 核心驱动:event polling + state reduction
- 任务角色:远端代理对象
- 进度来源:远端 SDK events / hook events
- 完成判定:result / archived / idle / timeout / checker
- 恢复需求:很强
- 典型风险:轮询抖动、错误归约、session 恢复
当前结论
LocalAgentTask 和 RemoteAgentTask 的关系可以概括成:
它们不是同一个东西的两个实现细节,而是两种不同执行世界在 Task 协议层的统一投影。
Claude Code 真正聪明的地方,不是让 remote 看起来像 local, 而是让:
- local execution
- remote session orchestration
都能最终说同一种“任务语言”。
这门语言就是:
- task state
- output file
- notification
- attachment 回流
下一步最值得继续追
- 单独深挖
teleportToRemote()的 source/bundle/environment 决策树 - 追
queued_commandattachment 进入模型输入的最终序列化过程 - 对比 sync / async / remote 三种 AgentTool 路径在 transcript 上的差异