Kai: An Orchestration Harness for OpenCode
Request routing, a parallel engineering pipeline, quality gates, and persistent project memory — layered on top of OpenCode.
Kai: An Orchestration Harness for OpenCode
Request routing, a parallel engineering pipeline, quality gates, and persistent project memory — layered on top of OpenCode.
Driving a single coding agent by hand works until it doesn't. You ask for a feature, it writes the code, and whether that code gets reviewed, tested, or documented depends entirely on whether you remembered to ask. Run the same request twice and you get two different shapes of work. The agent is capable; the process around it is ad hoc.
Kai is a harness that removes the improvisation. It is a set of agent definitions for OpenCode that turns an open-ended request into a fixed, inspectable pipeline: classify the work, route it to the right specialist, run review and testing and documentation in parallel, check the result against explicit gates, and report. It adds no new runtime — it is a configuration layer that constrains how OpenCode's agents are used.
flowchart LR
U["👤 Request"] --> K["Kai (primary)"]
K --> C{"Classify"}
C -->|"trivial"| FT["Fast-track agent"]
C -->|"investigation"| R["@research"]
C -->|"feature / refactor"| P["Engineering pipeline"]
FT --> RPT["Report"]
R --> RPT
P --> RPT1. What Kai is
OpenCode lets you define agents as markdown files. Kai is a self-contained agents/ folder you copy into your OpenCode config:
cp -r agents/ ~/.config/opencode/agents/One agent, kai.md, is configured as mode: "primary" — it is the only agent you talk to. Every other agent is a mode: "subagent" that activates only on a structured DIRECTIVE from Kai. There is no separate daemon, no orchestration server, and no change to the underlying model. The behavior lives entirely in the agent definitions, which makes the whole system auditable: the pipeline is text you can read.
The trade is explicit. You give up the freedom to poke individual agents directly, and in return you get a request flow that runs the same way every time.
2. Routing: a fixed request lifecycle
Every request, regardless of size, moves through the same six steps:
Analyze → Classify → Route → Orchestrate → Validate → Report
Classification is table-driven. Kai maps a request to one of eleven types, and each type resolves to a specific handler — there is no per-request guessing about who does the work:
| Request | Routed to |
|---|---|
| Typo / formatting | @doc-fixer |
| Small code change, dependency bump | Fast-track agent |
| Open-ended investigation | @research |
| New feature / refactor | Engineering pipeline |
| Tech-debt assessment | @refactor-advisor |
The agents are grouped by function — a fast-track team for cosmetic and low-risk changes, a research team for investigation and claim verification, an engineering team for the full build pipeline, a learning team for failure analysis and tech-debt detection, and a few utility agents for summaries and ticketing. Routing is deterministic: the same class of request always lands in the same place.
3. The engineering pipeline and parallelism
The interesting case is a real feature or refactor, which fans out into a pipeline:
flowchart LR
A["@architect"] --> D["@developer"]
D --> RV["@reviewer"]
D --> T["@tester"]
D --> DOC["@docs"]
RV --> M["Merge"]
T --> M
DOC --> M
M --> OPS["@devops"]@architect produces a design, @developer implements it, and then @reviewer, @tester, and @docs run concurrently — they each depend only on the developer's output, not on one another, so there is no reason to serialize them. The concrete payoff is wall-clock time: three reviews for the latency of one.
The re-run logic is selective. If @reviewer finds a critical issue, only @developer runs again; the test and documentation results from the previous round are preserved rather than recomputed. Parallel where the work is independent, sequential only where a quality gate demands it.
4. A typed handoff contract
Agents do not pass each other free-form prose. Every transfer uses a YAML handoff schema with a fixed shape:
HANDOFF:
metadata:
from: "@developer"
to: "@reviewer"
task_id: "..."
phase: "review"
deliverables:
- name: "..."
path: "..."
status: "complete | partial | blocked"
quality_summary:
issues_found: 0
issues_resolved: 0
duration: "..."
context_for_next:
focus_areas: ["..."]
known_issues: ["..."]Specialist roles extend this with their own completion reports (DEVELOPER_COMPLETION_REPORT, TEST_COMPLETION_REPORT, and so on), so the interface between agents is structured rather than improvised.
There is a security property worth stating plainly: handoff text fields — and fetched web content, and the code under review — are treated as untrusted data. A receiving agent never executes instructions it finds in a handoff, a dependency, or a page it fetched. That is ordinary engineering hygiene applied to a multi-agent system, where the "input" can include code an LLM wrote.
5. Persistent project memory
The part that compounds is the .kai/ directory, written into each project:
.kai/
├── memory.yaml # master index
├── conventions/ # detected coding style, naming
├── decisions/ # architecture decision records
├── postmortems/ # failure analyses
├── tech-debt/ # prioritized register
└── preferences/ # workflow preferencesmemory.yaml records the project's languages, package manager, and test runner, plus a set of active_prevention_rules accumulated from past runs:
project:
languages: ["TypeScript"]
package_manager: "npm"
test_runner: "jest"
active_prevention_rules:
- id: "PM-2026-001"
when: "..."
action: "..."On pipeline start, Kai loads these prevention rules as pre-flight checks, hands detected conventions to the developer, and surfaces tech-debt flags as warnings. The effect is that the system stops re-discovering the same facts about a codebase every session — the conventions, the prior decisions, the failure modes are already on disk. Write access to .kai/ is restricted to Kai, @postmortem, and @refactor-advisor; every other agent reads it but cannot mutate it.
6. Guardrails and bounded execution
A harness is only useful if it fails predictably. Kai enforces five quality gates a change must clear before it advances:
- Architecture — design is reviewed and risk-assessed
- Code — no critical/high security findings, clean linting
- Testing — ≥80% coverage, 100% pass rate
- Documentation — APIs documented, examples runnable
- Deployment — CI green, staging verified
Execution is bounded on several axes. A retry budget caps rework — ten retries across the whole pipeline, three per agent, two per phase — and once it is exhausted (or an agent fails three times running) a circuit breaker halts the run, summarizes the failure, and hands the decision back to the user instead of looping indefinitely. Per-agent timeouts and an overall pipeline ceiling bound the time. Filesystem access is scoped to the project root, secrets and credential files are off-limits without explicit confirmation, and a deny list blocks destructive commands. Agents are even temperature-tuned by role — low for deterministic work like coding and testing, higher for writing and design — so the variance matches the task.
7. What it does, and what it doesn't
Kai is a workflow-and-memory layer over OpenCode. It does not replace OpenCode, introduce a new runtime, or change the model doing the work. What it changes is the process: a deterministic routing table instead of ad-hoc prompting, an enforced review/test/docs pass instead of optional ones, parallel execution where the work allows it, and a project memory that carries context across sessions. You trade some flexibility for repeatability.
One of those enforced steps — the quality gates, the coverage threshold, the postmortem register — is a concrete, if narrow, answer to the verification problem laid out in The AI Verification Debt: the cheapest place to verify generated code is in the pipeline that generated it, before a human ever sees it.
That is the whole pitch. Not a smarter agent — a more disciplined one.
Kyberneees, 2026