-
Notifications
You must be signed in to change notification settings - Fork 1
Core zh
上游 Agent 循环、Agent 注册表和 turn 生命周期在 Edge 中的适配。
上游参考:Core
核心子系统提供每个组合都依赖的基础 Agent 基础设施:
-
AgentRegistry(
ctx.agents)— 创建、恢复和销毁 Agent。每个 Agent 拥有一个 session、一个 inbox(next-turn / next-step 消息队列)和一个作用域 cordis context。销毁器是一个能力——只有创建者能拆除 Agent。 -
AgentLoop — 实现
Agent契约的具体驱动。通过 step 管线处理 inbox 消息:pre-step 验证 → 模型请求 → 流式 → 工具执行 → post-step。在idle和running状态之间转换。 -
Agent 事件 — 作用域过滤分发:
agent/created、agent/disposed、agent/pre-step、agent/request、agent/turn-stopping、agent/status和 inbox 事件。 -
Inbox 管理 — 两个有序消息列表(
next-turn和next-step),支持 append、prepend、replace、remove、clear 和 splice 操作,全部记录为持久化的agent/inbox/spliced事件。
两个插件原封不动安装。Agent 创建、session 绑定、inbox 管理、step 管线、模型流式和工具分发完全是上游代码。
上游的 agent loop 和调用者在同一个进程——turn 在调用者发消息时开始,Agent 空闲时结束。Edge 在此基础上加了传输层,因为调用者(浏览器)是远程的:
-
activeTurnsmap — 追踪 DO 内哪些 session 有正在运行的 turn。防止交叉 HTTP 请求对同一 session 发起并发 turn。 -
claimAndOpenAgent()— 原子地占位 session 并在接受 prompt 前打开/恢复 Agent。确保没有两个请求同时拥有同一个 session。 -
runAgentTurn()— 用 flush-then-publish 管线包装上游 turn:监听session/event,flush 到 DO SQL,然后通过 WebSocket 发布事件。在 turn 期间绑定 shell 后端。 -
准入控制 —
createDurablePromptAdmitter在 persistence flush 之后才准入 prompt,确保用户消息在模型看到之前已持久化。
上游的 agent loop 在这个包装器内部原样运行——它不知道自己被观察并通过网络发布。
Turn 开始时,Edge 广播 host/session-status { running: true }。结束时广播 { running: false }。上游直接从内存读 agent.status;Edge 把这个翻译成网络帧。
Edge 完整支持上游的两种消息模式:
-
queue(排队)— 消息通过
agent.followup()进入 next-turn inbox。当前 turn 结束后处理。客户端通过session/queueWebSocket 帧看到待处理消息,可在处理前编辑或删除。 -
steer(引导)— 消息通过
agent.steer()进入 next-step inbox。在当前 turn 的下一个 step 边界处理。用于中途引导("停下手头的工作,专注做 X")。
updateQueue() 让客户端管理待处理消息:编辑文本、删除、或将排队消息提升为 steer。Edge 在每次 inbox 变更和重连 baseline 时广播 session/queue 帧,确保客户端始终显示当前的待处理状态。
- Agent 创建、session 绑定和销毁生命周期
- Inbox 管理和消息队列语义
- Step 管线(pre-step → request → streaming → tool execution → post-step)
- 作用域过滤事件分发
- 模型请求准备和重试策略
- Turn-stopping 协商(
agent/turn-stopping瀑布)
Edge 在上游 turn 基础上增加三项代价:
- 占位检查:每个 prompt 一次 Map 查找验证无并发 turn — O(1),亚微秒。
- Flush 屏障:每个事件在 WebSocket 发布前 flush 到 DO SQL。每事件增加约 1ms 同步 SQL 写入。上游在检查点边界 flush;Edge 逐事件 flush 以提供更强的持久性保证。
-
Shell 绑定:
EdgeShellBindings.bind()在 turn 期间关联 Computer VFS workspace 和 Agent — 一次 Map 插入,在finally中释放。
一个 Durable Object 实例(名为 'owner')管理所有 workspace 和 session——镜像了上游的单进程架构。activeTurns map 确保每个 session 最多运行一个 turn,不同 session 可在同一 DO 内交错执行。隔离来自应用层的作用域(cordis agent scope、VFS workspace 路径),而非独立的运行时实例。
当 session 已有活跃 Agent(来自之前未销毁的 turn),openAgentForTurn 复用它——无 Agent 创建开销。冷 session(DO 重启后)需要付 Agent 恢复代价:从 DO SQL 加载 session header + 事件日志 + 重建内存状态。
| 组件 | 分类 | Edge 代码 |
|---|---|---|
| AgentRegistry | 复用 | 一行 ctx.plugin() 调用 |
| AgentLoop | 复用 | 一行 ctx.plugin() 调用 |
| Turn 生命周期包装 | 桥接 |
runAgentTurn() + claimAndOpenAgent()
|
| 状态广播 | 桥接 |
host/session-status WebSocket 帧 |
关键观察:核心 Agent 基础设施完全运行上游代码。Edge 用 claim → flush → publish 管线包装每个 turn 来桥接 DO 和浏览器之间的网络间隙。Agent loop 不知道自己运行在 Cloudflare 上——它看到的是同样的 cordis context、同样的 session 和同样的工具注册表。
当前的单 DO 架构镜像了上游的单进程设计,但受 Cloudflare 平台特有的天花板限制:
- 内存:每个 DO 128 MB,所有活跃 session 共享——限制大上下文窗口下的并发 turn 数量。
- SQL 存储:每个 DO 10 GB,存放所有 session 的事件日志——长期使用的部署会逐渐逼近上限。
- 并发:DO 是单线程的——多个 session 交错执行但无法真正并行。
- Subagent 隔离:同一 DO 内的 Agent 共享内存,无法做资源隔离。
自然演进方向是 session-per-DO:每个 session 拥有独立的 Durable Object,独立的内存、存储和生命周期。这需要:
- 路由 DO(或入口 Worker)管理 workspace → session → DO-id 的映射。
- 分层 VFS:Agent 级共享存储(workspace 代码、配置)可跨 session DO 访问,加上 session 本地存储(临时文件、spill、工具输出)隔离在各自 DO 内。共享层可用 R2 或专用 workspace DO。
- Subagent via DO fork:子 Agent 作为独立 DO 启动,拥有自己的内存预算,通过 DO-to-DO fetch 将结果回传给父 Agent。
- Home
- Architecture
- Core & Scope
- Session & Persistence
- Model & Context
-
Execution & Tools
- Tools
- Bash
- Subprocess 🚫
- PTY Session 🚫
- Background Jobs 🚫
- Filesystem
- LSP Navigation 🚫
- Code Runtime 🚫
-
Web Access
⚠️ -
Skills
⚠️ - Workflow 🚫
- Subagent 🚫
-
Policy & Interaction
- Goal
- Approval 🚫
- Permission Presets 🚫
-
Sandbox
⚠️ - Plan Mode 🚫
- User Interaction 🚫
- Commands 🚫
- Schedule 🚫
- Message Feedback 🚫
- Platform & Access
- Development
- 首页
- 架构
- 核心与作用域
- 会话与持久化
- 模型与上下文
- 执行与工具
- 策略与交互
- 平台与接入
- 开发