agent-fleet/openspec/changes/adapter-cross-machine-revision/design.md
Zer4tul e39a16498c feat: dual execution model (SSH CLI + HTTP pull)
- ExecutionMode enum: SshCli (orchestrator dispatches) | HttpPull (agent pulls)
- SSH CLI executor: spawn remote agents via ssh + CLI template
- Local subprocess as SSH special case (localhost)
- HostConfig with capability matching and load-based selection
- Dispatch loop: scan created tasks → select host → execute → update
- CliAdapterConfig: CLI templates for Codex and Claude Code
- Structured prompt construction (Issue → goal/constraints/validation)
- Output parsers: Codex JSON, Claude Code JSON, raw fallback
- TaskStatus::ReviewPending + review_count loop limit
- Forgejo webhook: pull_request (opened→review_pending, merged→completed)
- Forgejo webhook: push events (task/* branch → last_activity_at)
- HTTP API: dequeue only returns http_pull tasks
- HTTP API: status update only for http_pull mode
- Token auth config for http_pull agents
- Adapter module rewritten: AgentAdapter trait removed → config-driven CLI templates
- New fields: execution_mode, assigned_host, branch_name, pr_title, last_activity_at, review_count
- 30/30 tests pass
2026-05-12 14:07:56 +08:00

5.8 KiB
Raw Blame History

Context

当前 adapter interface 基于 spawn 本地进程模式无法满足跨机协同的核心目标。实际使用中暴露了通知机制不可靠的问题Codex 完成任务后 Jeeves 收不到通知)。

核心认知转变:

  • Orchestrator 不调用 AgentAgent 调用 Orchestratorpull 模型)
  • Git/Forgejo 是状态追踪的 source of truthPR 生命周期 = 任务生命周期)
  • 通知 = Git 事件push → 进度信号PR opened → 完成通知PR merged → receipt 验证)

Goals / Non-Goals

Goals:

  • Agent 通过 HTTP API 主动拉取任务、更新状态、提交 receipt任何机器、任何语言
  • 利用 Forgejo PR webhook 作为可靠的状态追踪和通知机制
  • 消除"Agent 完成但无人知道"的问题
  • Agent client 可以是任何语言实现curl 就能交互)

Non-Goals:

  • 不实现 Agent 侧的 client SDKAgent 自己决定用什么语言/方式调用 HTTP API
  • 不实现 Orchestrator → Agent 的主动推送pull 模型足够Phase 2 可加 SSE
  • 不修改 Forgejo webhook 已有的实现(复用现有 POST /api/v1/webhooks/forgejo

Decisions

Decision 1: Pull 模型Agent 主动拉取任务)

选择: Agent 通过 POST /api/v1/tasks/dequeue 主动拉取

理由:

  • 跨机场景下 Orchestrator 无法主动连接 Agent防火墙、NAT、离线
  • Agent 最清楚自己什么时候有空
  • Pull 模型天然负载均衡——空闲 Agent 自然拉更多任务
  • 无需长连接、无需消息队列

替代方案:

  • Push 模型Orchestrator 推送):需要 Agent 暴露端点,复杂度高
  • 消息队列NATS/Redis增加基础设施依赖

Decision 2: Forgejo PR lifecycle 作为通知机制

选择: 利用 Git 事件push → PR opened → PR merged作为任务状态追踪

理由:

  • Forgejo webhook 已经实现,可靠性由 Forgejo 保证
  • PR 本身就是 code review 流程——天然对应任务的"完成→验证"流程
  • 解决了实际遇到的通知丢失问题:即使 Agent 直接通知失败Forgejo webhook 仍然会触发
  • PR merged = 自动 receipt 验证PR 存在且被 merge = 代码确实被接受)

替代方案:

  • SSE/WebSocket 推送:需要保持长连接,跨网络不可靠
  • Agent 回调 URL需要 Agent 暴露端点
  • 轮询:可行但延迟高,且不解决"Agent 完成后通知谁"的问题

Decision 3: Registry token 认证

选择: Agent 注册后获得 token后续请求需携带

理由:

  • 轻量级,不需要 OAuth 或 JWT
  • 防止未授权的 Agent 领取任务
  • token 在重新注册时刷新

Risks / Trade-offs

  • [Pull 延迟] Agent 需要定期 dequeue 轮询 → Agent 可以在 heartbeat 周期内顺便 dequeue不增加额外开销
  • [PR 必需] 强制要求 Agent 创建 PR → 非 PR 任务通过 /complete 端点完成,两条路径在 receipt 验证层汇合
  • [Forgejo 单点] Forgejo 挂了通知就断了 → Forgejo 本身是 Git source of truth挂了整个流程都停可接受
  • [死循环] Review 循环可能无限 → max_retries 限制 + review_count 跟踪

Key Design Principles (from community best practices)

基于 ChatGPT 讨论和社区最佳实践的几个核心原则:

  1. Agent 是纯函数 worker:输入 task + artifact输出 artifact + state change。不保留跨任务状态。
  2. 状态机驱动,不对话驱动:所有 Agent 只对共享状态SQLite + Forgejo读写由 Orchestrator loop 推进流程
  3. 结构化 handoffAgent 之间不传 chat history只传结构化 artifactreceipt、plan、review
  4. Git worktree 隔离:每个 task 独立分支,避免并发冲突
  5. Deterministic verification:不依赖 Agent 自我判断,用 cargo test / npm test 等确定性验证
  6. 80/20 原则80% 自动运行20% 人类介入(失败、架构决策、优先级调整)
  7. 外部调度 + 内部自治agent-fleet 只管理任务状态和 artifact 流转Agent 的执行 runtimehooks、compaction、sandbox、tool loop、session 管理)由 Agent 自己负责。agent-fleet 是 KubernetesAgent 是 Pod。
  8. 不替代 Agent runtimeClaude Code / Codex / OpenCode 的价值在于它们的 runtime不是模型本身。agent-fleet 不重新实现 tool loop、context compaction、patch management 等。

基于 ChatGPT 讨论和社区最佳实践的几个核心原则:

  1. Agent 是纯函数 worker:输入 task + artifact输出 artifact + state change。不保留跨任务状态。
  2. 状态机驱动,不对话驱动:所有 Agent 只对共享状态SQLite + Forgejo读写由 Orchestrator loop 推进流程
  3. 结构化 handoffAgent 之间不传 chat history只传结构化 artifactreceipt、plan、review
  4. Git worktree 隔离:每个 task 独立分支,避免并发冲突
  5. Deterministic verification:不依赖 Agent 自我判断,用 cargo test / npm test 等确定性验证
  6. 80/20 原则80% 自动运行20% 人类介入(失败、架构决策、优先级调整)

Migration Plan

  1. 新增 POST /api/v1/tasks/dequeue 端点
  2. 新增 POST /api/v1/tasks/{task_id}/status 端点
  3. 新增 GET /api/v1/tasks/{task_id} 端点
  4. 扩展 Forgejo webhook 处理:支持 pull_requestpush 事件
  5. 重写 src/adapters/mod.rs:从 AgentAdapter trait 改为 Agent Protocol 描述文档
  6. 新增 token 认证中间件
  7. 更新测试

Open Questions

(resolved — 见下方)

  • 非 PR 任务research、review如何触发完成通知 → 使用 POST /api/v1/tasks/{id}/complete + receipt与 PR 路径在 receipt 验证层汇合
  • Token 认证是否需要在 Phase 1 实现? → 必须在 Phase 1 实现,否则无法安全对接远程 Agent