- 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
5.8 KiB
5.8 KiB
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 讨论和社区最佳实践的几个核心原则:
- Agent 是纯函数 worker:输入 task + artifact,输出 artifact + state change。不保留跨任务状态。
- 状态机驱动,不对话驱动:所有 Agent 只对共享状态(SQLite + Forgejo)读写,由 Orchestrator loop 推进流程
- 结构化 handoff:Agent 之间不传 chat history,只传结构化 artifact(receipt、plan、review)
- Git worktree 隔离:每个 task 独立分支,避免并发冲突
- Deterministic verification:不依赖 Agent 自我判断,用
cargo test/npm test等确定性验证 - 80/20 原则:80% 自动运行,20% 人类介入(失败、架构决策、优先级调整)
- 外部调度 + 内部自治:agent-fleet 只管理任务状态和 artifact 流转,Agent 的执行 runtime(hooks、compaction、sandbox、tool loop、session 管理)由 Agent 自己负责。agent-fleet 是 Kubernetes,Agent 是 Pod。
- 不替代 Agent runtime:Claude Code / Codex / OpenCode 的价值在于它们的 runtime,不是模型本身。agent-fleet 不重新实现 tool loop、context compaction、patch management 等。
基于 ChatGPT 讨论和社区最佳实践的几个核心原则:
- Agent 是纯函数 worker:输入 task + artifact,输出 artifact + state change。不保留跨任务状态。
- 状态机驱动,不对话驱动:所有 Agent 只对共享状态(SQLite + Forgejo)读写,由 Orchestrator loop 推进流程
- 结构化 handoff:Agent 之间不传 chat history,只传结构化 artifact(receipt、plan、review)
- Git worktree 隔离:每个 task 独立分支,避免并发冲突
- Deterministic verification:不依赖 Agent 自我判断,用
cargo test/npm test等确定性验证 - 80/20 原则:80% 自动运行,20% 人类介入(失败、架构决策、优先级调整)
Migration Plan
- 新增
POST /api/v1/tasks/dequeue端点 - 新增
POST /api/v1/tasks/{task_id}/status端点 - 新增
GET /api/v1/tasks/{task_id}端点 - 扩展 Forgejo webhook 处理:支持
pull_request和push事件 - 重写
src/adapters/mod.rs:从 AgentAdapter trait 改为 Agent Protocol 描述文档 - 新增 token 认证中间件
- 更新测试
Open Questions
(resolved — 见下方)
非 PR 任务(research、review)如何触发完成通知?→ 使用POST /api/v1/tasks/{id}/complete+ receipt,与 PR 路径在 receipt 验证层汇合Token 认证是否需要在 Phase 1 实现?→ 必须在 Phase 1 实现,否则无法安全对接远程 Agent