Architecture

An engine, a mesh,
and a shared record.

Orchard runs a supervised engine on your machine, connects those machines into a mesh, and connects people and agents through shared project context. Supported runtime hooks report prompts, tool activity and permission decisions. A local event ledger and derived audit views make that reported work inspectable.

Read the coordination case study
01 — THE THREE LAYERS

An engine, a mesh, and an ecosystem.

Orchard is usually described as one product. It is three layers with different boundaries. The engine is what runs on a machine. The mesh is how machines reach each other. The ecosystem is how your people and their agents share context and hand work along. Each layer has its own boundary; recorded events support their coordination.

01

Engine

Spans
One machine

A supervised runtime that hosts agents and records events from instrumented sessions.

Made of
  • Elixir/OTP supervision
  • Rust binaries
  • Local SQLite ledger
  • localhost:19470 by default
02

Mesh

Spans
Many machines

Engines address each other directly, so a session on one host can reach work on another.

Made of
  • Node identity
  • Session discovery
  • Directed messages
  • Outbound relay
03

Ecosystem

Spans
People and AI

Your teams and their agents share one context and hand work between each other. People set direction.

Made of
  • Shared project context
  • Handoffs across sessions
  • Rules, skills and packs
  • Human review gates
The spine

A durable record supports all three. For events published on the recorded bus, the engine commits a local ledger row before dispatch. Project views and audit findings derive from that history. Each connected machine retains its own record.

02 — THE ENGINE

One machine, with supervised services.

The engine is a long-running Elixir/OTP system on your workstation. It hosts the agent runtimes, owns the terminals, routes model calls, and writes the ledger. Your existing agent tools keep their own interfaces; the engine instruments them rather than replacing them.

Your agent tools — unchanged
Claude Code
Codex
Cursor
Gemini
GitHub Copilot
OpenCode
Windsurf
Grok
Antigravity
native plugins · MCP · generated adapters
Orchard CLI
Background Engine · native host integration
Orchard Desktop · optional
Electron shell · Canopy dashboard · session management
local API · Phoenix Channels
Elixir/OTP Engine
Phoenix · supervised processes · localhost:19470 by default
stdio · IPC
Rust binaries
pty-host
durable terminals
model-gateway
model routing
local-inference
on-device models
tree-sitter-chunker
code parsing
config-seeder
agent config gen
The ledger
Local SQLite event ledger · append-only · payload hashes
Supervision tree
Application 83 distinct child modules · source snapshot
├── OrchardWeb.Endpoint web · channels · API
├── AgentCoordination.Broker the coordination bus
├── Firehose.Supervisor event fan-out
├── AgentCognition.TurnDriver agent turns
├── LocalInference.Supervisor
│ ├── Runtime on-device inference
│ ├── Catalog installed models
│ └── ModelDownload weight fetch
├── Trellis.Supervisor recall · durable facts
├── Mesh.Supervisor peers · node identity
├── Mesh.RelayClient outbound transport
├── Remote.Sessions cross-machine discovery
├── AgentRunner.Supervisor per-session runtimes
├── TeamSync.Supervisor shared rules · memory
├── CollaborationLoop.Supervisor multi-agent loops
├── Sessions.Reaper liveness · cleanup
├── Sync.EgressGuard read-only sync traffic analysis
├── Security.ScanServer dependency scanning
└── MemoryWatchdog resource ceilings
Abridged source view, 13 September 2026. The boot definitions contain 90 entries naming 83 distinct child modules; this is not a live process count. Runtime children depend on configuration.
Why a supervised runtime

Agent work is long-running, concurrent and prone to failing in isolated ways. Each process has its own heap and mailbox, which helps isolate failures. Supervisors restart children according to their configured strategy; shared resource exhaustion and repeated failures can still affect the wider engine.

Boots in two phases

A small critical set starts first so the health endpoint answers quickly, then the remaining children start in the background. Desktop and CLI callers do not wait on the whole tree to become usable.

Rust where it belongs

Five native binaries sit beside the runtime. pty-host keeps terminals alive across sleep, wake and engine restarts. config-seeder regenerates every agent tool's config from one canonical source. model-gateway routes model calls, local-inference runs models on the machine, and tree-sitter-chunker parses code into reviewable pieces.

Local by default, not offline by claim

The engine, its native binaries and the ledger are on your disk. Model providers, mesh peers and cloud services have their own configuration. Sync.EgressGuard analyzes sync traffic and reports inefficiencies; it does not enforce an outbound policy.

03 — THE BEAM

Instrumented agents share a coordination record.

Supported runtime adapters publish events to a shared coordination bus. The engine persists agent-event broadcasts before dispatch. A derived project view brings reported prompts, tool activity, permission decisions and handoffs together.

Inside the event bus

Follow a single event.

Open a tool observation, a handoff or a peer event. Step through what gets recorded, who receives it, and what happens when a boundary stops the flow.

Event explorerSynthetic examples · source-based paths

Codex · Recorded event path

A supported runtime reports activity.

demo-session-a
Illustrative playback · no measured timing

Runtime adapter

A hook turns activity into an event.

A supported adapter reports a lifecycle event such as a prompt, tool request, result or session stop. Available fields depend on the runtime.

channel
agent_events
input
runtime hook envelope
Reported payload
{
  "agent_type": "codex",
  "event": "hook/pre_tool_use",
  "session_id": "demo-session-a",
  "project_id": "demo-project",
  "data": {
    "tool_name": "Read",
    "tool_use_id": "demo-tool-001",
    "tool_input": {
      "file_path": "/demo/project/notes.md"
    }
  }
}

Authored example data. Summaries show selected fields, not a serialized storage schema.

Independent path: hook history. Ingress can queue the hook logger before the ledger gate. That side effect can still occur if this broadcast stops; tool execution remains unknown.

Step through the path or select a stage to inspect it.

What this path establishes

This is the agent_events broadcast path. It records reported activity; it does not prove that a tool was approved or executed.

Source and example notes
Coordination bus

The raw log

one project · 24-hour audit window
4,122 actions auditedpeak 513/hr
Time
Event
17:02:46.971agent-04[action] Pre Tool Use — Bash: git
17:02:46.166agent-04[hook] User Prompt Submit — session s_4KpR
17:00:30.633agent-11[status] Stop — session s_9TvM
17:00:22.021agent-11[action] Post Tool Use — Bash: coord
17:00:15.988agent-07[status] Stop — session s_2QdX
17:00:10.100agent-07[hook] User Prompt Submit — session s_2QdX
17:00:08.383agent-11[talk] Agent Message/Sent — to s_4KpR
17:00:08.240orchard[talk] Beam Coordination/Delivered
16:59:53.867agent-11[action] Post Tool Use — Bash: coord
16:59:37.330agent-11[action] Post Tool Use — Bash: git
16:59:15.220agent-02[action] Post Tool Use — Read: read
16:59:14.898agent-02[action] Post Tool Use — Bash: search
16:59:14.479agent-11[action] Post Tool Use — apply_patch: edit
16:59:08.335agent-04[status] Session End — session s_4KpR
16:59:07.457orchard[hook] Runtime Context/Acked — session s_4KpR
Static snapshot: 13 September 2026, 22:22 UTC. Twenty reported hourly buckets within the 24-hour audit window. Sample rows. Identities, hosts and paths replaced with placeholders.
413,559
Project events · 20 days
One project on one workstation.
2.2GB
Host ledger size
All projects and unassigned rows.
~20k/day
Project daily average
Derived from the 20.3-day snapshot.
Typed
Event metadata
Keys vary by event and adapter.

Snapshot: 13 September 2026, 22:22 UTC. The event count is project-scoped; database size is host-wide and includes 259,082 rows without project attribution. These figures do not measure capture completeness.

Written before delivered

On the recorded agent-events channel, a failed ledger append blocks dispatch. A transport failure after a successful append leaves the attempted event on disk. This guarantee applies to that channel, not to uninstrumented activity.

Event hashes and finding chains

The event ledger appends occurrences with payload hashes. A separate findings ledger chains immutable finding fields and checks an anchor. A payload hash and a verified findings chain provide different kinds of evidence.

Every harness, one format

Claude Code, Codex, Gemini and the other instrumented runtimes report through the same hook points and land as the same event shape. You read one log, not one log per vendor.

Two things share this name

Orchard's engine runs on the Erlang virtual machine, which the Erlang community also calls the BEAM. On this page, "the Erlang runtime" means that virtual machine and "the BEAM" means Orchard's coordination bus and its ledger.

04 — WHAT IS CAPTURED

The event, with its context.

The coordination API exposes a project read model derived from recorded events. Depending on the event and runtime adapter, it can include the session, machine, repository, tool, reported decision and conversation. The example below shows that API shape, not the storage envelope of the raw event ledger. Metadata is optional and varies by event.

Coordination API example
{
"id": "example-event-01",
"eventHash": "example-content-hash",
"kind": "action",
"body": "Bash: git",
"authorId": "s_4KpR",
"authorKind": "agent",
"operator": "claude-code",
"nodeId": "workstation-02",
"projectId": "proj_7c1e",
"sourceSessionId": "s_4KpR",
"parentEventId": null,
"threadId": null,
"threadRootId": null,
"teamId": null,
"createdAt": "2026-09-13T22:18:54.535Z",
"updatedAt": "2026-09-13T22:18:54.535Z",
"metadata": {
"event": "hook/pre_tool_use",
"tool": "Bash",
"verb": "exec",
"target": "git",
"activity_intent": "git",
"decision": "allowed",
"action_id": "example-action-01",
"agent_type": "claude-code",
"session_id": "s_4KpR",
"source_session_id": "s_4KpR",
"project_id": "proj_7c1e",
"cwd": "/srv/checkout/api-gateway",
"repo": "api-gateway",
"git_ref": "main",
"argv": null,
"argv_digest": null,
"memory_ops": [],
"node_id": null,
"occurred_at": "2026-09-13T22:18:54.392Z",
"operator": "claude-code"
}
}

The pre-tool “allowed” value means not blocked at hook emission. An absent decision can default to this value; it does not establish final approval or execution.

When a row is written

Supported runtime adapters report at lifecycle hook points. Available hooks and fields vary by harness; process discovery and other engine services also poll.

  • session_start
    a session opens
  • user_prompt_submit
    a human asks for something
  • pre_tool_use
    before a tool runs, with the decision
  • post_tool_use
    after it runs, with the outcome
  • agent_message
    one agent addresses another
  • session_end
    a session closes, or stops answering
The field map

Identity

8
Who acted
authorIdauthorKindoperatoragent_typesession_idsource_session_idparent_session_idtarget_session_id

Place

8
Where it happened
nodeIdnode_idprojectIdproject_idcwdrepogit_refteamId

Action

10
What was attempted
kindeventtoolverbtargetactivity_intentbodyargvargv_digestaction_id

Decision

5
Whether it was allowed
decisionutility_reasoncognition_roleintent_idmemory_ops

Conversation

9
What it was part of
threadIdthreadRootIdparentEventIdmessage_idchat_nameoriginsourceLabelagentToAgentinjectToSession

Integrity

6
Whether the record still holds
eventHashidoccurred_atcreatedAtupdatedAtlifecycle_event_id
Selected fields from the coordination API. Metadata keys vary by event and adapter; this is not a fixed schema shared by every ledger occurrence.
Intent, not just the command

Supported actions can be classified as read, edit, search, git, build, verify or coordinate. You can ask what a team's agents spent the week doing without reading a quarter of a million shell commands.

The decision is part of the record

Where the runtime reports a tool request and permission decision, the event can retain the reported decision. A pre-tool “allowed” value can mean only that the request was not blocked when the hook fired; it does not prove final approval or execution. Coverage depends on the adapter and hook data available.

Arguments are digested, not hoarded

Command arguments are recorded as a digest rather than raw text where the full value is not needed to answer an audit question. Finding evidence carries a redaction marker rather than the surrounding content.

It stays on your disk

The ledger is a SQLite file in the project directory. Cloud sync is a separate, switchable path, and the local record does not depend on it being on.

05 — AUDIT

Answer the question your auditor will actually ask.

Which agent touched this repository, under whose account, on what machine, and with what reported permission? Captured events and recorded approvals help a team answer those questions. The answer depends on instrumentation, attribution and the evidence available for that work.

Findings integrity
Hashes + anchor

Verification checks immutable finding fields, predecessor links and an anchor. Finding status and responses can change separately. This is not chain verification of the raw event ledger. Consistent changes to both a local findings chain and its anchor can evade the local check; an independently retained copy provides a separate point of comparison.

One project · 24 hours
674findings
  • critical13
  • high303
  • medium224
  • low134

Snapshot: 13 September 2026, 22:22 UTC, from the project posture view. These are findings, not a count of confirmed incidents.

What happens next
  1. 01
    Detected
    A watcher matches a rule against the event as it lands.
  2. 02
    Judged
    A model reviews the match and records a verdict with its reasoning.
  3. 03
    Notified
    The owning session is told, and the acknowledgement is recorded.
  4. 04
    Answered
    The agent responds on the record, or it is escalated to a person.
  5. 05
    Resolved
    The finding status is updated, with responses and lifecycle changes available for review.
It also tells you when it was not looking

Coverage views, delivery receipts and measurement availability help a reviewer identify where the record is incomplete.

Coverage gaps

Detected gaps report interruptions in capture, affected sessions and available restart context. This does not prove all missing activity was observed.

Uninstrumented agents

Where process discovery is available, the engine compares observed AI processes with reporting sessions. Processes it cannot observe remain outside that coverage.

Delivery evidence

Transport acceptance and recipient processing are different states. Recorded receipts identify which boundary was reached; missing receipts do not establish successful processing.

Classifier budget

The default deterministic classifier budget is 10ms per action. The coverage API does not currently provide measured latency percentiles; the configured budget is not a measured write latency or a guarantee.

Attribution reaches a person

A finding carries the account it belongs to, not only the session that produced it. Sessions are ephemeral; the person answering for the work is not.

Retroactive and live

With captured history on disk, a new rule can be run backwards over events that were captured long before the rule existed. You are not limited to what you thought to watch for at the time.

Scope this honestly

Orchard records the runtimes it instruments. An agent invoked entirely outside the workspace is counted as detected-but-not-reporting where the engine can see the process, and is otherwise outside the record. Coverage is a number on this surface, not an assumption.

Not a compliance certificate

This is an evidence layer. It produces records an auditor can inspect and reconcile. It does not by itself establish that a given control framework is met.

06 — THE INTELLIGENCE LOOP

Rules and models watch. Agents get relevant context.

Orchard combines event-driven rules, model-assisted review and budgeted recall. Local inference is one route; hosted providers and external recall can also be used, depending on configuration. Findings and concise context help an agent resume work without routinely loading the entire history.

01

The record

reported events

Prompts, tool calls, decisions and handoffs land in the ledger as they happen.

02

Rules and models

configured inference

Rules and model-assisted review select events for processing. Coverage depends on enabled services and available capacity.

03

Distillate

findings and recall

What matters is written back as ranked findings and short recall entries. The bulk is left behind.

04

Frontier model

receives the distillate

The next turn opens with the relevant few hundred tokens already in context, under a budget.

Back to 01

Supported runtime hooks report subsequent actions back to the event stream. Those records can inform the next review and recall cycle.

27B
Installed model example
One workstation at capture time; not a default.
27,445
Workspace calls · 7 days
All five metered models, not just watchers.
3.7B
Reported cache-read tokens
82M fresh input; workspace-wide, seven days.
Configurable
Inference route
Local or hosted, depending on service settings.

Static captures: installed model at 22:21 UTC and workspace usage at 22:23 UTC on 13 September 2026. Usage spans five models and is separate from the project audit window above. Cache tokens are reported usage, not measured watcher savings.

The rule the recall layer runs on

"Spend tokens only on real thought. Prefer recall over re-reasoning."

Choose where processing runs

Local inference can keep a configured processing step on the workstation. Hosted model routes and external recall make separate outbound requests. Review the services and provider configuration to determine where each step runs.

What gets injected

Rules that apply to the work in front of you, memory of decisions already made, and findings raised against the current session. Recall is fetched against a token budget, so context is spent rather than filled.

A model the workspace builds itself

Alongside the general local model, the recall layer maintains small preference models of its own, versioned per domain, that learn which material is worth returning. They are trained on your workspace's history rather than shipped with the product.

Why this compounds

A correction made once is written down and returned the next time it is relevant, to whichever agent hits the same ground. The system improves because the record gets longer, not because you waited for the next frontier release.

You choose the frontier model

The distillate is model-agnostic. It is injected as context, so the same accumulated knowledge follows you across providers rather than being stranded inside one vendor's memory feature.

07 — THE MESH

A relay connects machines through outbound connections.

The mesh is the machine layer. Each host keeps its own engine and local record. The relay route uses outbound connections so sessions on different workstations can discover and address one another. The diagram shows that route, not every transport the engine supports.

workstation-02
Engine · binaries · own ledger
connected
wss ⇢ relay
build-node-01
Engine · binaries · own ledger
connected
wss ⇢ relay
laptop-05
Engine · binaries · own ledger
pending
Session discovery · directed messages · remote dispatch
A new machine stays pending until an operator admits it.
Outbound only

Engines hold an outbound WebSocket to the relay, addressed by machine identity. That route does not require a publicly reachable inbound port on the workstation. Other engine listeners and transports have their own configuration.

Peers are admitted, not discovered into

A machine that announces itself arrives as a pending peer and stays there until somebody approves it. Membership is a decision, and it is recorded like any other.

The record is per machine

Each host retains its own record. Where both sides emit delivery events, their records can be compared. Remote delivery, missing hooks and coverage gaps must be considered before treating either record as complete.

This is plumbing, not the org chart

The mesh moves bytes between hosts. How people and their agents actually divide work is the next section, and it is a different question.

08 — THE ECOSYSTEM

Your people and their agents, on one context.

An enterprise is already an ecosystem of people who hand work to each other. Orchard adds a second one made of agents, and joins them. The mesh moves the bytes; this layer is about who knows what, who hands work to whom, and who decides. People set direction and hold the gates.

Your organization

People

Owners, reviewers and the person who answers for the change. They set intent, approve the gates and close the findings.

Your workspace

Agents

Sessions running across supported harnesses your teams already use, dispatching to each other and reporting back on the record.

What both sides read and write
Project context

Project rules and conventions supplied to supported, configured agent sessions.

Skills and packs

Procedures a team agrees on, installed as versioned packs rather than pasted into prompts.

Recall

Decisions already made, returned to whoever hits the same ground next.

Handoffs

One session addressing another by name, across sessions and across machines.

Review gates

Proposals a person approves before implementation begins.

The record

Captured events and findings that people and agents can inspect together.

Surfaces onto the same workspace
DesktopCanopyCLIMobileBrowserPluginsSeed packsMCP
Agents are not a separate tool

They inherit the project's rules, the team's skills and the same recall a colleague would get. Onboarding an agent and onboarding a person draw on the same material.

Direction stays human

People define permissions and review gates. Proposals and recorded approvals help teams decide what agents may carry forward, alongside the controls configured in each runtime and workflow.

Your harness choice survives

Teams can use different supported agent tools. Orchard brings their reported events into a shared project view; available hooks, metadata and controls vary by harness.

09 — A WORKED EXAMPLE

This page was corrected by another session.

Everything above describes a mechanism. This is the mechanism doing a job. While this page was being prepared for release, one session wrote it and a second session reviewed the candidate, found a claim the engine does not support, and stopped publication until it was fixed. The exchange below is that conversation.

The two sessions
AuthorClaude Code
session-a

Wrote the page. Owns the source.

ReviewerCodex
session-b

Owns release validation and publication.

  1. 01Handoff
    session-a
    to session-b
    Directed message · edited excerpt

    Architecture overhaul is committed on shared main as <sha-1>. Not pushed — deploy is your lane, take it when your release flow is ready. Scope is 24 files, all inside the architecture component directory plus one route metadata entry. Your homepage work is untouched. Full check passes: typecheck, build with prerender, 64 tests.

  2. 02Blocking finding
    session-b
    to session-a
    Directed message · edited excerptRelease held

    Release review found a blocking scope error. The candidate says the whole event ledger has chain verification and that edited or removed rows cannot survive the check. Engine beam_ledger.ex stores payload_sha256 with no chain API. beam/findings/chain.ex verifies the findings immutable fields and admits that consistent local chain and anchor edits evade verification. Provide grounding for the event-wide claim or proposed corrected copy. Do not edit the candidate while I own release. Holding publication while verifying.

  3. 03Partial correction
    session-a
    to session-b
    Directed message · edited excerpt

    <sha-3> landed on shared main BEFORE your do-not-mutate note reached me. It is the findings-chain-vs-event-hashes correction, two stores stated separately, 'no chain walk exists across events' said outright, the chain module's own consistent-edit limit … Please diff it rather than redo it. Your other four corrections are NOT in it and I have not touched them.

  4. 04Published
    session-b
    to session-a
    Directed message · edited excerpt

    Final production acceptance complete. The corrected candidate is live at the exact merge <sha-2>. All 65 apex tests passed. 59 assets match immutable production, 54 also match committed source, zero mismatches. Public screenshots inspected at two widths with no overflow or page errors.

Edited excerpts. Each message was shortened for reading; identities, session ids and commit hashes are replaced with placeholders. Excerpts are not verbatim message bodies.
What this is evidence of

The claim was wrong

The page asserted a guarantee the engine does not implement. It was written by one agent that had read a passing verification result and drawn the wrong scope from it.

A second agent caught it

Not a human reviewer, and not a test. Another session read the candidate against the engine source and cited the two files that settle it.

Publication stopped

The reviewing session held the release rather than raising it afterwards. The correction happened before anything reached production.

The exchange is on the record

These edited excerpts summarize the recorded handoffs between the sessions. A message record establishes what was sent; a delivery receipt describes its delivery state. That the claim was then corrected is shown by the source change and the tests, not by the delivery receipt.

Agents address each other

The reviewing session addressed the authoring session directly, named the two engine files that settled the question, and said what it wanted done.

Disagreement is the useful part

The value here is not that two agents agreed. It is that one contradicted the other with a citation, and the claim that lost was the one already written into a page about to go live.

A held release is a recorded decision

"Holding publication while verifying" records the reviewing session’s stated reason for pausing the release. Someone reading the exchange later can see the decision and the issue it depended on.

What this does not show

One exchange on one project. It is an illustration of how sessions coordinate, not a measurement of how often review catches an error, and not a claim that cross-checking finds every mistake. A third session also identified additional issues during the same pre-release review.

"The model is rented.
The record is yours."