judge-loop
A step runs, a judge scores it against its declared goal, the loop decides: iterate, hold, or block.
Where agents, tasks, knowledge, and your repositories become one governed system — all of it declared as contracts, all of it auditable.
Agents are configuration
An agent is a typed, schema-pinned entity in registry/agents/. The
five-piece contract set — Go types + loader, YAML, JSON schema, contract
tests, docs — means a manifest that doesn’t validate doesn’t exist:
name: developer
runtime: cli # cli · docker · http
provider: local-dev # provider registry reference
model: qwen3-coder-30b # must exist on the provider
persona: implementer # engine-owned base prompt + persona
prompt_mode: minimal
goal: ship the reviewed change
sandbox: workspace-write # restricted · workspace-write
mcp_servers: [aio-tools] # default-deny: only these cross the wire
knowledge:
scopes: [project, fleet] # wiki read scope, enforced at the tool
env_allowlist: [HOME, PATH] # everything else is absent
progress_timeout: 10m # silence past this = named kill
A2A first
Every agent advertises an A2A AgentCard (name, skills, capabilities)
published to a shared KV store at worker boot, and answers on governed
subjects — aio.a2a.discovery, aio.a2a.card.<agent>,
aio.a2a.send.<agent>, aio.a2a.tasks.get.<task-id>. A peer — or the
console — can discover the fleet and hand work to a named agent over the
bus, with no bespoke integration per harness.
A2A speaks HTTP by specification — AiOverload keeps the dialect but
not the transport state. Inbound sends are wrapped into ordinary
runs: an A2A message becomes run.started, step.dispatched,
gate.decided — dispatched, gated, and judged as events on the log, with
task status mirrored back to the caller. The wire stays compatible with
the protocol; the state is event-sourced. That is what makes high
availability a deployment detail instead of a rewrite: when the fleet
outgrows one box, redundancy and failover ride JetStream — not HTTP
connection affinity.
Honest scope, again: ad-hoc A2A sends become single-turn runs today —
same gate as workflow steps, input-required on hold, rejected on
block — while cancel, multi-turn, and message dedup are tracked work.
The resident runtime’s assistant persona will ride this wire with
session-continuous memory on top.
Define once
Everything the engine serves is declared, reviewed like code, and validated by contract tests. The walkthrough, in three files:
1. The provider — what serves the model, and on what terms:
id: local-dev
protocol: openai # wire dialect
hosting: self-hosted # self-hosted · cloud
management: external # the platform loads models on demand
models:
- id: qwen3-coder-30b
context_length: 131072 # capacity is a contract
parallelism: 2 # declared concurrency slots
single_model: true # switching exclusivity, enforced
2. The agent — persona, access, tools (the manifest above): who it is, what it may touch, what it may call.
3. The platform — where it runs. Today: subprocess (cli) and
Docker, per the platform-profiles decision — one container contract,
two drivers. Kubernetes is the main goal: the same contract served by
a K8s driver (pods, PVC-backed workspaces, no Docker-in-Docker), engaged
deliberately, not bolted on.
Intent in git, reality at the boundary. The manifest declares; the sidecar materializes; the agent can reach nothing the registry didn't name.
The task plane
Tasks are managed work items — event-sourced like runs, with a lifecycle on the task-events stream and a folded state in KV. Two fields make them governable:
intent: — required, human-auditable. What this is for, in prose an
operator can judge.acceptance: — required, machine-checkable. Verdicts on named
steps, non-empty outputs, existing artifacts, green test commands. At
least one machine gate, because prose criteria are input to a review
step, never the done signal.Around them: scope declarations (repos, paths_in, paths_out), a
priority for queue admission, dependencies between tasks, and epics that
roll up their children. The console’s task plane is the operator surface —
a picker with intent/scope/acceptance previews, typed forms for the
workflow’s declared vars, and lifecycle controls (start, pause, resume,
cancel) with every mutation audited as task.* events.
An agent — or, soon, the resident manager — files a task with POST /api/tasks; a human starts it. Filing is audited; execution is governed;
nothing auto-dispatches without a gate or an approval.
The console is real
The operator console is not an afterthought admin page stapled to the
API. It is a Vite + Preact + TypeScript SPA served by the engine,
with an Orval-generated typed client built from the OpenAPI contract —
the same contract the CLI speaks — and live updates over SSE, not
polling. The committed dist/ is rebuilt only through a pinned,
reviewable container build, and the legacy dashboard was retired only
after the new console reached parity with it.
Said with the usual honesty: it is young, parts are still being rebuilt, and it is the surface the roadmap invests in first — compose, watch, govern, learn. But it exists, it is tested at the transport level, and it is governed by the same event log as everything else.
GitOps
The served fleet converges from a fleet directory — a master repo plus per-project overlays — so the registry you review in git is the registry the engine serves:
The problem: the fleet drifts from the repo — someone hot-fixes a manifest on the box, and three weeks later nobody can say which agents the platform actually runs. The answer: the directory converges the served fleet from git, and drift is loud in both directions.
.aio/ overlays: add-only, closed world.Specialization without redefinition: overlays are
add-only — a colliding entity is a named overlay_collision, never a
silent override. Project var defaults consume declared workflow vars only
(unknown_project_var is refused). The overlay is closed-world: nothing
executable lives in .aio/.
an issue becomes work
intent: from the body, machine acceptance:, lifecycle writes flowing
back to the thread.a project specializes
deploy-check.yaml plus var defaults; it’s served
at the next sync. A colliding name is a named overlay_collision —
never a silent override.a hand-edit is caught
Issues first
The task plane’s front door is not a web form — it is your issue
tracker. A GitHub issue or a GitLab work item becomes a governed task:
the issue body carries the intent:, the acceptance bundle names the
machine gates, and lifecycle writes flow back to the issue so the thread
your team already reads stays the record it always was.
And the data posture follows the same rule — almost nothing lives only inside the app:
This is the anti-“black box” architecture: governance you can replay — every decision an event, every artifact in git.
Knowledge plane
Long-term memory is not a prompt appendix; it is a governed read model over a knowledge base that lives in your repos — parsed in the open Knowledge Format (OKF v0.2): one concept per page, typed frontmatter — howto, reference, decision, pitfall, convention, index — strict for our bundle, tolerant for foreign ones, every breach named.
Agents reach it through exactly two scoped tools — knowledge/search
(metadata and pointers) and knowledge/get (one page) — over
request/reply on the bus:
knowledge: scopes: [project, fleet] — no block, no access (knowledge_scopes_not_declared);knowledge_scope_refused) — never an empty result pretending nothing
exists;project page in the master wiki
is a named scope_containment_violation, recorded and skipped;The same read model powers the console’s wiki surface — humans and agents
read the same pages, through gates sized for each. And because the pages
are files in the master wiki/ tree (or a project’s declared
wiki_path), the knowledge base is reviewed, versioned, and forked like
everything else — the wiki is the repo.
Forge-native
The engine meets your repos where they are, both directions:
intent: and acceptance:; CI
signals feed cascade triggers.Telemetry
Every layer emits — the engine, the reflex gate, the agents. The LGTM stack ships in the compose file, provisioned and pre-wired with shared trace IDs.
aioverload-overview loads on first boot.gate.decided event and
landed in reflex/decisions.jsonl. A control-plane labeler pairs each
decision with the run’s outcome — justified, false_positive,
confirmed, negated (blocks are honestly unobservable: a veto causes
the failure, nothing can refute it) — and aio_gate_* gauges report veto
precision, escalation-justified rate, and routing accuracy per workflow
— and, on the tool path, allow/hold precision per tool on the console’s
gate-quality page. Gate quality is measured, not asserted — and the
decision log doubles as fine-tuning data for the next gate.Deep-dive docs publish with the source at release.
Golden workflows
Workflows are commented YAML in the registry — the procedure is immutable, the agent bindings are governed, and every skip is on the log. The ones worth reading first:
judge-loop
A step runs, a judge scores it against its declared goal, the loop decides: iterate, hold, or block.
dev-review-loop
Code change → review → machine-readable verdict. The reflex variant lets the gate hold risky dispatches.
code-review-cascade
A failed review fans out governed child reviews; failures cascade into a postmortem run.
tier-routed-dev
Work is routed across model tiers — cheap local drafts, stronger models for review — by declared policy.
research-fanout
A question fans out to parallel researchers over an http runtime and consolidates — no local model required.
prospecting-crew
The non-code proof: the gate is expected to hold the outreach decision until a human approves it.
manager-epic decomposes an epic into governed children,
subworkflow-demo runs a workflow inside a workflow, and echo-demo
needs no AI at all — it’s the first run you should execute once the
repository is public.