Reactive Agents

A composable TypeScript framework for building reliable LLM agents on a harness you fully control. It wraps the agent loop — think, call a tool, observe, repeat — and keeps the loop finishing across model tiers while exposing every step as a typed event you can hook into. Three things it's built around:

  • 🛡️ Reliable on every model tier. Tool-call healing, output verification, durable crash-resume, and a single-owner termination oracle let the same code finish the agent loop on a local 4B Ollama model and on Claude / GPT / Gemini.
  • 🔍 Transparent. A deterministic 12-phase execution engine with before / after / on-error hooks on every phase. Every prompt, tool call, and reasoning step is a typed event you can inspect, steer, and replay — locally, no SaaS dashboard required.
  • 🧩 Composable. A typed builder of opt-in layers. Start with a model; add reasoning, 4-tier memory, guardrails, cost routing, and durability one .with() call at a time.

Built on Effect-TS — schema-validated boundaries, tagged errors, no untyped throws.

41 packages & apps 34 packages + 5 apps — 33 published to npm, all opt-in, no hidden coupling
8 LLM providers Anthropic, OpenAI, Gemini, Groq, xAI, Ollama (local), LiteLLM 40+, Test
7 reasoning strategies ReAct · Blueprint · Reflexion · Plan-Execute · Tree-of-Thought · Adaptive · Code-Action (@exp)
8,276 tests · 1060 files Verified with bun test on every PR
12-phase execution Deterministic lifecycle with before/after/error hooks per phase
Cortex Studio Live agent canvas, entropy charts, debrief UI, agent builder
Effect-TS end to end Compile-time type safety, schema-validated boundaries, tagged errors

CI npm License: MIT TypeScript Effect-TS Bun PRs Welcome Open in GitHub Codespaces

Documentation · Discord · Quick Start · Features · Comparison · Architecture · Packages


Reliable on every tier — see it for yourself

The same agent investigates an incident, calls two tools, correlates the data, and recommends a fix — and finishes the job on a 4B local model just like on Claude. One builder, the only line that changes is the model. Demo source.

…and survives a crash mid-run

Durable execution: kill the process mid-run, and a fresh process reconstructs the run from its last on-disk checkpoint and finishes the job — completed tools never re-run. Demo source.


Why Reactive Agents?

Most AI agent frameworks are dynamically typed, monolithic, and opaque. They assume you're using GPT-4, break when you try smaller models, and hide every decision behind abstractions you can't inspect. Reactive Agents takes a fundamentally different approach:

Problem How We Solve It
No type safety Effect-TS schemas validate every service boundary at compile time
Monolithic 13 independent layers -- enable only what you need
Opaque decisions 12-phase execution engine with before/after/error hooks on every phase
Model lock-in Model-adaptive context profiles (4 tiers: local, mid, large, frontier) help smaller models punch above their weight
Single reasoning mode 7 strategies (ReAct, Blueprint, Reflexion, Plan-Execute, Tree-of-Thought, Adaptive, Code-Action @experimental)
Unsafe by default Guardrails block injection/PII/toxicity before the LLM sees input
No cost control Complexity router picks the cheapest capable model; budget enforcement at 4 levels
Poor DX Builder API chains capabilities in one place

Cortex Studio

A full-featured local studio for live debugging — start it with .withCortex() or rax run --cortex:

→ Full Cortex documentation with more screenshots

Features

Grouped by capability. Every layer is opt-in — call .with*() only for what you need.

🧠 Reasoning & Cognition

  • 7 reasoning strategies + adaptive meta-strategy: ReAct, Blueprint (efficient static-decomposable), Reflexion, Plan-Execute, Tree-of-Thought, Adaptive, Code-Action (@experimental)
  • Intelligent context synthesis — fast-template or deep-LLM transcript shaping per iteration (ContextSynthesized on EventBus)
  • Reactive intelligence — 5-source entropy sensor + 8-action controller (early-stop, compress, switch strategy, adjust temp, inject tool, activate skill, redirect on failure, stall-detect) + Thompson Sampling bandit
  • Adaptive calibration — three-tier live learning (shipped prior → community profile → local posterior) with per-run observations and classifier bypass

💾 Memory & Skills

  • 4-layer memory — working, episodic, semantic (vector + FTS5), procedural — backed by bun:sqlite with background consolidation + decay
  • ExperienceStore — cross-agent learning loop closed by ToolCallObservation
  • Living Skills System — agentskills.io SKILL.md compatible, SQLite-backed, LLM-refined evolution, 5-stage compression, context-aware injection guard
  • Agent debrief + chatagent.chat() for one-shot Q&A, agent.session() for multi-turn (optional SQLite persistence), post-run DebriefSynthesizer

🔌 Providers & Models

  • 8 LLM providers — Anthropic, OpenAI, Google Gemini, Groq, xAI (Grok), Ollama (local), LiteLLM (40+ models), Test (deterministic)
  • Model-adaptive context profiles — 4 tiers (local / mid / large / frontier) with tier-aware prompts, compaction, and truncation; 4B+ Ollama models work with the same code
  • Adaptive tool calling — FC dialect probe routes to NativeFCDriver or 3-tier TextParseDriver (XML / JSON / pseudo-code)
  • HealingPipeline — normalizes tool-name aliases, param aliases, paths, and type coercion before every execution, so malformed tool calls from smaller models get repaired instead of failing
  • Provider fallback chainswithFallbacks() for graceful degradation across providers and models
  • Native thinking mode.withThinking({ effort, budgetTokens }) opts into provider-native reasoning across all four cloud/local adapters (off unless enabled); .withModel({ thinking: true }) is the quick boolean
  • Cost-aware model routing.withModelRouting() (opt-in, off by default) routes each run to the cheapest capable model of the configured provider by task complexity, degrading to the configured model on any error

🛡️ Production Safety

  • Guardrails — pre-LLM injection detection, PII filtering, toxicity blocking, kill switch, behavioral contracts
  • Ed25519 identity — real cryptographic agent certificates, RBAC, delegation chains, audit trails
  • Verification — semantic entropy, fact decomposition, NLI hallucination detection
  • Fabrication guard.withFabricationGuard() is on by default; rejects invented empirical performance measurements (benchmark timings, % speed-ups) absent from the tool-observation corpus. Soften to "warn" or disable with "off"
  • Stall / no-progress policy.withStallPolicy() bounds wasted iterations when the model ignores required-tool nudges: fast-escalate after N ignored nudges instead of looping to the full cap (progress resets the streak)
  • Harness-forced abstention — when grounding is structurally impossible (a required tool is missing, or synthesis is repeatedly rejected as ungrounded), the run ends honestly with terminatedBy: "abstained" and result.abstention { reason, missing } instead of fabricating or grinding to max_iterations
  • Cost controls — multi-factor complexity router (task length, code presence, multi-step markers, tool-reliability escalation), semantic cache, budget enforcement (persists across restarts), dynamic pricing via OpenRouter
  • Required tools guard — ensure critical tools are called before answering, with maxCallsPerTool budgets to prevent research loops
  • Evidence ledger + deliverable-truth — every run keeps an append-only ledger (tool invocations, artifacts with path + content digest — including files written by code-execute / shell / MCP tools — verifier verdicts, and the answer's evidence claims) that rides crash-resume. It also compiles a typed contract of what "done" means from the task; the terminal gate checks requirement satisfaction against the ledger, and result.receipt.deliverables[] names each declared output as produced or missing — a partial multi-file run reports exactly which outputs never landed instead of claiming success. Default-on in a reasoning run

🔭 Observability

  • 12-phase execution engine — deterministic lifecycle with before / after / on-error hooks per phase
  • Professional metrics dashboard — EventBus-driven execution timeline, tool-call summary, cost estimation, smart alerts (zero manual instrumentation)
  • Distributed tracing (OTLP) + structured logging via withLogging({ level, format, filePath })
  • Cortex Studio live reporting.withCortex(url?) streams runtime telemetry over WebSocket
  • Streaming + SSEagent.runStream() with AbortSignal cancellation; one-line SSE endpoint via AgentStream.toSSE()
  • Per-iteration run assessment — every iteration emits an assessment trace event (requirements satisfied/outstanding, deliverables, evidence delta, run phase — orient/gather/execute/synthesize/verify — pace band, health), visible in rax diagnose replay. The measurement is always on; its consumption by adaptive pacing is behind the opt-in flags below

🧩 Composition & Multi-Agent

  • Builder API — chains capabilities in one place; Agent-as-data via toConfig() / fromJSON() for save/share/restore
  • Two-line entry pointReactiveAgents.quick() resolves provider, model, and iteration defaults from the environment and returns a ready-to-run agent
  • Functional combinatorsagentFn(), pipe(), parallel(), race() for declarative agent pipelines
  • A2A protocol — Agent Cards, JSON-RPC 2.0 server/client, SSE streaming, agent-as-tool
  • Orchestration — sequential, parallel, pipeline, map-reduce; dynamic sub-agent spawning with depth limits
  • Persistent gateway — adaptive heartbeats, cron scheduling, webhook ingestion (GitHub adapter), composable policy engine, chat mode with per-sender SQLite session history

⚙️ Builder Hardening

  • withStrictValidation(), withTimeout(), withLlmTimeout() (per-LLM-call timeout for local/Ollama providers — tolerate cold model loads without loosening the run-level timeout), withRetryPolicy(), withErrorHandler(), withFallbacks(), withLogging(), withHealthCheck(), withMinIterations(), withVerificationStep(), withOutputValidator(), withCustomTermination(), withTaskContext()
  • defineTool typed tool authoring — Standard Schema input (Effect Schema / Zod / Valibot / ArkType) + a plain async handler with arg types inferred from the schema; malformed options (parameters/execute instead of input/handler) fail fast with a typed error
  • ToolBuilder fluent API — define tools without raw schema objects
  • Dynamic tool registrationagent.registerTool() / agent.unregisterTool() at runtime
  • .withLongHorizon() (opt-in, off by default) — scales the guard thresholds (stall, consecutive-thoughts, redirect/nudge budgets) proportionally to maxIterations so a 40+ iteration research run isn't tripped by guards tuned for short runs. Verified to let a long-horizon task run to completion; not yet lift-gated for default-on. When not called, behavior is byte-identical to the default
  • .withAdaptiveHarness() (opt-in, experimental) — a policy compiler derives the run's harness (strategy, guard depth, horizon profile) from model tier + task classification + horizon at run-start, and recompiles mid-run on progress evidence; explicit .withX() withers override the compiled plan. Under active validation — its cross-tier ablation was inconclusive (n=1 dev-hardware noise), so it is not default-on and sits under a lift-gate veto

🌐 Frontend Integration

  • @reactive-agents/ui-core — headless, framework-agnostic core: versioned wire protocol, resumable stream client (cursor reconnect), run state machine, safe generative-UI trees, durable human-in-the-loop rails, and zero-token fixture testing. The engine the bindings share.
  • @reactive-agents/react — React 18+ hooks + components: useRun, useResumableRun, useInteractions, useTaskInbox, useRunCost/useRunSteps, AgentSurface, AgentDevtools, and the useAgentStream/useAgent classics
  • @reactive-agents/vue — Vue 3 composables with reactive refs
  • @reactive-agents/svelte — Svelte 4/5 stores (createRun, createResumableRun, createInteractions, createAgentStream, …)
  • All build on ui-core and consume AgentStream.toSSE() + the durable endpoint helpers from Next.js, SvelteKit, Nuxt, or any SSE-capable server

✅ Confidence

  • 8,276 tests across 1060 files — verified bun test on every PR
  • Strict TypeScript — Effect-TS schemas validate every service boundary; explicit tagged errors, no untyped throws

Quick Start

Install and run your first TypeScript AI agent in under 60 seconds.

Recommended: Bun ≥1.0.0 — optimal performance with native SQLite, subprocess, and HTTP APIs. Node.js 22.5+ is now also supported via @reactive-agents/runtime-shim — same code, both runtimes. Install Bun: curl -fsSL https://bun.sh/install | bash

# Bun (recommended)
bun add reactive-agents

# Node.js 22.5+
npm install reactive-agents

Note: effect is included as a dependency of reactive-agents and installed automatically. If you import from effect directly in your own code (e.g. import { Effect } from "effect"), add it to your project explicitly: bun add effect (or npm install effect).

createAgent(config) is the front door — one declarative config object, the shape you already know from the Vercel AI SDK and OpenAI SDK. This is the 90% case:

import { createAgent } from 'reactive-agents'

const agent = await createAgent({
  name: 'assistant',
  provider: 'anthropic',
  model: 'claude-sonnet-4-6',
})

const result = await agent.run('Explain quantum entanglement')
console.log(result.output)
console.log(result.metadata) // { duration, cost, tokensUsed, stepsCount }

Add Capabilities

Add capabilities as config keys — grouped by domain, so autocomplete reads like a menu. Start from a profile preset ("lean", "balanced", "intelligent") and override individual keys:

import { createAgent } from 'reactive-agents'

const agent = await createAgent({
  name: 'research-agent',
  provider: 'anthropic',
  model: 'claude-sonnet-4-6',
  profile: 'balanced',                        // memory + RI + verifier + strategy switching
  tools: { allowedTools: ['web-search', 'file-write'] },
  budget: { tokenLimit: 100_000 },            // canonical budget killswitch
})

Pick the profile that matches the workload:

  • "lean" — model + nothing else. Latency- and cost-sensitive paths; benchmark ablations.
  • "balanced" — today's production defaults (memory + reactive intelligence + verifier + strategy switching).
  • "intelligent" — balanced + skill persistence for cross-session compounding learning.

Advanced: the fluent builder

createAgent(config) and the fluent builder are the same API in two syntaxes — same names, same nesting. Reach for the builder when construction is conditional or imperative (branch on runtime state, inject code-only escape hatches like hooks/layers, or compose a precise chokepoint) — things that read awkwardly as static data:

import { ReactiveAgents, HarnessProfile } from 'reactive-agents'

let builder = ReactiveAgents.create()
    .withName('research-agent')
    .withProvider('anthropic')
    .withProfile(HarnessProfile.intelligent())  // cross-session skills
    .withMemory({ tier: 'enhanced' })           // upgrade memory to vector embeddings
    .withTools()

if (process.env.AUTONOMOUS) {
    builder = builder.withGateway({             // persistent autonomous harness
        heartbeat: { intervalMs: 1_800_000, policy: 'adaptive' },
        crons: [{ schedule: '0 9 * * MON', instruction: 'Weekly review' }],
        policies: { dailyTokenBudget: 50_000 },
    })
}

const agent = await builder
    .compose((h) => h.before('act', (ctx) => { console.log(ctx.phase) }))  // precise chokepoint
    .build()

The full builder / config reference is generated from the schema (the single source of truth): builder-api · configuration.

Conversational Chat

Use agent.chat() for single-turn Q&A or agent.session() for multi-turn conversations with adaptive routing -- direct LLM for simple questions, full ReAct loop for tool-capable queries:

// Single-turn chat
const answer = await agent.chat("What's the status of the deployment?")

// Multi-turn session
const session = agent.session()
await session.chat("Summarize yesterday's logs")
await session.chat('Which errors were most frequent?')

Agent Config (Agent as Data)

Define agents as JSON-serializable config objects. Save, share, and reconstruct agents without code:

import {
    agentConfigToJSON,
    agentConfigFromJSON,
    ReactiveAgents,
} from 'reactive-agents'

// Builder → Config → JSON
const builder = ReactiveAgents.create()
    .withName('researcher')
    .withProvider('anthropic')
    .withReasoning({ defaultStrategy: 'plan-execute-reflect' })
    .withTools({ adaptive: true })
    .withMemory({ tier: 'enhanced' })

const config = builder.toConfig()
const json = agentConfigToJSON(config)
// Save to file, database, or send over the wire

// JSON → Builder → Agent
const restored = await ReactiveAgents.fromJSON(json)
const agent = await restored.build()
const result = await agent.run('Research quantum computing advances')

Composition API

Build agent pipelines with functional combinators:

import { agentFn, pipe, parallel, race } from 'reactive-agents'

// Create lazy agent functions
const researcher = agentFn({ name: 'researcher', provider: 'anthropic' }, (b) =>
    b.withReasoning().withTools()
)
const summarizer = agentFn({ name: 'summarizer', provider: 'anthropic' })

// Sequential pipeline: research → summarize
const pipeline = pipe(researcher, summarizer)
const result = await pipeline('What are the latest AI breakthroughs?')

// Parallel fan-out: run multiple analyses concurrently
const multiAnalysis = parallel(
    agentFn({ name: 'sentiment', provider: 'anthropic' }),
    agentFn({ name: 'keywords', provider: 'anthropic' }),
    agentFn({ name: 'summary', provider: 'anthropic' })
)
const combined = await multiAnalysis('Article text here...')
// combined.output contains labeled results from all 3 agents

// Race: fastest agent wins
const fastest = race(
    agentFn({ name: 'claude', provider: 'anthropic' }),
    agentFn({ name: 'gpt4', provider: 'openai' })
)
const winner = await fastest('Quick answer needed')

// Clean up
await pipeline.dispose()
await multiAnalysis.dispose()
await fastest.dispose()

Streaming

Tokens arrive as they're generated via AsyncGenerator. Pass an AbortSignal to cancel mid-stream:

const controller = new AbortController()

for await (const event of agent.runStream('Analyze this dataset', {
    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 === 'StreamCancelled') console.log('Stream cancelled')
    if (event._tag === 'StreamCompleted') {
        console.log('\nDone!')
        // event.toolSummary: Array<{ toolName, calls, successRate }>
    }
}

// Cancel from elsewhere (e.g., HTTP request abort)
controller.abort()

Agents are processes

A durable run behaves like an OS process: inspect it live, fork it from a checkpoint, and read a graded evidence receipt on completion.

const handle = agent.runStream(task)          // needs .withReasoning() + .withDurableRuns()
handle.inspect()                              // live: { iteration, stepsCount, lastThought, pendingToolCalls }
handle.pause(); handle.resume()

const result = await agent.run(task)
result.receipt                                // { verdict: "tool-grounded", toolsUsed: ["calculator"], … }
// graded evidence about HOW the answer was produced — not a truth certificate
// optional Ed25519 signing via .withReceiptSigning() certifies provenance

await agent.fork(runId, { at: 1 })            // counterfactual restart from iteration 1's checkpoint —
                                              // live LLM calls after the fork point, never "time-travel"

From the terminal: rax ps lists durable runs, rax attach <runId> tails one. Recorded runs re-execute with zero tokens via exact replay (makeReplayLLMLayer — unchanged prompts only; drift misses loudly). → The Process Model docs · demo

Lifecycle Hooks

Intercept any of the 12 execution phases with before, after, or error hooks:

import { Effect } from 'effect'
import { ReactiveAgents } from 'reactive-agents'

const agent = await ReactiveAgents.create()
    .withProvider('anthropic')
    .withReasoning()
    .withTools()
    .withHook({
        phase: 'think',
        timing: 'after',
        handler: (ctx) => {
            console.log(
                `Step ${ctx.metadata.stepsCount}: ${ctx.metadata.strategyUsed}`
            )
            return Effect.succeed(ctx)
        },
    })
    .withHook({
        phase: 'act',
        timing: 'after',
        handler: (ctx) => {
            const last = ctx.toolResults.at(-1) as
                | { toolName?: string }
                | undefined
            if (last?.toolName) console.log(`Tool called: ${last.toolName}`)
            return Effect.succeed(ctx)
        },
    })
    .build()

Available phases (12): bootstrap, guardrail, cost-route, strategy-select, think, act, observe, verify, memory-flush, cost-track, audit, complete. Each supports before, after, and on-error timing.

Comparison

How Reactive Agents compares to other TypeScript agent frameworks on shipped, working features:

Capability Reactive Agents LangChain JS Vercel AI SDK Mastra
Full type safety (Effect-TS) Yes -- Partial Partial
Composable layer architecture 13 layers -- -- --
Reasoning strategies 6 (+ @exp code-action) Multiple Partial 1
Model-adaptive context 4 tiers -- -- --
Local model optimization Yes -- -- --
Execution lifecycle hooks 12 phases Callbacks Middleware --
Multi-agent orchestration A2A + workflows Yes Partial Yes
Token streaming Yes Yes Yes Yes
Production guardrails Yes -- -- --
Cost tracking + budgets Yes -- -- --
Persistent gateway Yes -- -- --
Agent debrief + chat Yes -- -- --
Metrics dashboard Yes LangSmith -- --
Agent-as-data config Yes -- -- --
Functional composition Yes Yes -- --
Dynamic tool registration Yes Yes -- --
Test suite 8,276 tests -- -- --

Reflects our understanding of each framework's first-party, shipped features as of 2026-06. -- means we found no first-party equivalent, not that none exists. Corrections welcome — open a PR.

Use Cases

  • Autonomous engineering agents with tool execution and code generation
  • Research and reporting workflows with verifiable reasoning steps
  • Scheduled background agents using heartbeats, cron jobs, and webhooks
  • Secure enterprise copilots with RBAC, audit trails, and policy controls
  • Hybrid local/cloud AI deployments with adaptive context profiles
  • Multi-agent teams with A2A protocol and dynamic sub-agent delegation

Architecture

ReactiveAgentBuilder
  -> createRuntime()
    -> Core Services     EventBus, AgentService, TaskService
    -> LLM Provider      Anthropic, OpenAI, Gemini, Groq, xAI, Ollama, LiteLLM, Test
    -> Memory            Working, Semantic, Episodic, Procedural
    -> Reasoning         ReAct, Reflexion, Plan-Execute, ToT, Adaptive
    -> Tools             Registry, Sandbox, MCP Client
    -> Guardrails        Injection, PII, Toxicity, Kill Switch, Behavioral Contracts
    -> Verification      Semantic Entropy, Fact Decomposition, NLI
    -> Cost              Complexity Router, Budget Enforcer, Cache
    -> Identity          Certificates, RBAC, Delegation, Audit
    -> Observability     Tracing, Metrics, Structured Logging
    -> Interaction       5 Modes, Checkpoints, Preference Learning
    -> Orchestration     Sequential, Parallel, Pipeline, Map-Reduce
    -> Prompts           Template Engine, Version Control
    -> Gateway           Heartbeats, Crons, Webhooks, Policy Engine
    -> ExecutionEngine   12-phase lifecycle with hooks

Every layer is an Effect Layer -- composable, independently testable, and tree-shakeable.

12-Phase Execution Engine

Every task flows through a deterministic lifecycle. Each phase calls its corresponding service when enabled:

Bootstrap --> Guardrail --> Cost Route --> Strategy Select
                                              |
                                    +--------------------+
                                    | Think -> Act -> Observe | <-- loop
                                    +--------------------+
                                              |
Verify --> Memory Flush --> Cost Track --> Audit --> Complete
Phase Service Called What It Does
Bootstrap MemoryService Load context from semantic/episodic memory
Guardrail GuardrailService Block unsafe input before LLM sees it
Cost Route CostService Select optimal model tier by complexity
Strategy Select ReasoningService Pick reasoning strategy (or direct LLM)
Think/Act/Observe LLMService + ToolService Reasoning loop with real tool execution
Verify VerificationService Fact-check output (entropy, decomposition, NLI)
Memory Flush MemoryService Persist session + episodic memories
Cost Track CostService Record spend against budget
Audit ObservabilityService Log audit trail (tokens, cost, strategy, duration)
Complete -- Build final result with metadata

Every phase supports before, after, and on-error lifecycle hooks. When observability is enabled, every phase emits trace spans and metrics.

Reasoning Strategies

Strategy How It Works Best For
ReAct Think -> Act -> Observe loop Tool use, step-by-step tasks
Reflexion Generate -> Critique -> Improve Quality-critical output
Plan-Execute Plan steps -> Execute -> Reflect -> Refine Structured multi-step work
Tree-of-Thought Branch -> Score -> Prune -> Synthesize Creative, open-ended problems
Adaptive Analyze task -> Auto-select best strategy Mixed workloads
Code-Action @exp LLM generates a TypeScript IIFE run in a Worker sandbox; tools exposed as async functions Multi-tool orchestration, pure computation
// Auto-select the best strategy per task
const agent = await ReactiveAgents.create()
    .withProvider('anthropic')
    .withReasoning({ defaultStrategy: 'adaptive' })
    .build()

// Strategy switching is on by default — customize or disable explicitly
const agent2 = await ReactiveAgents.create()
    .withProvider('anthropic')
    .withReasoning({
        // enableStrategySwitching defaults to true
        maxStrategySwitches: 1,
        fallbackStrategy: 'plan-execute-reflect',
    })
    .build()

Multi-Provider Support

Provider Models Tool Calling Streaming
Anthropic Claude Haiku, Sonnet, Opus Yes Yes
OpenAI GPT-4o, GPT-4o-mini Yes Yes
Google Gemini Gemini Flash, Pro Yes Yes
Groq Llama, Qwen, and more (hosted) Yes Yes
xAI Grok models Yes Yes
Ollama Any local model Yes Yes
LiteLLM 40+ models via LiteLLM proxy Yes Yes
Test Mock (deterministic) -- --

Switch providers with one line -- agent code stays the same.

Model-Adaptive Context

Optimize prompt construction and context compaction for your model tier:

const agent = await ReactiveAgents.create()
    .withProvider('ollama')
    .withModel('qwen3:4b')
    .withReasoning()
    .withTools()
    .withContextProfile({ tier: 'local' }) // Lean prompts, aggressive compaction
    .build()
Tier Models Context Strategy
"local" Ollama small models (<=14b) Lean prompts, aggressive compaction after 6 steps, 800-char truncation
"mid" Mid-range models Balanced prompts, moderate compaction
"large" Anthropic, OpenAI, Gemini Full context, standard compaction
"frontier" Flagship models Maximum context, minimal compaction

Context Window Override (numCtx)

Pin the exact context window the provider is given, instead of relying on the model's assumed maximum. Pass it via the .withModel() object form:

const agent = await ReactiveAgents.create()
    .withProvider('ollama')
    .withModel({ model: 'qwen3:4b', numCtx: 32768 }) // exact num_ctx sent to Ollama
    .withReasoning()
    .build()

numCtx is also a first-class AgentConfig field, so it round-trips through toConfig() / fromJSON() and the Cortex Studio agent builder:

{ "provider": "ollama", "model": "qwen3:4b", "numCtx": 32768 }

Provider applicability: honored by providers that expose a context-window knob (Ollama maps it to num_ctx). Cloud providers that don't expose one ignore the field. When set, it becomes the authoritative denominator for the context-usage gauge in Cortex Studio.

Packages

Package Description
@reactive-agents/core EventBus pub/sub, AgentService lifecycle, TaskService state machine, canonical types
@reactive-agents/runtime 12-phase ExecutionEngine, ReactiveAgentBuilder, createRuntime() layer composer
@reactive-agents/llm-provider Unified LLM interface for Anthropic, OpenAI, Gemini, Groq, xAI, Ollama, LiteLLM, and Test providers
@reactive-agents/memory 4-layer memory (working, semantic, episodic, procedural) on bun:sqlite; ExperienceStore cross-agent learning; background consolidation + decay
@reactive-agents/reasoning 7 strategies (ReAct, Blueprint, Reflexion, Plan-Execute, ToT, Adaptive, Code-Action @experimental) with composable kernel architecture
@reactive-agents/tools Tool registry with sandboxed execution, MCP client, agent-as-tool adapter, dynamic sub-agent spawning
@reactive-agents/guardrails Pre-LLM safety: injection detection, PII filtering, toxicity blocking
@reactive-agents/verification Post-LLM quality: semantic entropy, fact decomposition, NLI hallucination detection
@reactive-agents/cost Multi-factor complexity routing, per-execution budget enforcement, semantic cache
@reactive-agents/identity Ed25519 agent certificates, RBAC policies, delegation chains, audit logging