ADR 0004 — Engine pluralism: harnesses as drivers behind the ACP socket
In short
Section titled “In short”Qren is built today on a single supplier’s coding assistant, which is a real risk to the business if that supplier’s price or terms change. This decides that Qren can drive several such assistants — we call one an engine — through one standard connection, much as a computer prints to different printers through one port. Each engine is used on the client’s own subscription; we never resell anyone’s model time. Qren keeps the parts that carry the value — who may do what, what needs approval, what gets recorded — and treats the assistants underneath as swappable. A second engine is to be proven early and cheaply, so the first never quietly becomes the only one.
Context
Section titled “Context”Qren is currently built end-to-end on Claude Code. That concentration is an existential dependence (Anthropic ToS/pricing was ranked threat #2 in the 2026-08-19 market landscape), and it forecloses real capability: multiple subscriptions (Claude + Codex/ChatGPT + Kimi) multiply rate limits and strengths, and a local engine is the only path to an airtight sovereignty claim. A previous model-agnostic attempt (aos-execution-layer) stalled.
Abstraction depth options: (a) model-level abstraction (one internal LLM API) — reduces every engine to the dumbest shared subset and destroys harness behaviors (tools, skills, hooks, sub-agents); (c) one harness calling other models as tools — does nothing for the dependence risk.
Evidence from the Buzz dissection (2026-08-17, validated live on this machine): agents connect over ACP (Agent Client Protocol); claude, codex, kimi, goose all speak it via their CLIs; per-provider special-casing is ~40 lines; auth is each vendor’s own subscription login — no API keys in any process. Per-agent definition = engine + model + effort + system prompt/persona + tool scope.
Decision
Section titled “Decision”- The unit of pluggability is the engine, not the model — an engine is a complete agent harness (Claude Code, Codex CLI, Kimi CLI, a local MLX/Ollama runner). Qren orchestrates engines; it never abstracts them into a common prompt/tool layer. Engines stay native; Qren stays the kernel.
- ACP is the engine socket. Any ACP-speaking binary can be an engine. No bespoke per-engine integration beyond thin adapters.
- Qren’s own layer sits above the socket, at the level of work: sessions, workspaces, principals, trust levels, the approval broker, audit, and the task graph. Permission enforcement is Qren’s, never delegated to an engine’s own permission mode (Buzz’s bypass-permissions default is the documented anti-pattern).
- An agent definition binds: identity (principal/keypair) + engine + model + effort + system prompt/persona + skill/tool scope + workspace memberships. Sandboxing = workspace membership + scope + broker, uniform across engines.
- Engine priority: Claude Code is the primary driver. Additional subscription engines (Codex, Kimi) are routed to by policy where their limits or strengths pay off. Local engines come last, as the sovereignty-hardening option — built as an option, not chased to parity.
- BYO subscription per engine, per client. Qren never intermediates model billing (Anthropic ToS compliance; same rule generalized to every vendor).
Consequences
Section titled “Consequences”- The correction loop, arms, and companion must express engine-agnostic requirements (a task + a scope), not Claude-specific prompts, at their boundaries; engine-specific prompt craft lives inside adapters.
- The second socket (Codex or Kimi) should be proven early and cheaply to keep the interface honest — one working second engine prevents silent Claude-coupling.
- A universal prompt/tool translation layer is explicitly out of scope.
- Engine health/auth probing (vendor CLI login state) becomes a first-class instance health check.