Note: This document describes planned/aspirational features. See README.md for the current API.
A collection of reusable program components for composing multi-agent systems. Three categories: composites (multi-agent structural patterns), roles (single-agent behaviors), and controls (delegation flow patterns). Seventeen components total, expressed as prose .md files in lib/.
These are program nodes, not engine primitives. They live alongside programs, not inside the runtime. The engine does not know they exist. A program author references them; the model reads them and self-configures.
The stdlib is a library for program authors -- humans writing root.md files who need to compose agents into structures. It is not a runtime framework. It provides no APIs. It adds no engine complexity. It is markdown that gets injected into system prompts when a program references a component.
Three observations motivate it:
Patterns recur. Every program that needs quality assurance ends up building some version of work-then-critique. Every program that needs robust observation builds something like independent witnesses. These are structural patterns -- they describe how agents relate, not what agents do. Crystallizing them into reusable nodes means a program author does not reinvent the same topology each time.
Multi-polarity needs structure. The tenet "tension is structural error correction" (TENETS.md) says that a single agent rationalizes its own mistakes, and that two or three agents with distinct roles catch errors through adversarial tension. But multi-polarity is not "add more agents." It requires specific structural relationships: the critic must not see the worker's self-assessment, the observer must be independent of the actor, the ratchet must be unable to roll back certified progress. Composites encode these relationships as concrete, slottable patterns. The structural guarantees are in the pattern, not in the program author's discipline.
Roles fill slots. A composite like worker-critic declares two slots: worker and critic. What fills those slots? The program author might write domain-specific nodes. Or they might use a stdlib role -- the critic role is a single-agent behavior designed to fill the critic slot in any composite that needs one. Roles and composites compose: a role is a leaf, a composite is a coordinator, and together they form a small delegation subtree.
The stdlib is like supervised fine-tuning (SFT) for composition. SFT gives a base model a starting behavior -- hand-designed demonstrations of how to respond. RLHF then refines that behavior from feedback. The stdlib gives program authors a starting vocabulary of structural patterns -- hand-designed compositions of how agents should relate. The backpressure judge (BACKPRESSURE.md) provides the RLHF-like feedback loop.
The analogy is precise:
- SFT patterns are a seed. They bootstrap useful behavior, but they are not the final answer. The stdlib's 17 components are a starting vocabulary that will grow, shrink, and change as empirical traces reveal what works.
- RLHF refines what SFT starts. The judge analyzes execution traces, detects patterns the model discovers on its own, and promotes recurring effective patterns into the stdlib. It also retires components that consistently fail or go unused.
- Discovery is expected. A program author who invents an effective pattern not in the stdlib is doing the right thing. A model that discovers a structural arrangement that outperforms a named composite is doing the right thing. The stdlib is a seed, not a cage.
The long-term expectation: the hand-designed library converges toward an empirically-grounded one. Engineering intuition seeds it. Traces evolve it. The judge is the mechanism.
Multi-agent structural patterns. A composite is a coordinator node: it receives a task from a parent, manages internal multi-polar dynamics across two or three child agents, and returns a result. The composing parent calls a composite as one component. The children never know they are part of a composite.
Each composite declares slots -- named positions that the parent fills with component names before delegating. The composite reads its slot assignments from &compositeState and delegates accordingly. The structural relationships between slots (who sees whose output, what information is firewalled) are encoded in the composite's delegation logic.
Composites implement the multi-polarity tenet as concrete patterns. worker-critic creates tension between production and evaluation. witness creates tension between independent observations. ratchet creates tension between progress and certification. The tension is the structural error correction -- it is not a side effect, it is the point.
Single-agent reusable behaviors. A role is a leaf node: it receives a brief, does one thing, and returns a structured result. Roles do not delegate.
Roles serve two purposes. They fill composite slots -- the critic role fills the critic slot in worker-critic, the verifier role fills the ratchet slot in ratchet. They also stand alone as delegation targets -- a program author who needs classification can delegate to classifier directly without wrapping it in a composite.
The distinction between roles is in what they evaluate and how they return:
criticevaluates quality against criteria: accept/reject with reasoningverifierchecks formal correctness against constraints: valid/invalid with violationsclassifiercategorizes an item into one of a provided setextractormaps unstructured input to a target schemasummarizercompresses content while preserving specified information
Delegation flow patterns. A control is a coordinator that wraps other components to add iteration, parallelism, gating, or sequencing. Controls manage the flow of delegation -- they decide when, how often, and in what order to delegate to their wrapped targets.
Controls use &controlState (not &compositeState) for their slot-filling convention, reflecting that they manage flow rather than multi-polar tension.
The distinction between controls and composites: composites create structural tension between agents with different roles. Controls manage the delegation mechanics around agents that may have the same role. worker-critic is a composite because the worker and critic have fundamentally different jobs. retry-with-learning is a control because it delegates to the same target repeatedly with enriched briefs.
Every stdlib component is a .md file with YAML frontmatter. The frontmatter declares the component's identity, role, slots, and state dependencies. The body declares contracts, shape, and delegation logic -- often with illustrative JavaScript.
---
name: worker-critic
kind: program-node
role: coordinator
version: 0.1.0
slots: [worker, critic]
delegates: []
prohibited: []
state:
reads: [&compositeState]
writes: [&compositeState]
---slots lists the positions the parent must fill. delegates is empty because the composite does not have fixed children -- the parent decides what fills each slot at composition time. state declares &compositeState (for composites) or &controlState (for controls) as the communication channel with the parent.
Roles have no slots and no state dependencies:
---
name: critic
kind: program-node
role: leaf
version: 0.1.0
delegates: []
prohibited: []
state:
reads: []
writes: []
---Each component declares requires (what the caller must provide) and ensures (what the component guarantees). For composites and controls, requires specifies the &compositeState or &controlState shape:
requires:
- &compositeState exists at __compositeState with:
worker: string -- component name to use as worker
critic: string -- component name to use as critic
task_brief: string -- the task to pass to the worker
criteria: string -- acceptance criteria for the critic
max_retries: number -- (optional, default 3)
For roles, requires specifies what the brief must contain:
requires:
- Brief contains:
result: the work product to evaluate
criteria: what constitutes acceptance
task: the original task description
ensures declares postconditions and the return shape:
ensures:
- Worker receives only the task brief (first attempt) or task brief + critique (retries)
- Critic returns { verdict: "accept" | "reject", reasoning, issues, suggestions }
- On accept: return the worker's result immediately
- &compositeState.result contains the final output
- &compositeState.attempts contains the count
Composites and controls include illustrative JavaScript showing how the delegation loop works. This code is a starting point -- the model may improve upon it. A better model writes better delegation logic. But the structural guarantees (information firewalls, retry semantics, slot isolation) must be preserved.
// From worker-critic
const { worker, critic, task_brief, criteria, max_retries = 3 } = __compositeState;
let lastResult = null;
let lastCritique = null;
for (let attempt = 0; attempt < max_retries; attempt++) {
let workerBrief = task_brief;
if (lastCritique) {
workerBrief += `\n\nPrevious attempt was rejected.\nCritique: ${lastCritique.reasoning}`;
}
lastResult = await press(workerBrief, null, { use: worker });
const criticBrief = `Evaluate this result against the criteria.\n\nOriginal task: ${task_brief}\nCriteria: ${criteria}\n\nResult to evaluate:\n${lastResult}`;
const verdict = await press(criticBrief, null, { use: critic });
if (/accept/i.test(String(verdict))) {
__compositeState.result = lastResult;
__compositeState.attempts = attempt + 1;
RETURN(lastResult);
}
lastCritique = verdict;
}Stdlib components become available when registered in childComponents. A program author can reference them in root.md's component catalog alongside domain-specific nodes. The engine loads the component's .md file as the child's <rlm-program> when the parent delegates with { use: "worker-critic" }.
The composing parent sets up slot assignments in &compositeState (or &controlState) before delegating. The composite reads these assignments and delegates to the named components:
// Parent sets up the composite
__compositeState = {
worker: "my-domain-worker", // a program-specific component
critic: "critic", // the stdlib critic role
task_brief: "Analyze this dataset and produce a summary.",
criteria: "Summary must contain all key findings and be under 500 words.",
max_retries: 3
};
const result = await press("Run worker-critic on this task", null, { use: "worker-critic" });
// After return: __compositeState.result has the accepted outputRoles are designed to fill composite slots. The critic role produces { verdict, reasoning, issues, suggestions } -- exactly the shape that worker-critic's critic slot expects. The verifier role produces { valid, violations, checks_passed } -- a natural fit for ratchet's certification slot when the criteria are formal constraints.
The mapping is not enforced. Any component that satisfies a slot's behavioral expectations can fill it. A domain-specific node can fill a composite slot. A role can fill a slot in a domain-specific composite. The stdlib provides defaults; the program author decides.
Controls wrap other delegations. The parent sets up &controlState with the target component and flow parameters:
// Retry a component with failure learning
__controlState = {
target: "level-solver",
task_brief: "Complete level 3. Grid is 10x10, goal is in top-right.",
max_retries: 3
};
const result = await press("Retry with learning", null, { use: "retry-with-learning" });// Gate: check preconditions before expensive delegation
__controlState = {
guard: "classifier",
target: "expensive-analyzer",
task_brief: "Analyze this dataset for anomalies."
};
const result = await press("Gate check", null, { use: "gate" });
// __controlState.proceeded tells you if the guard passedRoles can be used without a composite. Delegate directly when you need a single-agent behavior:
const summary = await press(
`Summarize this content. Preserve: key decisions, open questions.\n\n${largeContent}`,
null,
{ use: "summarizer" }
);A pattern belongs in the stdlib when it meets four criteria:
Recurrence. It appears across multiple programs. A pattern used in only one program is a program-local component, not a library component. When the same structural arrangement shows up in arc3, in the judge, and in a data analysis program, it is a candidate.
Structural, not domain-specific. It describes how agents relate (actor/observer, proposer/adversary, sequential stages), not what agents do (analyze grids, parse JSON, play games). The worker-critic pattern works for code review, essay writing, and data analysis because it is about the relationship between production and evaluation, not about any particular domain.
Clear slot interfaces. The component has named slots with documented behavioral expectations. A parent can fill the slots without reading the component's implementation -- the contract is sufficient.
Bitter-lesson compatibility. A better model should use the same pattern more effectively. The pattern does not bet against model improvement. worker-critic gets better with a better model because the worker produces better work and the critic catches subtler issues. A pattern that relies on model limitations (e.g., "the model needs 5 retries because it always fails the first time") is not a good stdlib candidate.
- A pattern appears in a program as a local component.
- The same pattern appears in a second program.
- The judge (BACKPRESSURE.md) detects the recurrence in traces and flags it as a candidate.
- A human reviews, generalizes the pattern into a slot-based component, and adds it to
lib/. - The original program-local components are replaced with references to the stdlib version.
The demotion path is the reverse: a component that is consistently unused or ineffective across traces gets retired.
| Component | Description | Slots |
|---|---|---|
worker-critic |
Work, evaluate, retry until accepted or budget exhausted | worker, critic |
proposer-adversary |
Propose, then attack the proposal; parent decides | proposer, adversary |
observer-actor-arbiter |
Act, observe independently, arbitrate next step | actor, observer, arbiter |
ensemble-synthesizer |
K agents work independently, synthesizer merges by reasoning about disagreements | ensemble_member, synthesizer |
dialectic |
Thesis and antithesis argue positions; disagreement is the output | thesis, antithesis |
witness |
Two agents independently observe same data; discrepancies flag ambiguity | witness_a, witness_b |
ratchet |
Advance and certify; certified progress is never rolled back | advancer, ratchet |
| Component | Description | Natural composite slot |
|---|---|---|
critic |
Evaluate result against criteria; accept or reject with structured reasoning | worker-critic.critic |
verifier |
Check result against formal constraints; correctness, not quality | ratchet.ratchet |
summarizer |
Compress large context preserving specified key information | Pipeline stage, curation |
classifier |
Categorize an item given categories and criteria | gate.guard, routing |
extractor |
Pull structured data from unstructured input given a target schema | Pipeline stage, state population |
| Component | Description | Slots |
|---|---|---|
retry-with-learning |
Retry with failure analysis passed to each subsequent attempt | target |
progressive-refinement |
Iteratively improve through rounds until quality threshold met | refiner, evaluator |
map-reduce |
Split input into chunks, delegate to mappers, merge with reducer | mapper, reducer |
pipeline |
Sequential transformation; each stage sees only predecessor's output | stages[] |
gate |
Check precondition before delegating; fail-fast | guard, target |
lib/
composites/
worker-critic.md
proposer-adversary.md
observer-actor-arbiter.md
ensemble-synthesizer.md
dialectic.md
witness.md
ratchet.md
roles/
critic.md
verifier.md
summarizer.md
classifier.md
extractor.md
controls/
retry-with-learning.md
progressive-refinement.md
map-reduce.md
pipeline.md
gate.md