How RLM Subagents Communicate with Parent Agents Using `rlm()` and `agent_message`

Prime Agent implements an asynchronous spawn-and-message pattern where parent agents spawn child subagents via the rlm() callable and receive results through the agent_message skill, rather than blocking for return values.

The PrimeIntellect-ai/prime-agent framework provides a Recursive Language Model (RLM) kernel that enables hierarchical agent execution. Understanding how parent agents spawn children and exchange messages without blocking is essential for building complex multi-agent workflows. This guide examines the specific implementation details found in the runtime source code.

The RLM Subagent Lifecycle

Spawning Child Agents with rlm()

In prime-agent-runtime/src/rlm/__init__.py, the rlm() function (exposed as the _RLMCallable type) provides the entry point for creating subagents. When a parent calls await rlm(prompt), the system sends an "rlm.run" request to the TypeScript host via the internal host_request function.

The host admits the child and immediately returns an RLMSpawnHandle containing the child's unique rlm_child_id, assigned name, session directory, and model configuration. This handle allows the parent to reference the child, but crucially, the child's actual output is not returned here. As documented in prime-agent-runtime/src/rlm/harness.py (lines 30‑35), results arrive only through explicit agent_message replies.

Managing Active Subagents with list_subagents() and delete_subagent()

Parents can query the host for current children using rlm.list_subagents(), which translates to an "rlm.list_subagents" host request. The raw response is processed by _subagent_from_payload (lines 81‑102 in rlm/__init__.py) and wrapped into RLMSubagent objects.

To terminate a child session, the parent calls rlm.delete_subagent(target), dispatching an "rlm.delete_subagent" request to the host. The target can be an RLMSubagent instance or the string rlm_child_id.

Child-to-Parent Communication via agent_message

Sending Results with agent_message.send()

Located in packages/coding-agent/skills/agent-message/src/agent_message/__init__.py, the agent_message.send function enables child subagents to push results back to their parent asynchronously. The skill constructs a payload containing the message content, receiver_role, and optional receiver_name, then dispatches it via host_request("agent_message.send", ...).

Routing Roles and Message Delivery

The host routes messages according to the receiver_role parameter. When a child specifies receiver_role="parent", the host directs the message to the spawning parent session (see lines 30‑38 in agent_message/__init__.py). Other valid roles include "sibling" and "child", enabling peer-to-peer communication between subagents.

Implementation Examples

Parent Spawning a Subagent

from rlm import rlm

# Spawn a child subagent for document summarization

handle = await rlm("Summarize the attached document")
print(f"Subagent spawned with ID: {handle.rlm_child_id}")

# Parent continues execution immediately; results arrive via message handler

Child Replying to Parent

from agent_message import send

# Inside the child subagent execution context

await send(
    "Here is the completed summary.",
    receiver_role="parent"  # Critical: routes to the spawning parent

)

Listing and Cleaning Up Subagents


# Retrieve all active children as RLMSubagent objects

children = await rlm.list_subagents()
for child in children:
    print(f"ID: {child.rlm_child_id}, Status: {child.status}")

# Terminate a specific subagent by passing the object or ID string

await rlm.delete_subagent(children[0])

Key Source Files and Functions

The RLM subagent communication protocol is implemented across these critical locations in the PrimeIntellect-ai/prime-agent repository:

Summary

  • rlm() returns immediately: The spawn operation returns an RLMSpawnHandle without blocking for the child's completion, enabling concurrent subagent execution.
  • Explicit messaging required: Children must use agent_message.send() with receiver_role="parent" to communicate results; there is no implicit return value mechanism.
  • Host-mediated routing: All communication flows through the TypeScript host via host_request calls, with the host managing session routing based on role parameters.
  • Subagent lifecycle management: Parents track active children via list_subagents() and clean up resources with delete_subagent().

Frequently Asked Questions

How does rlm() differ from a standard Python function call?

Unlike standard function calls that block until a return value is received, rlm() returns an RLMSpawnHandle immediately after the host creates the child session. The actual results are delivered asynchronously through the agent_message system, allowing the parent to continue processing or spawn additional subagents concurrently.

What information does the RLMSpawnHandle contain?

According to the source in rlm/__init__.py, the handle contains the child's unique identifier (rlm_child_id), the assigned name, the session directory path, and the model configuration. This metadata allows the parent to reference and manage the child throughout its lifecycle without waiting for the child's execution to complete.

Can subagents communicate with siblings instead of the parent?

Yes. The agent_message.send() function accepts a receiver_role parameter that can be set to "sibling" or "child" in addition to "parent". The host routes these messages accordingly, enabling direct peer-to-peer communication between subagents spawned from the same parent session.

Where is the subagent payload validated in the source code?

Payload validation and object construction occur in the _subagent_from_payload function within prime-agent-runtime/src/rlm/__init__.py (lines 81‑102). This function parses the raw host response and constructs RLMSubagent objects with validated fields for the parent agent to consume.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →