A polished builder-track introduction to Recursive Language Models, covering context rot, the official client, and a minimal REPL harness.
Learning Outcomes
Explain the RLM paradigm
Run the official RLM client
Build a minimal REPL-based RLM
Modules
Why RLMs Exist
Frame context rot and the REPL-based alternative.
1.1 Overview and Framing
Objective
Understand the actual failure mode RLMs are addressing: not that models cannot read long text at all, but that reasoning quality degrades when inspection and synthesis are squeezed into one giant prompt.
Why This Paradigm Exists
Direct long-context prompting asks the model to do three jobs at once: remember the entire document, decide what matters, and answer the question. As the prompt grows, attention gets expensive and important details get blurred, skipped, or flattened into generic summaries. That is the practical failure mode people call context rot.
An RLM separates storage from reasoning. The long context lives outside the prompt in a programmable environment such as a Python REPL. The root model sees the query and knows it can inspect context with code, recurse on chunks, and store intermediate results in variables.
Mental Model
Keep the root prompt small.
Treat long context as data, not memory.
Let the model inspect before it concludes.
Persist intermediate findings instead of re-explaining them in tokens.
Quick Exercise
Pick a task you would normally solve by pasting too much material into a normal chat prompt.
Rewrite it as a tiny query plus an external context object.
Write down the first three inspection actions you would want the model to take.
1.2 Read the Primary Sources
Reading Pass
Read the blog post end to end. Then skim the paper abstract and Section 2. You are not trying to memorize every detail yet; you are building a clean mental model of the runtime.
What To Capture
One sentence explaining why RLM is not just "more context."
One sentence explaining why RLM is not just RAG.
One concrete workload where recursive inspection matters.
Use this quiz to separate the new idea from adjacent patterns. The important thing is not memorizing terms; it is recognizing when a workload needs programmable inspection rather than bigger prompts.
After The Quiz
Write two short answers for yourself:
Where would RAG still be the simpler and better choice?
Where would an RLM clearly earn its added complexity?
Quiz
Which statement best distinguishes an RLM from classic RAG?
Correct: RAG retrieves relevant chunks into the prompt, while an RLM treats the wider context as an external workspace the model can inspect with code and recursion.
What problem does a larger context window or long-context fine-tuning fail to solve by itself?
Correct: It does not give the model a programmable way to inspect, cache, and recurse over the context.
Which workload is the clearest fit for an RLM-style approach?
Correct: Working through a large codebase or long document corpus where the model must inspect different regions deliberately.
First Official RLM Call
Install the official client and run a first end-to-end RLM call.
2.1 Environment Setup
Goal
Get to a point where a single Python file can call the official client against a real model.
Missing API key: the client will initialize, but the first request will fail.
Wrong package name: the official package is rlms, while the import path is from rlm import RLMClient.
Shell mismatch: if the variable exists in one terminal tab only, your editor or LearnHouse environment may not inherit it.
Exit Criterion
You can run python3 -c "import os; print(bool(os.getenv('OPENAI_API_KEY')))" and get True.
2.2 Run the Official Client
First Run
Start with the smallest successful end-to-end call. Do not optimize yet. The goal is to watch the library work with a long context payload.
from rlm import RLMClient
import os
client = RLMClient(
model="gpt-4o-mini",
api_key=os.getenv("OPENAI_API_KEY"),
)
response = client.completion(
query="Summarize the key findings from this long document.",
context="""Replace this with a long document or file contents.""",
)
print(response)
What To Observe
Does the model return a grounded summary instead of a generic one?
Does latency stay reasonable for the context size you used?
If you replace the context with a local file, does the answer change in the way you expect?
Stretch Task
Run the same task twice:
Once with the RLM client.
Once with a plain chat completion that pastes the same document directly into the prompt.
Write down what changed in cost, latency, or answer quality.
2.3 Debugging Lab
Lab Setup
Break the happy path on purpose. You learn more about the system by debugging failure modes than by watching one clean demo.
Debug Targets
Load the context from a file instead of an inline string.
Try a missing environment variable and inspect the error.
Try a small context and a very large context and compare the output tone.
Replace the query with something that requires a precise fact, not a vague summary.
Troubleshooting Prompts
If the answer is generic, did you actually provide enough inspectable source text?
If the import fails, are you using rlms as the package and rlm as the Python module?
If the request fails, is the provider key available in the current shell?
Debrief
Write a short note with three sections:
Failure
Root cause
Fix
The point of this lab is to build operational intuition, not just get a green run.
Build a Minimal RLM
Implement a small REPL-backed harness and inspect its failure modes.
3.1 Implement the REPL Harness
Goal
Implement the smallest useful REPL-backed loop yourself so the abstraction stops feeling magical.
Build Order
Store the long source material in self.repl_vars["context"].
Ask the model for either Python code or FINAL_ANSWER: ....
Execute Python when it appears.
Feed the REPL output back into the conversation.
Stop only when the model emits a final answer.
Minimal Skeleton
import ast
from openai import OpenAI
client = OpenAI()
class SimpleRLM:
def __init__(self, model="gpt-4o-mini"):
self.model = model
self.repl_vars = {}
def execute(self, code: str):
tree = ast.parse(code)
if tree.body and isinstance(tree.body[-1], ast.Expr):
return eval(compile(tree, "<string>", "eval"), self.repl_vars)
exec(compile(tree, "<string>", "exec"), self.repl_vars)
return "executed"
Implementation Notes
Use ast.parse before execution so syntax errors surface cleanly.
Keep the prompt explicit about the context variable and the FINAL_ANSWER: contract.
Append REPL output as a system message so the model can continue reasoning.
Expect malformed outputs and plan for retries.
Finish Line
Your harness can answer a question that requires inspecting context instead of guessing.
3.2 Playground Challenge
Challenge
Before you rely on an LLM to inspect context, formalize a small inspection task yourself. The playground below asks you to compute the most common word above a minimum length from raw text.
Why This Matters
RLMs work best when the inspection steps are crisp. If you cannot describe the task precisely, the model will struggle too.
count only words whose length is greater than min_length
if multiple words tie, return the lexicographically smallest one
print an empty string when no word qualifies
3.3 Code Review Checkpoint
Review The Minimal Harness
A minimal RLM is powerful because it is permissive. That is also why it is dangerous.
Issues To Spot
exec and eval can run arbitrary code.
The loop can continue forever without a max-steps guard.
A malformed model response can break the parser.
There is no sandbox, timeout, or resource limit around execution.
The model can overwrite REPL state in surprising ways.
Reflection
Which risk is still acceptable for a local toy project?
Which risk becomes unacceptable the moment you run untrusted input?
What is the smallest safety improvement you would implement next?
Next Step
Once the toy harness works, the next worthwhile upgrade is not more features. It is control: step limits, safer execution, better parsing, and observability.