11:10–11:30 · Track 8 · Context Engineering

It's Tokens All The Way Down

How RLMs are Different

Kevin Madura
01

What an RLM is,
and why it's different.

01 · Foundations

A Recursive Language Model:

- treats context as an object it can manipulate in a symbolic environment

- delegates to sub-LMs as functions inside that REPL

- is bitter lesson pilled; lets the model decide how to work

Recursive Language Model architecture diagram
01 · Foundations · origin
Tweet from Omar Khattab (@lateinteraction): a general-purpose massively_summarize DSPy program that takes arbitrarily long text, builds a table of contents, assigns chunks to sections, and recursively summarizes each section in parallel using dspy.ChainOfThought and parallelize.

Omar Khattab, May 2025 — a general-purpose summarizer for arbitrarily long text as a recursive DSPy program. The RLM idea, in ~40 lines.

01 · Foundations · the result
Two charts on BrowseComp-Plus vs number of context docs. Left: correct-answer rate — RLM(GPT-5) holds ~100% out to 1000 docs while GPT-5, truncation, BM25 retrieval and ReAct collapse. Right: average API cost per query — RLM stays moderate while ReAct+BM25 cost climbs steeply to ~$2.

On BrowseComp-Plus, RLM(GPT-5) stays near 100% out to 1000 docs while flat, truncation, RAG, and ReAct all decay — at a fraction of ReAct's cost.

01 · Foundations

You define the task,
the model picks the path.

With agents and tool-calling, you are subject to limits of the context window.

With an RLM the model decides how to navigate the context — peek, grep, chunk, recurse — inside the REPL.

The deterministic shell is yours. The open-ended, judgment-heavy middle is the model's job.

Deterministic shell: typed inputs and outputs surround a probabilistic core where the model extracts, judges, and drafts
Dex Horthy's context-window diagram: System Instructions, CLAUDE.md, tools, the user message, Read() and context.md sit in the top 'smart zone' at 40% context used; everything below the line is 'the dumb zone'.
01 · Foundations

Meaningfully different from tool-calling;
context is part of the environment.

ApproachHow it treats context
RAGRetrieves top‑k passages for a single query.
AgentsDecompose task — pollute root context with every sub-result.
CodeActRuns code as a tool, not as the environment itself.
RLMThe code is the environment; recursion is the primitive.

The first three stuff the context window. An RLM keeps the context as a variable in the environment — the root LM never "sees" the bulk; it orchestrates via code.

Context window · what the model actually sees
or Space to step through
01 · Foundations · where results live
Comparison of Claude orchestration primitives — Subagents, Skills, Agent teams, Workflows — across what it is, who decides what runs next, where intermediate results live, what's repeatable, scale, and interruption. The 'where intermediate results live' row and the Workflows 'script variables' cell are circled.

Only workflows keep intermediate results in script variables — state that outlives any one context window. Sounds familiar!

02

When to reach
for it.

02 · Fit

Rule of thumb.

Use an RLM when the context won't fit or the work is compositional — and you can spend latency to buy reliability.

Otherwise a single call, RAG, or a plain code tool is cheaper and just as good.

02 · Fit

When to use

Use it
  • Very large/ dense inputs or outputs
  • Tasks amenable to decomposition
  • Long-horizon sessionsthat would rot a flat context
02 · benchmark · LongCoT

LongCoT Performance

@raw_works stress-tested long-horizon reasoning using claude-sonnet-4-5 vanilla vs dspy.RLM

Across 500 questions (logic, CS, chemistry, chess, and math):
RLM lifted accuracy from 2.6% → 45.4%

RLM wins where dependencies compile to code — puzzles, Hanoi, chess. It stalls on graph-shaped problems (max-flow, Hindley–Milner) and graphs.

Source: raw.works/longcot-a-benchmark-worthy-of-a-rlms-attention

500 questions · same model
MetricVanillaRLM
Correct13/500227/500
Accuracy2.6%45.4%
Captured cost$31$621
Per-task — solved
TaskVanillaRLM
Logic puzzlesHanoi · Sudoku · Dungeon · +30/1515/15
Chess0/10085/100
BlocksWorld · Sokoban0/2016/20
Chemistry13/10031/100
Math0/956/95
MaxFlow · Hindley–Milnergraph-shaped — both fail0/750/75
03 · measured · flat vs RLM

Sum 12 numbers
buried in 30k tokens.

Same root model (gpt-5.4-mini), same question. flat dumps the whole blob into one prompt; RLM loads it as a sandbox variable and counts in code.

Complexitypeak prompt tok ↓
flat19,556
rlm1,253
15.6× smaller blob per call
Performanceaccuracy ↑
flat0%
rlm100%
right vs wrong — flat miscounts
Times / question ↓
flat4.2s
rlm5.9s
flat 1.4× faster — and wrong
Token usagetotal tok ↓
flat19,572
rlm3,869
5.1× fewer tokens billed

flat 0/1 correct · RLM 1/1 — RLM trades 1.4× wall-clock for a 15× smaller prompt, fewer tokens, and the right answer.

03 · measured · flat vs RLM

Five questions
over a 5k-row table.

Joins, group-bys, churn math. flat flattens df.to_string() into the prompt (truncated); RLM reads only a preview, then runs real pandas in the sandbox.

Complexitypeak prompt tok ↓
flat3,821
rlm1,191
3.2× smaller — frame stays out
Performanceaccuracy ↑
flat0%
rlm75%
3/4 vs 0/4 — truncation loses rows
Times / question ↓
flat0.9s
rlm6.6s
flat 7× faster — the cost of the loop
Token usagetotal tok ↓
flat3,840
rlm2,488
1.5× fewer even with the sandbox loop

The honest trade: RLM is slower per question, but the only arm that actually computes over the data — flat truncates and guesses.

03 · measured · the coding-agent question

A coding agent gets it right too.
For 40–115× the overhead.

Same two tasks, same grading. agent = Claude Code — its own frontier model, its own shell, not dspy.RLM at all. Not iso-model with flat/rlm: this answers "what does buying a general-purpose agent cost instead of building the scaffold," not "which scaffold wins."

A · cost / querylong-context agg ↓
flat$0.0147
rlm$0.0041
agent$0.190
agent 46× rlm's cost — tied on accuracy
A · total tokenslong-context agg ↓
flat19,572
rlm3,933
agent146,263
agent 37× rlm's tokens per question
B · cost / queryworkbook ↓
flat$0.0013
rlm$0.0035
agent$0.189
agent 54× rlm's cost — tied on accuracy
B · total tokensworkbook ↓
flat3,837
rlm3,405
agent144,967
agent 43× rlm's tokens per question

Accuracy tied: agent 100% / 75% vs rlm 100% / 75% on tasks A/B — a real shell beats flat regardless of scaffold. The gap is pure overhead: Claude Code's own system prompt, tool schema, and full-file reads dominate every call. Building the scaffold is ~50× cheaper than buying general-purpose agent overhead, per query.

03

In practice.

03 · In practice

RLMs in the real world

dspy.RLM — the core module in DSPy. Typed signatures, pluggable sandbox.

ax (github.com/ax-llm/ax) — open source reference agent with DSPy, full workflow and orchestration.

predict-rlm (Trampoline AI) — production runtime on DSPy. Multimodal, skills, file I/O, full traces.

fast-rlm (avbiswas) — minimal; the whole thing in an afternoon.

Tweet from Sam Hogan (@samhogan): to try GLM 5.2 in production, install Inference Gateway, which uses an RLM to sort through live traffic and auto-generate evals over ~24 hours, mirrors traffic to run them, and notifies you on Slack when it is safe to switch — saving ~90% on the token bill.
03 · dspy.RLM

Exploring a dataframe

The whole integration is a DSPy signature — analyst brief in the docstring, typed inputs, typed outputs.

Pass the DataFrames in, call dspy.RLM(). No agent scaffold, no custom tools, no hand-built orchestration.

The model interacts with the data through REPL code. That's the entire program you write.

class CohortRetentionAnalysis(dspy.Signature):
    """You are a data analyst investigating why user retention is dropping.

    You have access to three DataFrames:
    - users: user profiles with signup dates and acquisition channels
    - events: feature usage events with timestamps
    - subscriptions: subscription status, plan, MRR, and cancellation reasons

    Investigate the data step by step. Compute retention by cohort, segment by
    acquisition channel, compare feature usage between retained and churned users,
    and identify the root cause of churn.
    """

    users: DataFrame = dspy.InputField(desc="User profiles with signup_date, acquisition_channel, country")
    events: DataFrame = dspy.InputField(desc="Feature usage events with user_id, event_type, timestamp")
    subscriptions: DataFrame = dspy.InputField(desc="Subscription records with status, plan, mrr, cancellation_reason")

    overall_churn_rate: float = dspy.OutputField(desc="Overall churn rate as a decimal (e.g. 0.25 for 25%)")
    worst_channel: str = dspy.OutputField(desc="Acquisition channel with highest churn rate")
    key_finding: str = dspy.OutputField(desc="The main insight about what differentiates churned users")
    recommendations: str = dspy.OutputField(desc="2-3 actionable recommendations based on the analysis")

dspy.RLM(CohortRetentionAnalysis)(users=..., events=..., subscriptions=...)
            
03 · dspy.RLM

dspy.RLM — exploring a dataframe

Three DataFrames, 16MB / 250k events. Only previews hit the prompt — the model writes and runs the analysis in the sandbox.

Exploreshapes, dtypes, channel & plan counts
Define churncancelled / total; cohort by signup month
Segment by channelpaid_campaign_x worst, every cohort
Dig into behaviorretained vs churned feature usage
Find the signaladvanced_reports adoption
Verify & submitsanity checks, then SUBMIT(...)
or Space to step through
Reasoning turn 1 / 7


            
03 · dspy.RLM · trajectory
A single RLM trajectory step: a 'reasoning' block where the model plans to compare feature usage between retained and churned users within paid_campaign_x, followed by a 'code' block with the pandas it wrote — user-level event aggregates via groupby and a feature-count pivot table.

One step of the run, verbatim — the model's reasoning, then the pandas it wrote to build user-level aggregates and feature pivots. No scaffold; it planned this itself.

03 · predict-rlm · live run

Real world use case:
Invoice to inventory

2 invoice PDFs in
Acme Corporation invoice PDF, INV-2025-0042, with line items for cloud hosting, storage, support, API overage and SSL renewal. GlobalTech Solutions invoice PDF, GT-10587, with line items for software license, consulting, migration, training, support, integration and a discount.
one .xlsx out
Generated invoice_extraction.xlsx: line items extracted from the invoice PDFs with Description, Quantity, Unit Price and Amount columns, including a Discount (10%) row.

Two PDFs → one typed .xlsx — line items lifted straight off the page, one sheet per vendor plus a reconciled Summary. predict-rlm/examples/invoice_processing

03 · predict-rlm · the run

Focus on abstractions instead of context engineerning.

from predict_rlm import PredictRLM, File
from predict_rlm.skills import pdf, spreadsheet

rlm = PredictRLM(ProcessInvoices,
                 skills=[pdf, spreadsheet],
                 sub_lm="openai/gpt-5.1")
await rlm.acall(invoices=[File("acme.pdf"),
                              File("globaltech.pdf")])

One DSPy signature → typed InvoiceExtractionResult + an .xlsx workbook. No agent scaffold. Orchestrator gpt-5.4 drives the REPL; gpt-5.1 reads the page images.

01 Survey 8.0s
pymupdf.open(p)  # 2 files · 2 pages
# vendors: Acme Corp, GlobalTech
02 Render + extract 15.8s · 2 sub-calls
await asyncio.gather(*[
  predict("page: dspy.Image -> invoice", page=img)
  for img in pages])  # parallel, gpt-5.1
03 Self-verify 12.4s
# GlobalTech: subtotal+tax != total
#   33817.9 vs 30717.9  → reconciled
wb.save("invoice_extraction.xlsx")

5 REPL iterations · 60s · $0.12 ($0.06/page)

03 · predict-rlm · under the hood

predict-rlm enforces signatures between sub-lm calls

Every recursive call crosses a typed boundary. The orchestrator can't pass prose to a sub-LM — it passes a signature.

DSPy enforces structure at the seam: the sub-LM's reply is parsed into a Pydantic model and retried on a schema miss before it returns.

The REPL gets back a real Python object — .total, .line_items — not a string to re-parse.

Orchestratorgpt-5.4 · writing REPL code
inv = await predict(
  "page: dspy.Image -> invoice: InvoiceModel",
  page=render(pdf))
typed call · dspy.Image in
DSPy Signaturethe contract — validated both ways
IN  page    : dspy.Image
OUT invoice : InvoiceModel
        vendor_name : str
        total       : float
        line_items  : list[LineItem]
JSON reply → parsed → retried on schema miss
Sub-LMgpt-5.1 · returns a typed object
inv.total        # 4086.4  (float)
inv.line_items[0]# LineItem(...)
03 · in the real world
Tweet from diego (@diblacksmith): 'My RLM agent can effortlessly process ~80k lines of service logs from CloudWatch in a single go — worth like 8 million tokens. The cool part is, after 53 steps it had spent only 32k active tokens.' A System Update journal screenshot summarizes three errors found across 21,547 log entries.

8M tokens of CloudWatch logs, ~32k active after 53 steps — the model paged through the context instead of holding it all at once.

03 · in the real world · HALO
HALO Engine architecture: a root RLM (depth 0) invokes tools — get_dataset_overview, query_traces, count_traces, view_trace, search_trace, get_context_item, synthesis, run_code (sandboxed) — over an OpenTelemetry trace store, and spawns per-depth-parallel subagents (max 4) that recurse to a terminal grandchild depth, with a compaction model persisting context items.

HALO (context-labs/halo) — a recursive-LM engine over OpenTelemetry traces: the root LM navigates the trace store through tools, spawns bounded per-depth-parallel subagents, and compacts findings into persistent context items.

03 · dspy.RLM · security audit

Scanning a codebase
for $0.87

Pointed dspy.RLM at OWASP's Damn Vulnerable Serverless App — no prompt engineering, no custom scanner logic, just a signature.

It decomposed the tree itself, delegated file-level reads to a cheap sub-LM, and synthesized findings back up and caught 6 of 10 planted vulns.

Missed dynamic ones: auth bypass, DoS via billing abuse, TOCTOU race conditions, vulnerable dependencies.

Write-up: kmad.ai/Recursive-Language-Models-Security-Audit

import dspy
import os

from typing import Any

# LM Setup - must have OPENROUTER_API_KEY set
lm = dspy.LM("openrouter/moonshotai/kimi-k2.5", max_tokens=16000)
lm_mini = dspy.LM("openrouter/moonshotai/kimi-k2.5", max_tokens=16000)
dspy.configure(lm=lm)

# DSPy Signature & Program
class CodeScanner(dspy.Signature):
    """
  Review the provided application source code in detail. 
  Focus specifically on identifying security vulnerabilities, 
  insecure coding patterns, and other areas of concern.
  """
    source_tree: dict[str, Any] = dspy.InputField()
    documentation: str = dspy.OutputField(description="Generated markdown documentation.")

def load_source_tree(root_dir: str) -> dict[str, Any]:
    """Recursively load the folder into a nested dict."""
    tree: dict[str, Any] = {}
    for entry in os.listdir(root_dir):
        path = os.path.join(root_dir, entry)
        if os.path.isdir(path):
            tree[entry] = load_source_tree(path)
        else:
            with open(path, "r", encoding="utf-8", errors="ignore") as f:
                tree[entry] = f.read()
    return tree

source_root = "~/dev/DVSA/"
source_tree = load_source_tree(source_root)
del source_tree['CONTENT'] # Remove the 'lessons' we will compare against.

code_scanner = dspy.RLM(CodeScanner, max_iterations=35, sub_lm=lm_mini, verbose=True)

# Load and run
result = code_scanner(source_tree=source_tree)
03 · dspy.RLM · security audit

What it caught,
lesson by lesson.

LessonTopicStatusNotes
#1Event InjectionPartialCaught S3 command injection; missed node-serialize code injection
#2Broken AuthenticationMissedJWT bypass & open billing API not documented
#3Sensitive Info DisclosureCaughtAdmin receipt access via S3
#4Insecure Cloud ConfigCaughtS3 public write & command injection
#5Broken Access ControlPartialCaught IDOR/privilege escalation; missed payment bypass
#6Denial of ServiceMissedBilling concurrency abuse not mentioned
#7Over-Privileged FunctionsCaughtComprehensive IAM policy violations
#8Logic VulnerabilitiesMissedRace condition/TOCTOU not documented
#9Vulnerable DependenciesMissednode-serialize, node-jose, shell-quote not mentioned
#10Unhandled ExceptionsPartialGeneric error disclosure noted; specific examples missed

3 caught · 3 partial · 4 missed — every miss was runtime behavior static reading can't see.

what's next?

Imagine models post-trained to be RLM-native...

kmad.ai