The 80% of the API you’ll use, all on one page. For full signatures and option types, see the generated Builder API reference and Configuration reference (both emitted from the schema — the single source of truth).
Minimum viable agent
Section titled “Minimum viable agent”The front door — a declarative config object:
import { createAgent } from "reactive-agents";
const agent = await createAgent({ name: "assistant", provider: "anthropic",});
const result = await agent.run("What's 2 + 2?");console.log(result.output);That’s it. Provider key from .env, model auto-picked, direct LLM loop. The
same agent via the fluent builder:
import { ReactiveAgents } from "reactive-agents";
const agent = await ReactiveAgents.create() .withName("assistant") .withProvider("anthropic") .build();Builder Methods (most-used)
Section titled “Builder Methods (most-used)”Identity & provider
Section titled “Identity & provider”| Method | Status | What it does |
|---|---|---|
.withName(name) | recommended | Identifier for logs, telemetry, A2A |
.withProvider(p) | essential | "anthropic" · "openai" · "gemini" · "groq" · "xai" · "ollama" · "litellm" · "test" |
.withModel(id) | recommended | e.g. "claude-sonnet-4-6", "gpt-4o", "qwen3:14b" |
.withSystemPrompt(s) | opt-in | Persona / instructions for the agent |
Cognition
Section titled “Cognition”| Method | Status | What it does |
|---|---|---|
.withReasoning() | essential | ReAct loop (default). Pass { defaultStrategy: "tree-of-thought" } to switch. |
.withTools() | recommended | Built-in tools + meta-tools (recall, find, brief, pulse) |
.withTools({ tools: [myTool] }) | opt-in | Add custom tools to the registry |
.withMemory() | recommended | 4-layer memory, tier "standard" (FTS5 keyword search) |
.withMemory({ tier: "enhanced" }) | opt-in | + vector embeddings (needs EMBEDDING_PROVIDER) |
.withSkills({ paths: ["./skills/"] }) | opt-in | Living Skills System — agentskills.io compatible |
Production safety
Section titled “Production safety”| Method | Status | What it does |
|---|---|---|
.withGuardrails() | recommended | Pre-LLM injection / PII / toxicity blocking |
.withVerification() | opt-in | Post-LLM fact-check (semantic entropy, NLI) |
.withCostTracking() | recommended | Complexity routing + budget enforcement |
.withIdentity() | advanced | Ed25519 certificates + RBAC + delegation |
.withKillSwitch() | recommended | Per-agent + global emergency halt |
.withRequiredTools({ tools: ["web-search"] }) | opt-in | Force critical tool calls before answering |
.withApprovalPolicy({ tools, mode: "detach" }) | opt-in | Gate tool calls behind durable human approval (HITL) |
Observability
Section titled “Observability”| Method | What it does |
|---|---|
.withObservability({ verbosity: "normal", live: true }) | Metrics dashboard + live phase logs + tracing |
.withLogging({ level, format, filePath }) | Structured logs (rotates at maxFileSizeMb) |
.withCortex() | Stream telemetry to Cortex Studio over WebSocket |
.withHealthCheck() | Adds agent.health() probe |
Reliability
Section titled “Reliability”| Method | What it does |
|---|---|
.withTimeout(ms) | Hard execution timeout |
.withRetryPolicy({ maxRetries, backoffMs }) | Retry on transient LLM failures |
.withFallbacks({ providers, errorThreshold }) | Provider/model fallback chain |
.withErrorHandler(fn) | Global error callback |
.withMinIterations(n) | Force at least N reasoning steps |
.withVerificationStep({ mode: "reflect" }) | LLM self-review before answering |
.withOutputValidator(fn) | Retry until output passes a predicate |
.withCustomTermination(fn) | User-defined “done” check |
.withDurableRuns({ dir, checkpointEvery }) | Checkpoint every iteration to SQLite; crash-resume via resumeRun (Durable Execution) |
Multi-agent & gateway
Section titled “Multi-agent & gateway”| Method | What it does |
|---|---|
.withDynamicSubAgents({ maxIterations }) | Model-spawned sub-agents at runtime |
.withAgentTool(name, config) | Named purpose-built sub-agent |
.withOrchestration() | Sequential / parallel / pipeline / map-reduce |
.withA2A() | Agent Cards + JSON-RPC + SSE for cross-agent calls |
.withGateway({ heartbeat, crons, webhooks, policies }) | Persistent autonomous harness |
| Method | What it does |
|---|---|
.withHook({ phase, timing, handler }) | Intercept any of the 12 phases |
.withHook({ phase: "act", timing: "after", handler: (ctx) => Effect.succeed(ctx),})Phases: bootstrap · guardrail · cost-route · strategy-select · think · act · observe · verify · memory-flush · cost-track · audit · complete
Runtime methods (after .build())
Section titled “Runtime methods (after .build())”| Method | Returns |
|---|---|
agent.run(task) | Promise<AgentResult> — full execution (status: "awaiting-approval" if gated) |
agent.run(task, { onApproval }) | Same-process HITL — callback drives pause → decide → resume |
agent.runStream(task, { signal }) | AsyncGenerator<AgentEvent> — token streaming |
agent.chat(question) | Promise<string> — single-turn Q&A with adaptive routing |
agent.session() | Multi-turn session with memory |
agent.subscribe(tag, fn) | Listen to EventBus events |
agent.registerTool(def, handler) | Add a tool at runtime |
agent.unregisterTool(name) | Remove a tool at runtime |
agent.listRuns({ status? }) | Persisted durable runs, newest first (needs .withDurableRuns()) |
agent.resumeRun(runId) | Reconstruct + finish a crashed run from its last checkpoint |
agent.listPendingApprovals() | Runs paused at an approval gate, awaiting a decision |
agent.approveRun(runId) / agent.denyRun(runId, reason) | Resume a paused run — execute or skip the gated call |
agent.health() | { status, checks[] } — readiness probe |
agent.dispose() | Cleanup MCP + open resources |
AgentResult shape:
{ output: string, success: boolean, debrief?: { summary, keyFindings, metrics }, terminatedBy: "final_answer_tool" | "final_answer" | "max_iterations" | "end_turn" | "llm_error" | "abstained", abstention?: { reason, missing }, // present iff terminatedBy === "abstained" metadata: { duration, cost, tokensUsed, stepsCount, strategyUsed },}Event tags (subscribe via agent.on())
Section titled “Event tags (subscribe via agent.on())”| Tag | Fires when |
|---|---|
AgentStarted / AgentCompleted | Task begins / ends |
ReasoningStepCompleted | Each thought / action / observation |
ToolCallCompleted | Each tool call ({ toolName, durationMs, success }) |
IterationProgress | Every reasoning loop iteration (streaming) |
StrategySwitched | Auto-strategy-switch triggered |
GuardrailViolationDetected | Input blocked |
LLMRequestStarted / LLMRequestCompleted | Each LLM API call |
MemoryBootstrapped / MemoryFlushed | Memory loaded / written |
FinalAnswerProduced | Final answer extracted from loop |
ContextSynthesized | Context curation step ran |
TextDelta | Token-level streaming chunk (runStream only) |
StreamCompleted / StreamCancelled | Stream end states |
Streaming pattern
Section titled “Streaming pattern”const controller = new AbortController();
for await (const event of agent.runStream("Analyze this", { signal: controller.signal })) { if (event._tag === "TextDelta") process.stdout.write(event.text); if (event._tag === "IterationProgress") console.log(`Step ${event.iteration}/${event.maxIterations}`); if (event._tag === "StreamCompleted") { console.log(event.toolSummary); // Array<{ toolName, calls, successRate }> }}
// Cancel from anywherecontroller.abort();One-line SSE endpoint:
import { AgentStream } from "reactive-agents";Bun.serve({ fetch: (req) => AgentStream.toSSE(agent.runStream("Hello")) });Functional composition
Section titled “Functional composition”import { agentFn, pipe, parallel, race } from "reactive-agents";
// Lazy agent functionsconst researcher = agentFn({ name: "researcher", provider: "anthropic" }, (b) => b.withReasoning().withTools());
// Sequential pipelineconst pipeline = pipe(researcher, summarizer);const result = await pipeline("Find latest AI news");
// Parallel fan-out — output contains labeled results from all 3const multi = parallel(sentimentAgent, keywordAgent, summaryAgent);
// Fastest winsconst fastest = race(claudeAgent, gpt4Agent);
// Cleanupawait pipeline.dispose();Agent as data
Section titled “Agent as data”import { agentConfigToJSON, ReactiveAgents } from "reactive-agents";
const builder = ReactiveAgents.create() .withName("researcher") .withProvider("anthropic") .withReasoning({ defaultStrategy: "plan-execute-reflect" }) .withTools({ adaptive: true }) .withMemory({ tier: "enhanced" });
const json = agentConfigToJSON(builder.toConfig());// Save to DB / send over wire / commit to repo
const restored = await ReactiveAgents.fromJSON(json);const agent = await restored.build();Environment variables
Section titled “Environment variables”# Pick one provider key (or run local Ollama)ANTHROPIC_API_KEY=sk-ant-...OPENAI_API_KEY=sk-...GOOGLE_API_KEY=...GROQ_API_KEY=gsk_...XAI_API_KEY=xai-...
# Optional — enables built-in toolsTAVILY_API_KEY=tvly-... # Web searchSERPER_API_KEY=... # Web search (alt)
# Optional — vector memory ("enhanced" tier)EMBEDDING_PROVIDER=openai # or "ollama"EMBEDDING_MODEL=text-embedding-3-small
# TuningLLM_DEFAULT_MODEL=claude-sonnet-4-6LLM_DEFAULT_TEMPERATURE=0.7LLM_MAX_RETRIES=3LLM_TIMEOUT_MS=30000CLI (rax)
Section titled “CLI (rax)”bunx rax init my-app --template standard # Scaffold a projectrax create agent researcher --recipe researcher # Generate from reciperax run "Explain X" --provider anthropic # Run an agentrax serve --port 4111 # Expose as A2A HTTP serverrax cortex # Launch Cortex Studiorax playground # Interactive REPLrax eval run --suite ./eval-suite.yaml # Run an evaluationrax inspect <agent-id> # Debug a sessionrax health # Check provider readinessFull reference: CLI Commands.
Mental model
Section titled “Mental model”A ReactiveAgent is a runtime built from composable Layers. Each .with*() adds a Layer. build() composes them into the ExecutionEngine’s 12-phase lifecycle. agent.run() flows a task through all 12 phases. Hooks intercept any phase. Events fire from every phase. No singletons, no global state — each agent is its own isolated runtime.
.withProvider() · .withReasoning() · .withTools() · .withMemory() ↓ build() composes Layers ↓ 12-phase ExecutionEngine ↓ bootstrap → guardrail → cost-route → strategy-select ↓ ⟲ think → act → observe ⟲ ↓ verify → memory-flush → cost-track → audit → complete ↓ AgentResultFor the deep dive, see Architecture and Layer System.