agent-fleet/openspec/changes/dual-execution-model/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

83 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Context
`adapter-cross-machine-revision` change 设计了纯 Pull 模型Agent 主动调 HTTP API但分析后发现 Pull 模型不是 subprocess CLI 的跨机等价——控制权、上下文传递、生命周期管理都不同。
真正的跨机等价是 **SSH + CLI**Orchestrator 通过 SSH 在远程主机上 spawn Agent CLI与本地 subprocess 完全一致的执行模型。
同时HTTP Pull 对外部 AgentOpenClaw/Jeeves、Hermes仍有价值。因此需要双执行模型。
## Goals / Non-Goals
**Goals:**
- SSH + CLI 作为主执行模式Orchestrator 主动调度、构造上下文、控制生命周期)
- HTTP API 保留给外部 Agent 自主接入
- 每种 Agent 类型定义为 CLI 模板 + 输出解析器
- 远程主机管理SSH 连接、CLI 可用性检查)
**Non-Goals:**
- 不实现 Agent daemonPhase 1 用 SSH + CLI 足够)
- 不实现动态主机发现Phase 1 静态配置)
- 不实现容器化执行(不用 Docker/Kubernetes
## Decisions
### Decision 1: SSH + CLI 是 subprocess 的跨机等价
**选择**: Orchestrator 通过 SSH 执行远程 Agent CLI
**理由**:
- 控制流与本地 subprocess 完全一致
- 上下文由 Orchestrator 构造,通过 CLI 参数传入
- Agent 不需要预运行,不需要 daemon
- 唯一前提SSH 免密登录 + 目标机器装了 CLI
**替代方案**:
- HTTP Pull控制权反转上下文传递难解决
- Agent daemon复杂度高每台机器多一个服务
- 容器化:更复杂,需要 container runtime
### Decision 2: HTTP Pull 作为补充模式
**选择**: 保留 HTTP API 给外部 Agent
**理由**:
- OpenClaw/Jeeves、Hermes 有自己的调度,不需要 Orchestrator 启动
- 它们只需要查询/更新任务状态
- 两种模式通过 `execution_mode` 字段区分
### Decision 3: Adapter = CLI 模板 + 输出解析器
**选择**: 不实现 AgentAdapter trait而是配置驱动
**理由**:
- CLI 模板可以通过配置文件定义,无需编译
- 不同 Agent 的差异主要在 CLI 参数和输出格式
- 新增 Agent 类型只需要加配置,不需要写代码
### Decision 4: 本地执行作为 SSH 的特例
**选择**: Orchestrator 所在机器的 Agent 用本地 subprocess不经过 SSH
**理由**:
- 避免 SSH loopback 的开销和配置
- subprocess 是 SSH 的本地特例,逻辑统一
## Risks / Trade-offs
- **[SSH 密钥管理] 需要配置免密 SSH** → 用 SSH agent forwarding 或 deploy key标准运维实践
- **[长时间运行] SSH 连接可能超时** → 用 `ssh -o ServerAliveInterval=60`,或改用 SSH multiplexing
- **[CLI 版本差异] 不同机器可能装不同版本** → health check 时验证版本
## Migration Plan
1. 新增 `src/execution/` 模块SSH executor、CLI template、output parser
2. Task 模型添加 `execution_mode``assigned_host` 字段
3. 新增 `[hosts]` 配置 section
4. 实现 Orchestrator dispatch loopssh_cli → SSH 执行http_pull → 等待 Agent dequeue
5. 保留并调整 HTTP API 端点dequeue 仅限 http_pull 任务)
6. 更新测试
## Open Questions
- SSH 库选择:`ssh2` crate vs `tokio::process::Command` + 系统 `ssh` 命令?
- 是否需要支持 SSH jump host通过跳板机连接目标机器