**Goal:** Enable OpenHands + omniroute to autonomously execute Echodo convoys by mapping roles to model profiles and integrating Agent Skills format.
---
## Executive Summary
Echodo's convoy system (defined in `.convoys/*.md` with role-based `model_policy`) currently requires Cursor to execute per-role briefs. This plan replaces Cursor with OpenHands as the runtime harness, using omniroute's model profiles (`auto`, `auto/coding`, `auto/reasoning`, `auto/coding-pro`, `auto/reasoning-pro`) to route each role to the appropriate model.
The main insight: **Your convoy structure already works. We're just swapping the agent harness and making skills discoverable.**
**Key changes:**
1. Convert role-prompt rules to `.agents/skills/` in SKILL.md format (Agent Skills spec)
### Phase 1: Agent Skills Format Conversion (M estimate)
**Goal:** Make repo-integrated skills discoverable by OpenHands via SKILL.md format in `.agents/skills/`.
**Why:** Your current `.cursor/rules/*.mdc` files are Cursor-specific. OpenHands reads `.agents/skills/*/SKILL.md` (per Agent Skills spec). Converting moves you from Cursor-only to Cursor + OpenHands + any harness that supports Agent Skills.
- **When to invoke:** When working with `plans/`, `markdown_backlog_items`, or the Echodo markdown import
- **What it teaches:** How backlog frontmatter maps to DB, how `pnpm --filter @tasks/database watch:markdown-backlog` works, the contract between `.md` and `markdown_backlog_items`
- **When to invoke:** When routing models, configuring aliases, or understanding how the orchestrator selects models
- **What it teaches:** The resolution order (brief override → convoy policy → workspace routes → pipeline defaults), omniroute profile mapping, how `resolveModel(workspace, roleId)` works, how model metadata flows to `agent_runs` and `convoy_events`
- [ ] Each SKILL.md has frontmatter (name, description) + at least 3 sections
- [ ]`skil --validate .agents/skills/*/SKILL.md` passes (or equiv. local validation)
- [ ] Skills are referenced in `AGENTS.md` under the "Skills available" section
- [ ] Agent can invoke them via `/skill` command or model-invocation within OpenHands
---
### Phase 2: OmniRoute Profile Mapping & Model Policy Doc (S estimate)
**Goal:** Document how omniroute profiles map to roles and how the orchestrator uses `model_policy` to route.
**Why:** Your `model_policy.roles` in convoy frontmatter lists role names + model aliases. Those aliases need to resolve to omniroute **profiles** (e.g., `auto/coding`, `auto/reasoning`) so the worker can ask omniroute "give me the model for `claude-planning`" and get back the current endpoint.
3. resolveModel(workspace, job.roleId) → model spec
4. Create OpenHands session with bootstrap (brief context + skills)
5. Run tool loop (agent interacts with codebase)
6. On success: push branch, call forge PR endpoint
7. Log complete_task + convoy_events.role_complete with model metadata
8. Return to step 1
```
- **Config:** Add env var `WORKER_SESSION_TYPE=openai-client | minimal | openhands` (default: minimal for backward compat, set to `openhands` to use new flow)
- Phase 1 + 2 are sequential (skills first, then routing docs)
- Phase 3 can start once Phase 1 + 2 are done
- Phase 4 requires Phase 3 complete
---
## Agent Instructions for Each Phase
### For Agents Working on Phase 1 (Skills)
1.**Before writing:** Read the existing `.cursor/rules/*.mdc` files in this repo + the referenced SKILL.md files from mattpocock/skills, anthropics/skills
2.**Structure:** Follow the Agent Skills spec (frontmatter + markdown sections)
3.**Validation:** Each skill should be invokable by model (e.g., `/skill backlog-sync` or implied when needed) and have 3–4 substantive sections
4.**Test:** Run locally with OpenHands or Claude Code to verify skills load
5.**Acceptance:** PR reviewer checks that skills have frontmatter + clear When-to-Activate section
### For Agents Working on Phase 2 (Routing)
1.**Before writing:** Read `docs/adr-model-routing.md` fully + understand how `model_policy` works in `.convoys/*.md`
2.**Assumption:** OmniRoute cloud is the target (not local-only), and omniroute has 5 profiles (auto, auto/coding, auto/coding-pro, auto/reasoning, auto/reasoning-pro)
3.**Output:** Two markdown files (mapping + setup), both human-readable and copy-pasteable examples
4.**Validation:** Walk through the flow: convoy sets `model_policy.roles`, orchestrator calls `resolveModel`, worker receives model spec
5.**Test:** No automated test needed; human walkthrough in Phase 4
### For Agents Working on Phase 3 (Worker Integration)
**Goal:** Make submatter runtime-agnostic via Agent Client Protocol (ACP).
**Why:** ACP is an emerging standard that allows OpenHands, Claude Code, Gemini CLI, and other runtimes to be swapped via a single protocol. This prevents vendor lock-in and lets operators choose the best runtime per task.
**Tasks:**
1. Add `HarnessType: "acp"` to shared types
2. Create `apps/worker/src/executor/acp-executor.ts` — implements ACP client (connects to any ACP-compatible server)
3. Support ACP discovery via `/.well-known/agent.json` (runtime metadata)
4. Add `acp` harness type to executor registry
5. Support sub-agents via ACP Task Tool Set
**ACP-compatible runtimes:**
- OpenHands (primary)
- Claude Code (Anthropic)
- Gemini CLI (Google)
- Cursor (experimental)
- Custom (any ACP server)
**This is NOT required for v0.1 testing.** Ships after v0.1 ships and proves out.
2.**Deploy OpenHands Agent Server** — Docker container on Dokploy (CT 102), worker connects via internal Docker DNS
3.**Scale briefs** — Extend to 5–6 briefs per convoy (architect → implementer → reviewer → ops-copilot → etc.)
4.**Scale roles** — Add `role-docs-writer`, `role-security-auditor`, `role-performance-reviewer` as needed
5.**Scale models** — Extend omniroute integration to support Claude/OpenAI/Gemini APIs side-by-side
6.**Migrate Cursor convoys** — For convoys that have historically run in Cursor, run them via OpenHands instead (backward compat: human-initiated, not automated)
7.**ACP harness** — After v0.1 ships, add ACP support to enable runtime-agnostic agent execution