How it works

How a run moves

The engine owns the graph and the record. An LLM only answers agent steps. The same engine sits behind all three ways of driving a run: MCP, realm agent, and realm listen.

Overview

One engine, three front doors

WHO STARTS ITREALM ENTRY POINTCORESTATE AND PEOPLEMCP clientClaude Code, any agentrealm mcp / serveMCP server, stdio or HTTPtool callsexecute_stepExternal systemGitHub, Stripe, cronrealm listenwebhook serverHTTP POSTcreates runspawns, --run-idModel providerAnthropic or OpenAIrealm agentthe driver loopprompt / replyexecute_stepEngineexecution-loop.tspicks eligible steps (DAG)validates outputsruns auto + guard stepswrites the evidenceRun store~/.realm/runsread / writeHumanrespond, Slack,or MCPgate opensanswerMCPWEBHOOKREALM AGENTMCP clientExternal appModel APItool callsHTTP POSTprompt/ replyrealm mcprealm listenrealm agentspawnsexecute_stepcreates runexecute_stepEnginepicks eligible steps, validates outputs,runs auto + guard steps, writes evidenceread / writegate opensanswerRun store~/.realm/runsHumanrespond, Slack, MCP
Every path ends at the same engine call. The dashed arrow is the one hand-off between paths: realm listen starts a run, then a separate realm agent process drives it.
Step kinds

The four step kinds

autoThe engine runs a handler or service adapter. No LLM.
agentThe driver supplies the output: an LLM, or you over MCP.
guardThe engine checks a condition inline and continues or aborts.
finalizerCleanup the engine runs after the run ends.

A gate is not a fifth kind: a step can carry a gate, and the run then parks until a person answers.

After every result, the engine validates and records it, then runs every auto and guard step it can reach. It stops at the next agent step, at a gate, or at the end. After a person answers a gate, the steps the engine owes are named in next_actions as one call, advance_run (or realm run advance from a shell). Step order comes from the definition (depends_on, when, trigger_rule), never from the LLM.

Path 1 · MCP

The external agent drives

Realm makes no model call. The client's own model does the agent steps and follows the instructions the engine returns in each reply.

MCP clientClaude Code, any agentrealm mcpMCP serverEngineexecution-loop.tsRun store~/.realm/runsget_workflow_protocol, then start_runcreate the runsave the runnext_actions: the agent step, its prompt and inputRepeat until the run endsthe client's own model does the workexecute_step(run, step, output)validate against the schemarecord the evidencerun the auto + guard steps that follownext_actions for the next agent stepWhen a gate openswaiting on a human: gate id and choicessubmit_human_responseMCP clientrealm mcpEngineRun storeget_workflow_protocol, then start_runcreate the runsave the runnext_actions: the agent step, its prompt and inputRepeat until the run endsthe client's own model does the workexecute_step(run, step, output)validate against the schemarecord the evidencerun the auto + guard steps that follownext_actions for the next agent stepWhen a gate openswaiting on a human: gate id and choicessubmit_human_response
Path 2 · realm agent

Realm drives and calls the model API

The loop lives in packages/cli/src/agent/run-agent.ts. It uses the same engine call an MCP client uses.

Model APIAnthropic or OpenAIrealm agentthe driver loopEngineexecution-loop.tsRun store~/.realm/runscreate the run, or attach with --run-idRepeat until the run ends or a gate openswhich steps are eligible?the first eligible agent stepprompt: profile + step text + inputsmodel outputexecute_step with the outputvalidate against the schemaIf the output breaks the schemavalidation errorssame step, with the errorsOtherwiserecord the evidencerun the auto + guard steps that followModel APIrealmagentEngineRun storecreate the run, or attach with --run-idRepeat until the run ends or a gate openswhich steps are eligible?the first eligible agent stepprompt: profile + step text + inputsmodel outputexecute_step with the outputvalidate against the schemaIf the output breaks the schemavalidation errorssame step, with the errorsOtherwiserecord the evidencerun the auto + guard steps that follow

Steps run one at a time today. Parallel branches are recorded correctly, but not called at the same time.

Path 3 · realm listen

A webhook front door that starts runs

realm listen does not drive anything itself. It accepts a request, creates the run and hands it to realm agent. Expired gates are settled only if it was started with --sweep-expired-gates.

External systemGitHub, Stripe, cronrealm listenwebhook serverrealm agentseparate processRun store~/.realm/runsPOST /path, body + signaturematch the path, check the busy limitverify the signature, drop duplicatesIf rejected403, 503 or 400 (among others)If a duplicate200 deduplicatedIf acceptedcreate the run, params checkedspawn realm agent --run-id202 accepteddrive the run, as in path 2opt-in: --sweep-expired-gatesExternalsystemrealmlistenrealmagentRun storePOST /path, body + signaturematch the path, check the busy limitverify the signature, drop duplicatesIf rejected403, 503 or 400 (among others)If a duplicate200 deduplicatedIf acceptedcreate the run, params checkedspawn realm agent --run-id202 accepteddrive the run, as in path 2opt-in: --sweep-expired-gates

The busy limit (--max-concurrent, default 20) counts requests being handled, not runs being driven. The spawned drivers are detached, so nothing currently caps how many run at once on a machine.

Where to read the code