Skip to content

packages coding agent rlm runtime

Zachary BENSALEM edited this page Aug 15, 2026 · 1 revision

RLM runtime

Active contributors: Mario Zechner, kt, Armin Ronacher

Purpose

Prime Agent is built around a recursive language model (RLM) runtime: the model works inside a persistent Python control environment and composes capabilities as code. Provider calls, session persistence, child lifecycles, scheduling, and safety policy remain in the TypeScript host; the IPython kernel is the model-facing programming surface. The programming model is documented in packages/coding-agent/docs/rlm.md and the runtime architecture in packages/coding-agent/docs/rlm-runtime.md.

The TypeScript-side runtime core lives in packages/coding-agent/src/core/rlm-runtime.ts. Supporting pieces include the recursion depth gate (rlm-max-depth.ts), agent-to-agent messaging (agent-messages.ts), system-prompt construction (system-prompt.ts), side questions (side-question.ts), and shared command execution (exec.ts). The Python rlm package shim runs in the kernel and is covered by the rlm package page.

Directory layout

packages/coding-agent/src/core/
├── rlm-runtime.ts      # Typed rlm.run host handlers, spawn handles, model search
├── rlm-max-depth.ts    # Wire-safe /rlm-max-depth state types
├── agent-messages.ts   # Agent-to-agent messaging types, prompts, host handlers
├── system-prompt.ts    # buildSystemPrompt: RLM guidance + subagent doctrine
├── side-question.ts    # startSideQuestion: /btw side turns
└── exec.ts             # execCommand: shared shell execution for extensions/tools

Key abstractions

Type Path Description
RlmRunRequest packages/coding-agent/src/core/rlm-runtime.ts Request for an rlm.run host call: prompt, kwargs, and optional cell source.
RlmSpawnHandle packages/coding-agent/src/core/rlm-runtime.ts Admission handle returned immediately: rlm_child_id, name, session_dir, model.
RlmSubagentRegistryEntry packages/coding-agent/src/core/rlm-runtime.ts A tracked direct child with status and session identity.
RlmModelMatch packages/coding-agent/src/core/rlm-runtime.ts A bounded model match from find_models.
RlmSubagentRuntime packages/coding-agent/src/core/rlm-runtime.ts Host-owned child runtime wrapping an AgentSession.
CreateRlmSubagentRuntimeOptions packages/coding-agent/src/core/rlm-runtime.ts Everything needed to spawn a child: model, thinking level, tools, depth.
SubagentRuntimeHost packages/coding-agent/src/core/rlm-runtime.ts Host interface to create, complete, release, delete, and dispose child runtimes.
RlmMaxDepthStatus packages/coding-agent/src/core/rlm-max-depth.ts Current max depth and its source (default, env, global, inherited, chat).
AgentSessionMessage packages/coding-agent/src/core/agent-messages.ts A custom session message carrying an agent-to-agent payload.
SideQuestionRun packages/coding-agent/src/core/side-question.ts A running side question with done and abort.
ExecResult packages/coding-agent/src/core/exec.ts stdout, stderr, code, and killed flag from execCommand.

How it works

flowchart TD
    model["Parent model"]
    ipython["IPython tool call"]
    kernel["Persistent IPython kernel"]
    shim["rlm Python shim"]
    comm["comm target host.request"]
    host["AgentSession host handlers"]
    child["Child AgentSession"]
    provider["Model provider"]

    model --> ipython --> kernel --> shim
    shim -->|"await rlm('task')"| comm
    comm -->|"rlm.run"| host
    host -->|"admit, return RLMSpawnHandle"| comm
    comm -->|"control channel reply"| shim
    shim -->|"handle.rlm_child_id ..."| model
    host --> child --> provider
    child -->|"agent_message.send(receiver_role='parent')"| host
Loading

The callable rlm is preloaded in the kernel. await rlm("task", name="x") travels over a Jupyter comm target named host.request; KernelManager dispatches request type rlm.run to the parent AgentSession, which checks depth, resolves or inherits the model, admits the child into the parent registry, and returns an admission handle. The call never waits for or returns the child's answer. Results arrive only through explicit agent_message replies or files. createRlmRunHostHandler, createRlmFindModelsHostHandler, createRlmListSubagentsHostHandler, and createRlmDeleteSubagentHostHandler in packages/coding-agent/src/core/rlm-runtime.ts adapt each handler into the typed kernel host bridge.

The rlm callable mirrors the RLM loop in packages/coding-agent/docs/rlm.md: the parent keeps its own context focused while Python holds working state and child agents receive only the context needed for their subtasks.

Recursive subagents

Child creation runs through CreateRlmSubagentRuntimeOptions and SubagentRuntimeHost in packages/coding-agent/src/core/rlm-runtime.ts. The session runtime (see the session runtime page) checks RLM_DEPTH < RLM_MAX_DEPTH, creates a sub-xxxxxxxx child directory under the parent artifact directory, admits the task and returns its handle, then runs the child prompt independently. Children inherit the parent model, provider, skills, tools, retry policy, and resource loader unless another configured model is requested. Default maximum depth is 1, so roots may create children but not grandchildren; the depth is raised via /rlm-max-depth (wire-safe state in packages/coding-agent/src/core/rlm-max-depth.ts) or RLM_MAX_DEPTH. findRlmModelMatches scores the authenticated model catalog by exact, prefix, and partial matches without adding it to the system prompt.

Agent-to-agent messaging

packages/coding-agent/src/core/agent-messages.ts implements messaging within an agent's nuclear family (parent, siblings, direct children). Key pieces:

  • buildAgentFamilyRoster derives the relationship graph; assertAgentFamilyReach and agentFamilyRelationship enforce the parent/sibling/child boundary. Broadcast is rejected.
  • createAgentSessionMessage and createAgentSessionMessagePrompt format the received-message prompt with [from <relationship>:<name>] and Message id lines; parseAgentSessionMessagePromptId and isAgentSessionMessage recognize these messages.
  • createAgentMessageHostHandlers exposes agent_message.list_agents and agent_message.send host handlers, enforcing receiver_role (parent, sibling, child) and receiver_name selection rules.
  • AgentSessionMessageRateLimiter applies token-bucket rate limiting per target with capacity/refillMs.
  • Defaults cap message length (DEFAULT_AGENT_MESSAGE_MAX_CHARS), pending per session, and rate limit.

Children reply with await agent_message.send(message, receiver_role="parent"); the parent can follow up with a retained child via receiver_role="child", receiver_name=<name>. The parent-scoped registry (await rlm.list_subagents()) survives compaction and kernel restart, and await rlm.delete_subagent(...) cancels or closes a child runtime.

System prompt construction

buildSystemPrompt in packages/coding-agent/src/core/system-prompt.ts composes the RLM prompt through buildRlmPrompt from packages/coding-agent/src/core/prompts/, then appends subagent delegation guidance (buildSubagentGuidance) when recursion is enabled and IPython is available, the continual harness overview (see the refinement page), project context files, and the skills section. buildChildAgentDoctrine injects a child-agent doctrine for nested agents with the installed Python skill imports, active tools, depth, and parent identity.

Side questions

startSideQuestion in packages/coding-agent/src/core/side-question.ts runs a /btw (side) question in a separate Agent whose tools are disabled. It re-clones the live main conversation each turn so follow-ups see the newest context, replays earlier side turns, and emits running, complete, cancelled, or error events. The side conversation is never added to the main session.

The IPython-harness programming model

The default RLM runtime exposes one built-in model tool, ipython. Reading and editing files, running project commands, invoking skills, and delegating work all begin from that persistent kernel. Python state survives across tool calls and compaction. %%bash cells are temporary subshells, while Python state and %cd changes persist. packages/coding-agent/src/core/exec.ts provides execCommand, a shared spawn-based executor used by extensions and custom tools that supports abort signals, timeouts, and per-call env merging.

Integration points

  • packages/coding-agent/src/core/kernel/ owns the Jupyter transport and host.request comm dispatch (see the session runtime page).
  • The session runtime (packages/coding-agent/src/core/agent-session.ts) implements child creation, the registry, usage attribution, cancellation, and goal handlers.
  • system-prompt.ts feeds the RLM doctrine, subagent specs, skills, and harness overview to the model.
  • The agent-message, agent-observe, rlm-heartbeat, goal, and compact skills are kernel-side host-bridge clients.
  • The Python rlm package is the model-facing shim; see the rlm package page for RLMSpawnHandle, RLMModel, RLMSubagent, and TokenUsage.

Entry points for modification

  • To change rlm.run validation or host-handler adaptation, edit packages/coding-agent/src/core/rlm-runtime.ts.
  • To change depth reporting, edit packages/coding-agent/src/core/rlm-max-depth.ts.
  • To change agent messaging policy or prompts, edit packages/coding-agent/src/core/agent-messages.ts.
  • To change the RLM system prompt, edit buildSystemPrompt in packages/coding-agent/src/core/system-prompt.ts and the prompt builders in packages/coding-agent/src/core/prompts/.
  • To change side-question behavior, edit packages/coding-agent/src/core/side-question.ts.

Key source files

File Role
packages/coding-agent/src/core/rlm-runtime.ts rlm.run host handlers, spawn handles, model search.
packages/coding-agent/src/core/rlm-max-depth.ts Max-depth state for /rlm-max-depth.
packages/coding-agent/src/core/agent-messages.ts Agent-to-agent messaging.
packages/coding-agent/src/core/system-prompt.ts RLM prompt, subagent doctrine, harness overview.
packages/coding-agent/src/core/side-question.ts /btw side turns.
packages/coding-agent/src/core/exec.ts Shared shell command execution.

Related pages

Clone this wiki locally