Architecture
What Infinia Harness emits, and why each piece is shaped the way it is. Everything here describes v0.7.0.
The compile model #
The input is one YAML file. The output is a native harness per target — not a runtime, not a wrapper process. Nothing of Infinia Harness stays resident while your fleet runs; the agents your CLI loads are ordinary files it already knows how to read.
┌──────────────────────────────────────────────┐
│ fleet.yaml │
│ pattern · agents[] · skills[] · handoff graph│
│ capabilities · loops · schedule · defaults │
└───────────────────────┬──────────────────────┘
│
┌───────────▼───────────┐
│ validate (schema + │
│ design-smell lint) │
└───────────┬───────────┘
│
┌─────────────────────┬───────────┴──────────┬─────────────────────┐
▼ ▼ ▼ ▼
┌────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Claude Code │ │ opencode │ │ goose │ │ _fleet/ │
│ agents/*.md │ │ agents/*.md │ │ recipes/*.yaml │ │ handoffs/ │
│ skills/SKILL.md│ │ commands/ skills/│ │ AGENTS.md │ │ LEDGER.md │
│ CLAUDE.md │ │ AGENTS.md │ │ sub-recipes │ │ runs/ knowledge/│
│ SubagentStop │ │ permission.task │ │ response. │ │ │
│ hook (gate) │ │ maps (gate) │ │ json_schema(gate)│ │ portable protocol│
└────────────────┘ └──────────────────┘ └──────────────────┘ └──────────────────┘
└─────────────────────┴──────────────────────┴─────────────────────┘
one fleet, three vocabularies,
one shared file protocol
The three CLIs differ in vocabulary, not in concept. Each has a named specialist with a prompt, a scoped permission model, an attached methodology, and a way to pass work on. The compiler targets that intersection and lets each adapter spend the differences.
The spec #
A minimal fleet is short. Every key below has a default:
fleet:
name: review-fleet
domain: "reviewing pull requests in a Rust service"
pattern: generate-verify
defaults:
capabilities: { read: true }
agents:
- name: change-analyst
role: "Reads a diff and states what it actually changes"
goal: "A change brief with every touched subsystem named"
capabilities: { read: true }
handoff:
to: [risk-reviewer]
artifact: change-brief.md
criteria:
- "Every changed file is accounted for"
- "Behavioural changes are separated from refactors"
- name: risk-reviewer
role: "Adversarially checks the brief against the diff"
goal: "A ranked risk list with file:line evidence"
capabilities: { read: true, run: true }
handoff:
to: []
Patterns #
The pattern is chosen from the shape of the data flow, not from taste. It sets the default handoff topology and the orchestrator's prompt.
| Pattern | Shape | Reach for it when |
|---|---|---|
pipeline |
Sequential stages, each consuming the previous handoff | Work has a natural order — analyse, then build, then review |
fanout |
Independent parallel workers, then one merger | Research sweeps and audits, where breadth beats depth |
generate-verify |
Producers paired with adversarial checkers | Output correctness matters more than throughput |
supervisor |
A coordinating lead plus specialists; the lead owns state | The work list is discovered as you go, not known upfront |
expert-pool |
A router plus on-demand specialists | Requests are heterogeneous and only some experts apply |
Capabilities #
Agents declare intent, not tool names. Each adapter maps the same five booleans onto its own permission model, so least privilege survives the port instead of being re-derived by hand for every tool.
| Declared | Claude Code | opencode | goose |
|---|---|---|---|
read | tools: allowlist | tools: booleans and permission: allow/deny maps | extensions, plus a stated read-only constraint |
edit | |||
run | |||
web | |||
spawn |
There is no permission surface to compile a capability into, so the constraint is emitted as an explicit statement in the recipe rather than an enforced boundary. That difference is stated in the generated output rather than papered over — a capability that is advisory on one target and enforced on two should not read identically on all three.
Cost control
model tiers (smart/fast/cheap) are
intents. They bind to nothing unless you supply a
defaults.claudeModels / opencodeModels /
gooseModels map — because a pinned model spawns that model even when the
user deliberately started a cheaper session, and fails outright where it is not on their
plan. effort and turns give you cost control that works on an
inherited model: they compile to Claude Code effort/maxTurns,
opencode variant/steps, and goose
settings.max_turns.
The handover protocol #
Every edge in the fleet graph carries an artifact and acceptance criteria. The protocol is file-based because files are the only channel all three tools share — which also makes fleet behaviour auditable after the fact and resumable after a crash.
The message is the doorbell; the file is the payload. Where a target has native agent-to-agent messaging, it is layered on top as a wake-up — never as the transport. A protocol that depends on messaging cannot be replayed, and cannot be read by a human deciding whether an agent actually did its job.
_fleet/
├── shared/ committed — what the team has learned (PR-gated)
│ ├── knowledge/ promoted, reviewed notes
│ ├── evolution/ proposals + decisions.jsonl
│ └── CHANGELOG.md
└── local/ gitignored — what my current run is doing
├── LEDGER.md my task rows: task, owner, depends-on, status, artifact
├── handoffs/ one file per completed edge
├── runs/ telemetry: gate verdicts, retries, corrections
└── scripts/ the gate + event-log hooks
Each handoff file carries a real brief — objective, output format, sources and tools, boundaries, and failed approaches — and consumers are told to cite it rather than restate it. Every paraphrase between producer and consumer loses detail, and the loss compounds down a chain.
Enforced gates #
Where a target can check something deterministically, the compiler emits the check instead of an instruction to remember it.
| Target | Mechanism | What it enforces |
|---|---|---|
| Claude Code | SubagentStop hook running validate-handoff.sh |
An agent cannot finish until its handoff file exists and carries every required section |
| opencode | permission.task maps compiled from the handoff graph |
An agent with no edge to another simply cannot see it in the task tool |
| goose | response.json_schema |
The handoff summary is validated against its declared shape at runtime |
Claude Code does not run project-level hooks until you accept its "trust this folder" dialog. Until you do, the handover gate is silently skipped and the fleet degrades to advisory instructions. This is the single most common reason a generated harness behaves less strictly than expected.
Workspace tiers #
Splitting the workspace stops a fleet's accumulated learning from living on one laptop, while stopping run logs from causing merge conflicts.
| Tier | Where | Holds |
|---|---|---|
| user-global | ~/.claude/skills/ | Methodology you reuse on every project |
| project-shared | _fleet/shared/ (committed) | What the team has learned — promoted by PR |
| project-local | _fleet/local/ (gitignored) | What your current run is doing |
| grid enterprise | RelataDB cortex | What everyone is doing and knows right now |
The promotion ladder is one-directional: nothing becomes reviewed team knowledge except
by landing in _fleet/shared/ through a pull request. The grid tier does not
shortcut it.
Self-evolution #
A generated harness records what its runs did, checks itself deterministically, and can propose its own improvements for review — with one model call in the whole system, and gates that never depend on it.
observe ──► evaluate ──► mutate ──► validate ──► promote
│ │ │ │ │
│ │ │ │ └─ proposal lands on a branch;
│ │ │ │ waits for `evolve --review`
│ │ │ └─ qa + eval must both pass — deterministic
│ │ └─ THE ONE MODEL CALL, and it may only touch
│ │ artifacts that evolution itself generated
│ └─ trigger discrimination against a held-out corpus,
│ staged 3/10/full, measured noise floor, paired baseline
└─ run telemetry the handover gate was already computing and throwing away
| Command | What it does |
|---|---|
fleetsmith qa | Spec gate, per-target compile, handoff graph checked against compiled output, capability leaks, loop bounds, drift |
fleetsmith eval | Whether skills actually fire, on prompts that should and should not trigger them |
fleetsmith evolve | Proposes changes on a branch; rollback is git revert fleet-gen/<n> |
Every agent and skill carries origin: human|evolved, and the loop may
only modify what it generated. The validator, QA battery, eval corpus and tests are
hard-coded off limits — enforced in-process and in CI, because a control
living inside the agent's own runtime is reachable by inputs that influence the agent.
The Darwin Gödel Machine, scored by a function counting marker tokens, deleted the
markers rather than fix the behaviour.
The Intelligence Grid enterprise #
Git makes team knowledge shareable, but only as fast as the last merged PR. That leaves four asks unanswered: agents cannot see each other's in-flight work, there is no semantic recall across the team mid-task, organisational context has no ingestion path, and there is no central governance. The grid is a fourth tier that answers them — and it is a projection, never an authority.
developer A laptop developer B laptop
┌─────────────────────────┐ ┌─────────────────────────┐
│ fleet agents │ │ fleet agents │
│ │ read/write (files) │ │ │
│ _fleet/local/ │ │ _fleet/local/ │
│ LEDGER.md handoffs/ │ │ LEDGER.md handoffs/ │
│ grid/peers/B/ ◄──────┼── of B's work │ grid/peers/A/ ◄──────┼── read-only
│ ▲ │ │ ▲ │ projection
│ fleetsmith grid sync │ │ fleetsmith grid sync │
└───┬─────┴───────────────┘ └───┬─────┴───────────────┘
│ push: /ingest (typed rows) │
│ pull: SSE /graph/changes + cursor │
▼ ▼
┌──────────────────────────────────────────────────────────────────┐
│ RelataDB cortex (customer-run, BYOL) │
│ grid ontology: FleetTask · ActorPresence · HandoffPointer · │
│ RunEventSummary │
│ memory verbs: MemoryItem · ProcedureMemory · DecisionRecord │
│ org knowledge: OrgDocument (meetings, calls, discussions) │
│ governance: purpose registry · ACL · audit chain · AS OF │
└──────────────────────────────────────────────────────────────────┘
▲ ▲
fleetsmith grid import cortex console (board, audit,
(meeting notes, transcripts) approvals, equip, tokens)
Agents never call the grid. They read files — the same files they would read with no
cortex at all, plus read-only peer projections under
_fleet/local/grid/peers/<actor>/ and one GRID.md rollup.
That keeps the design identical across all three targets and makes degradation trivial:
an unreachable cortex just means stale files.
Load-bearing decisions #
Each was forced by evidence. Reversing one means re-checking its source.
| Decision | Why |
|---|---|
Task and presence state go through /ingest as our own ontology types, not the memory verbs |
/memory/* writes bypass governed_upsert, so they never reach the changefeed. Only /ingest rows get WAL, ACL and fan-out |
Sync is an SSE wake-up plus cursor reconciliation, never /watch/stream |
/watch/stream is a stateless per-request poll whose registry is lost on restart. The SSE buffer is 1000 with gap notices — so SSE is only ever the doorbell and the cursor pull is the payload |
| Single-writer rows: every row keyed by actor | The engine has no CRDTs and no client-facing merge. Keying by actor makes concurrent-write conflicts impossible by construction |
| Rows carry pointers and digests, never handoff bodies or file contents | Server-side conditional-ACL enforcement is not yet wired into every call site; client-side redaction and minimal payloads are the defence until it is |
| One org = one tenant | Sub-tenant namespaces are stored but not enforced by the engine. Never build isolation on namespaces |
| Deterministic overlap checks; model judgment only inside existing agent turns | Project invariant since v0.5: deterministic checks carry every gate. The grid adds zero model calls |
Degradation #
Every enterprise capability names the core answer it falls back to. Nothing is enterprise-only.
| Capability | Degrades to |
|---|---|
| Cross-developer overlaps | Git file-intersection across local branches — grid overlaps --git-only needs no cortex and no network at all |
| Org knowledge | Filtering committed _fleet/shared/knowledge/ frontmatter directly |
| Semantic recall | Token overlap over the same committed notes |
| Audit | Local run events from _fleet/local/runs/ |
No configuration produces plain OSS behaviour with no output at all. An unreachable or license-expired cortex produces exactly one warning, stale-marked grid files, and runs that still complete. A cortex problem is never a run failure.
The ee/ boundary #
Core is MIT with one runtime dependency and is complete on its own — the file backend and git are the supported open-source answer, forever. Everything enterprise ships as AGPL-3.0-only in a separate package.
Four rules, each enforced in CI rather than documented and hoped for:
- No core file may import from
ee/. - Every enterprise source file carries its SPDX header.
- No RelataDB binary or source is vendored anywhere.
- Every enterprise capability names its degraded core answer.
Core loads the enterprise package fail-soft, by ordinary module resolution. Removing it leaves core byte-identical to open-source behaviour — a property the test suite checks rather than asserts.
The cortex engine is never shipped, vendored or patched here. You run your own instance; Infinia Harness speaks REST to it. The installer can start one for you in Docker, but the image and its license remain the vendor's.