## Context 当前 adapter interface 基于 spawn 本地进程模式,无法满足跨机协同的核心目标。实际使用中暴露了通知机制不可靠的问题(Codex 完成任务后 Jeeves 收不到通知)。 核心认知转变: - **Orchestrator 不调用 Agent,Agent 调用 Orchestrator**(pull 模型) - **Git/Forgejo 是状态追踪的 source of truth**(PR 生命周期 = 任务生命周期) - **通知 = 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 SDK(Agent 自己决定用什么语言/方式调用 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. **结构化 handoff**:Agent 之间不传 chat history,只传结构化 artifact(receipt、plan、review) 4. **Git worktree 隔离**:每个 task 独立分支,避免并发冲突 5. **Deterministic verification**:不依赖 Agent 自我判断,用 `cargo test` / `npm test` 等确定性验证 6. **80/20 原则**:80% 自动运行,20% 人类介入(失败、架构决策、优先级调整) 7. **外部调度 + 内部自治**:agent-fleet 只管理任务状态和 artifact 流转,Agent 的执行 runtime(hooks、compaction、sandbox、tool loop、session 管理)由 Agent 自己负责。agent-fleet 是 Kubernetes,Agent 是 Pod。 8. **不替代 Agent runtime**:Claude 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. **结构化 handoff**:Agent 之间不传 chat history,只传结构化 artifact(receipt、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_request` 和 `push` 事件 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