Ada

> < architecture

What runs when you send a message.

Ada's editor is a thin shell around a provider-agnostic coding agent. This is the whole path a request takes — from the pane on the right to a model and back — the loop that drives it, and the knowledge layer that keeps every turn grounded in your repository.

> < 01 / the request path

One wire format, every provider.

Two processes on your machine. The client speaks one dialect — OpenAI chat completions — no matter the target model. A local backend holds the real keys, applies policy, routes to whichever provider the model id names, and meters every call.

Client

the agent loop

The pane on the right. Assembles each request from scratch and streams the reply.

Backend · local

routing server

Auth → policy → route → adapter → meter. Auto-started; holds the keys.

Upstream

model APIs

claude-*gpt-*gemini-* @cf/*groq/ollama

The client never holds a provider key — only a client key for the local backend. 340+ models across 12 providers, switched mid‑conversation.

> < 02 / orchestrators

The loop is a strategy, not a script.

An Engine holds the harness primitives — streaming, tool-call recovery, compaction, approval, sessions. An Orchestrator only decides when to call them. So a new agent architecture is one Orchestrator and zero engine changes.

auto
cheap signals → a model only if they tie

Picks the architecture per request: a source too big for the window goes to rlm, a question or a one-liner to react, and anything longer is classified by the worker model. Set it once — the backend can push it to every client.

react default
reason → act → observe → repeat

The tool loop. Steerable mid-turn; nudges once if a model stops with tool output but no answer.

single
one turn · no tools

A single model turn with tools disabled. Quick question, quick answer.

plan
read-only plan → execute

One locked turn presents a numbered plan, then drops into the tool loop to carry it out.

toolsmith
docs → fan out → skills

Reads a connected integration's docs, then spawns a sub-agent per capability to author skills for it.

rlm
chunk → fan out → fold → answer

For a source too big to read. One worker per chunk holds the question while it reads its own slice; the model answering never sees the source, only their notes. Nothing is summarised before the question is asked — unlike compaction, which decides what to forget first. If the notes outgrow the answering model they are merged in passes until they fit. Measured on a 10 MB listing: 175 workers, every match found, nothing invented.

The heart — the react loop, condensed:

for (;;) {
  const turn = await e.step();
  if (!turn) return;                          // aborted
  if (!turn.toolCalls.length) {
    if (!turn.content.trim() && !nudged)      // stopped silent → ask for the answer, once
      { nudged = true; e.addUser("…write your final response now…"); continue; }
    if (e.drainSteer()) continue; return;     // done — unless steering queued more
  }
  await e.runTools(turn.toolCalls);
  e.drainSteer();
}

Delegation — the only fan-out primitive, with guardrails learned the hard way:

Isolated by default

A sub-agent runs in its own git worktree as a child process — parallel in-process workers would all write into the parent's tree. Falls back in-process when there's no repo.

A worker leash

50k-token budget per worker. One that missed its brief will read the repo until something stops it (measured: 174k on a single subtask). Parents are never capped.

Path claiming

Output files are claimed atomically — two workers can't both win the same file. A collision is reported as a decomposition bug, never silently merged.

Cost rolls up

A sub-agent's tokens and cost fold into the parent even if the subtask throws — a swarm's true spend stays on screen.

Removed — the lesson

A fifth strategy, multi (decompose → fan out → synthesize), was deleted. On the same task it burned 29× the input tokens, and only looked cheaper when workers ran on a throwaway model; on the user's model it cost 2× react for worse output — splitting one cohesive artifact along file lines leaves nobody holding the whole design. Delegation survives only for genuinely separable subtasks.

> < 03 / the knowledge layer

Four ways a session stays grounded.

Structure, facts, meaning, and relationships-over-time. Each persists beside your code and is injected into the model's context — only what a turn actually needs.

brain

Structure. A cached repo map — files and top-level symbols — so the agent starts oriented instead of grepping. Built locally, free.

memory

Facts. Durable notes across sessions, with supersede, secret-gating, scope, and relevance recall.

embed-index

Meaning. Semantic code search over a local embedding index — cosine over a packed vector blob, no embedding API bill.

graph

Relationships over time. Typed, bi-temporal edges — a contradicting fact invalidates the old one, so point-in-time questions still answer.

The graph closes the loop with memory at three points — all installed by one wireGraphMemory() at startup:

writea remembered fact  →  extractEdge (subject · predicate · object, or null)  →  addEdge → graph.db, invalidating any contradicted fact
readeach turn's recall  →  search names the entities the query mentions  →  neighbors pull their relationships  →  related facts into context
toolgraph_query — the model asks on demand: an entity's connections, or a free-text search over facts

Write and read are hooks that default off, so memory stays pure and offline-testable; the tool is read-only. Extraction self-gates to null rather than store a garbage triple; recall is trust-gated and honours point-in-time.

> < 04 / the routing backend

Every request passes one pipeline.

A small local server. Before any request reaches an upstream provider, it runs the same sequence — so keys, policy, and metering live in one place, not in the client.

auth allow-list org policy route(model) provider adapter meter + audit

Routing

Model id → provider by prefix; slash-namespaced ids fall back to an aggregator. Add a provider without touching the client.

Keys stay server-side

Provider keys never reach the editor. The client authenticates to the backend with a single client key.

Also serves

Embeddings, image generation, the model catalogue, and provider status — the same authenticated surface.

> < 05 / on disk

Everything the agent knows sits beside your code.

Per project, plain files — inspectable, deletable, and local. Nothing about your repository is indexed off the machine.

.ada/
  brain.json      # repo map cache
  index.json      # semantic index — manifest
  index.vec       # semantic index — packed vectors
  graph.db        # temporal knowledge graph
  skills/         # project + integration-authored skills
  mcp.json        # configured integrations
memory/           # durable facts (project + user)

See what this costs on the wire — the benchmark →