For working on your code.
Use a coding agent for interactive development: explore a codebase, make changes, and review the result.
Rulvar is an embeddable TypeScript runtime for multi-agent work. Route every model call, bound priced spend, and keep completed work in a durable journal. After a crash or deploy, journal-matched calls replay without a new provider request.
pnpm add @rulvar/rulvar
ship-feature-042
anthropic:claude-fable-5
openai:gpt-5.6-terra
ollama:qwen3.8:27b
openai:gpt-5.6-luna
Use a coding agent for interactive development: explore a codebase, make changes, and review the result.
Use Rulvar when the workflow must own routing, budgets, policy, durable state, tests, and a typed outcome without requiring an operator at every step.
Rulvar is a library, not a hosted control plane. It runs in your Node.js application and keeps workflow logic in ordinary TypeScript.
Follow ship-feature-042 through execution,
a crash, and recovery. Scroll to move through the run.
Bind a goal, policy, and USD ceiling before work begins.
Choose a model by call, profile, workflow, or engine default.
Priced work passes budget admission before provider dispatch.
Completed LLM calls settle into the content-addressed journal.
The coordinator is checkpointed, one child is complete, and another is in flight.
Restore the checkpoint, replay the completed child, and continue unfinished work live.
Receive a typed outcome with status, usage, and an estimated cost report.
orchestrate(engine, goal, options, { budgetUsd: 5 })
anthropic:claude-fable-5
route unresolved
openai:gpt-5.6-terra
waiting
ollama:qwen3.8:27b
waiting
openai:gpt-5.6-luna
waiting
orchestrator/checkpointrecorded
child/implementer/00completed
child/local-reviewer/00in flight
Only completed and journaled calls replay. An in-flight turn may run and be billed again.
Cross-process resume requires durable journal storage. Turn checkpoints and planner-compiled workflows also need a durable transcript store; the defaults are in memory.
A model without a price row is reported as unpriced and cannot be bounded by the USD ceiling.
Routing, budgets, journal identity, events, and tests share the same execution path in every authoring mode.
anthropic:claude-fable-5HOSTEDopenai:gpt-5.6-solHOSTEDopenai:gpt-5.6-terraHOSTEDopenai:gpt-5.6-lunaHOSTEDollama:qwen3.8:27bLOCAL / UNPRICEDThe runtime routes all seven invocation roles independently. Within one agent call, loop, finalize, extract, and summarize may use different providers; plan, orchestrate, and post-fan-in synthesize are routed separately.
vllm:zai-org/GLM-5.3-Flash
vllm:moonshotai/Kimi-K3
The ceiling is fixed for each segment. Overshoot is bounded by at most one in-flight turn per agent and depends on provider usage reporting. A resume-time budget override opens a new recorded segment. An opt-in lifetime policy can lock the ceiling across segments. Cost reports are estimates, not provider invoices.
Budget contract ↗wf:ship-feature:0/agent:0sha256:87c2...91e700Resume re-executes the workflow body. Compatible completed entries replay from the journal, while changed or new work becomes a live miss.
Journal semantics ↗✓ FakeAdapter returned a typed fixture
✓ VCR cassette matched the canonical request
✓ Journal replay required 0 live calls
✓ Typed event stream settled with status: ok
4 checks · 0 API keys · 0 live provider calls
Fake adapters support fast unit tests. Redacted cassettes replay provider exchanges, and replay-strict runs fail on the first would-be live call. Recording a new cassette still requires a live provider request.
Testing guide ↗External side effects need their own safety design. Rulvar's effect lane records intent before effect and binds retries to attempts, but it does not promise exactly-once external execution. Provider-side fencing or idempotency and host reconciliation remain required. Read the effects guide ↗
Register only the adapters you use, route invocation roles, attach durable stores, and start the workflow with a segment ceiling.
pnpm add @rulvar/rulvar @rulvar/openai
import {
anthropic,
createEngine,
FileTranscriptStore,
JsonlFileStore,
openai,
orchestrate,
} from '@rulvar/rulvar';
import { openaiCompatible } from '@rulvar/openai';
const engine = createEngine({
adapters: [
anthropic(),
openai(),
openaiCompatible({
id: 'ollama',
baseURL: 'http://127.0.0.1:11434/v1',
}),
],
defaults: {
routing: {
orchestrate: 'anthropic:claude-fable-5',
plan: 'openai:gpt-5.6-sol',
loop: 'openai:gpt-5.6-terra',
finalize: 'openai:gpt-5.6-terra',
extract: 'openai:gpt-5.6-luna',
summarize: 'ollama:qwen3.8:27b',
synthesize: 'anthropic:claude-fable-5',
},
profiles: {
implementer: {
description: 'Implements the requested change.',
model: 'openai:gpt-5.6-terra',
},
'local-reviewer': {
description: 'Reviews the patch on a private endpoint.',
model: 'ollama:qwen3.8:27b',
},
extractor: {
description: 'Returns the structured result.',
model: 'openai:gpt-5.6-luna',
},
},
},
stores: {
journal: new JsonlFileStore({ dir: '.rulvar/journal' }),
transcripts: new FileTranscriptStore({ dir: '.rulvar/transcripts' }),
},
});
const goal = 'Implement and verify the requested feature';
const run = orchestrate(
engine,
goal,
{
profiles: ['implementer', 'local-reviewer', 'extractor'],
maxSpawns: 8,
},
{
budgetUsd: 5,
runId: 'ship-feature-042',
},
);
const outcome = await run.result;
console.log(outcome.status, outcome.cost.totalUsd, outcome.cost.unpriced);