What's New
Last updated 1 day ago · 6379e94
Updated yesterday
"docs: sync all documentation to v0.14.0" · 6379e94 · 2026-07-21
- ## v0.14.0 — The Log & The Process (July 2026)
- ### The trust receipt — `result.receipt`
- ### The process model — inspect, fork, attach
- ### Enforcement caught up to the docs
- ### Reliability under provider turbulence
- ### APIs that now do what they say
A quick-scan guide to what has landed in each major release. Start here when returning after time away — each bullet links to the relevant documentation.
v0.14.0 — The Log & The Process (July 2026)
Section titled “v0.14.0 — The Log & The Process (July 2026)”The Arc 1 theme: runs are inspectable processes, and every run leaves a signed record.
The trust receipt — result.receipt
Section titled “The trust receipt — result.receipt”Every run now returns a receipt: a claim→evidence record with a verdict, confidence, the verification method, the declared deliverables[], and an Ed25519 signature over the provenance. It is a provenance record, not a truth certificate — it tells you what the run claimed, what evidence backs each claim, and whether the harness’s own checks passed, so downstream code can gate on trust instead of parsing prose.
const result = await agent.run("Summarize the Q3 report and cite figures.");result.receipt?.verdict; // "verified" | "partial" | "abstained" | ...result.receipt?.deliverables; // typed contract deliverables + their evidenceresult.abstained; // honest decline — now correct on every strategyThe process model — inspect, fork, attach
Section titled “The process model — inspect, fork, attach”A streamed run is a live handle. runStream() returns pause / resume / stop / terminate / status and inspect() for live kernel-state introspection (current iteration, steps, messages, pending tool calls, last thought).
const run = agent.runStream("Research and draft the memo.");const state = run.inspect(); // { iteration, steps, pendingToolCalls, ... }run.pause(); /* ... */ run.resume();Durable runs can be forked from any checkpoint for counterfactual restarts, and driven from the terminal:
const alt = await agent.fork(runId, { at: 4, model: "claude-sonnet-5" }); // requires .withDurableRuns()rax ps # list durable runsrax attach <runId> # tail a live runrax diagnose replay # re-execute a recorded run with zero tokens (exact replay)Enforcement caught up to the docs
Section titled “Enforcement caught up to the docs”The audit’s central finding was a façade — surfaces that looked wired but weren’t. v0.14 closes them:
- Tool policy is enforced, not suggested.
allowedTools/forbiddenToolsand the.withContract()deny-list are now enforced at the shared tool-execution choke point on every strategy — including planned steps (plan-execute, blueprint), hallucinated tool names, andcode-action’s sandbox, where generated code previously called tools with no policy check at all. A blocked call is recorded and never runs. - Honest abstention everywhere.
terminatedByand the abstention descriptor now cross the boundary on all eight strategies (was reactive-only), soresult.abstainedand the receipt are truthful regardless of which strategy ran. - Sub-agents are part of the run. Spawned sub-agents (
.withAgentTool()/ thespawn-agenttool) now fork into the parent’s fiber tree:agent.terminate()interrupts in-flight children (no orphaned workers), a failed child returns a truthfulsuccess: false, child events reach the parent’s EventBus taggedparentAgentId, traces correlate viarootRunId+ depth, and the recursion cap is live (sub-delegation only below an explicitmaxRecursionDepth). - The requirement lifecycle is real. Ledger
requiremententries are minted when the contract compiles and transition at the verification gate, so run assessment sees declared / satisfied / blocked requirements — per entity, so touchingorders.jsonno longer satisfies a requirement aboutrates.json. - Phase stream events fire.
PhaseStarted/PhaseCompletedchunks (stream density"full") are now actually emitted; they were advertised with zero writers before.
Reliability under provider turbulence
Section titled “Reliability under provider turbulence”- Transient provider failures retry. 5xx,
529overload (Anthropic/Groq), and network faults (ECONNRESET, socket hang-up,fetch failed) are now classified as retryable and go through the exponential-backoff schedule; only429retried before. Permanent4xxstill fail fast. - A critique/reflect blip no longer discards the run. If the self-critique pass (reflexion, plan-execute reflect) hits an LLM error, the run degrades gracefully — it keeps the answer it already produced and records an honest
[CRITIQUE skipped]marker — instead of throwing away completed work.
APIs that now do what they say
Section titled “APIs that now do what they say”.withVerificationStep()shapes the answer: aREVISEverdict re-runs once with the feedback (it previously burned a call and wrote to a field nothing read)..withCalibration("skip")is honored (it was silently rewritten to"auto"under reasoning).- Model calibration composes with the tier adapter instead of replacing it — calibrating a model can refine behavior but can never remove a capability (it used to drop four live adapter hooks).
- The meta-tool suite is opt-in. The default toolbox is task-facing; the planning/reflection meta-tools (and their web-egress default) load only when you ask for them.
Migrating to v0.14
Section titled “Migrating to v0.14”This release removes builder methods and options that had no reader, and unpublishes two packages that only a no-op reached. Migrate:
| Removed | Replacement |
|---|---|
.withTerminalTools(cfg?) | .withTools({ terminal: cfg ?? true }) |
.withTelemetry(cfg?) | .withObservability({ telemetry: cfg ?? true }) |
.withoutTracing() | .withObservability({ tracing: false }) |
.withProgressCheckpoint() | .withDurableRuns() |
.withCacheTimeout(ms) | removed — was a no-op |
.withIdentity() / .withInteraction() / .withOrchestration() | use @reactive-agents/identity / /interaction directly; orchestration has no replacement |
.withFallbacks({ models, errorThreshold }) | .withFallbacks({ providers }) — ordered provider cascade |
.withReactiveIntelligence({ autonomy, constraints }) | options removed (were no-op safety switches) |
bare .withSkills() / packages / overrides keys | .withSkills({ paths: [...] }) (throws otherwise) |
@reactive-agents/orchestration, @reactive-agents/scenarios | unpublished |
task-complete tool | final-answer (the sole terminator) |
rag-search tool | the unified find tool (.withDocuments() still ingests) |
The provider adapter contract is now 4 hooks (continuationHint, errorRecovery, synthesisPrompt, qualityCheck) plus parseToolCalls; the three that never fired (taskFraming, toolGuidance, systemPromptPatch) are removed. The full list is in the CHANGELOG.
v0.13.5 — Groq, xAI & the Agentic UI Kit (July 2026)
Section titled “v0.13.5 — Groq, xAI & the Agentic UI Kit (July 2026)”Two new providers, a headless UI-controller package that unifies the React, Svelte, and Vue bindings, a durable request-for-input rail in Cortex, and honest error surfacing.
Groq and xAI providers
Section titled “Groq and xAI providers”Both wire through a shared makeOpenAICompatProvider factory, so they inherit the full OpenAI-compatible stack — streaming, native function calling, structured output — with no bespoke adapter.
ReactiveAgents.create().withProvider("groq").withModel("llama-3.3-70b-versatile").build();ReactiveAgents.create().withProvider("xai").withModel("grok-4").build();Both are live-verified end to end (plain completion + native tool-call round-trips). Logprobs and embeddings are capability-gated (neither provider exposes them); structured output on Groq is model-dependent (json_schema strict on gpt-oss and some models, json_object elsewhere), with the parse-retry loop covering the gap. The selectable-provider count is now 8. See LLM Providers.
Agentic UI Kit — @reactive-agents/ui-core
Section titled “Agentic UI Kit — @reactive-agents/ui-core”A new framework-agnostic headless package holds the shared controllers behind every UI binding: a progressive UI-tree reconciler, a task-inbox fetch controller, and interaction + approval POST controllers. React, Svelte, and Vue now delegate to these instead of each re-implementing the wire protocol.
- React — rewired onto
ui-corewith a coreuseRunhook and the full v1 family surface: Interact (AgentPrompt/ChoiceCard), Inbox (useTaskInbox/TaskInbox), Observe (useRunCost/useRunSteps,CostMeter/StepTimeline), Render (AgentSurfaceregistry + UI-tree schema), plususeResumableRunand anAgentDevtoolsoverlay withtesting/stylessubpaths. - Svelte and Vue — rewired onto the same controllers (
createRun,createInteractions,createResumableRun, run cost/steps), withrequestInit/header pass-through restored on structured streams.
Cortex request_user_input rail
Section titled “Cortex request_user_input rail”Cortex gains a durable request-for-input rail — runner methods plus a .withUserInteraction(...) surface, an interaction-watcher, and a real pause → register → respond → resume flow. The Cortex UI renders a live Interact panel and streaming structured previews.
Honest run errors
Section titled “Honest run errors”Reasoning failures now propagate the real error string to result.error end to end. Previously the kernel captured the message in state.error, but normalizeReasoningResult dropped it during its whitelist rebuild, so callers only saw a generic "Reasoning failed". A bad model id now surfaces "…404 The model … does not exist" on result.error.
v0.13.0 — Receipts & first-touch (July 2026)
Section titled “v0.13.0 — Receipts & first-touch (July 2026)”The v0.13 line is about receipts and first-touch: native reasoning on every provider, cost-aware routing, an overhauled first-ten-minutes developer experience, honest abstention as a first-class terminal, a new efficiency-first Blueprint strategy, two token-waste guards, and a broad correctness sweep across providers and the kernel.
Native thinking on every provider
Section titled “Native thinking on every provider”.withThinking(...) turns on native reasoning across Anthropic, OpenAI, Gemini, and local models from one builder switch — pass true or { effort, budgetTokens }. It is off by default everywhere: undefined never auto-enables (this also flips Gemini’s former thinks-by-default behavior off). Budgets are bounded and reserved on top of the answer budget, so hidden reasoning can never starve the visible answer.
ReactiveAgents.create() .withProvider("anthropic").withModel("claude-sonnet-4-6") .withThinking({ effort: "medium" }) .build();See Builder API.
Cost-aware model routing
Section titled “Cost-aware model routing”.withModelRouting() (opt-in, off by default) routes each run to the cheapest capable model of your configured provider, picked by task complexity — on both the inline and reasoning paths. It stays within the provider’s tiers (a cheap → mid → expensive ladder mapped to that provider’s models, so it’s provider-agnostic), is capability-gated (never drops below a model whose context window fits the prompt), and is advisory (degrades to your configured model on any error — it can only make a run cheaper, never break it). See Cost-Aware Model Routing.
ReactiveAgents.create() .withProvider("anthropic").withModel("claude-sonnet-4-6") .withModelRouting() // simple tasks drop to the haiku tier .build();First-touch developer experience
Section titled “First-touch developer experience”The first ten minutes are re-paved:
- Typed tool authoring —
defineTool({ name, description, input, handler })takes a Standard Schema input (Zod, Effect, Valibot) and gives the plain-async handler inferred argument types — noRecord<string, unknown>oras nevercasts. It also validates its own options and rejects wrong field names (e.g.parameters/execute) with a message naming the correct field instead of crashing. See Tools. ReactiveAgents.quick()— a two-line agent that resolves provider, model, and iteration defaults from the environment:const agent = await ReactiveAgents.quick(); await agent.run("…"). See Quickstart.- Fail-fast
build()—.withStrictValidation()catches a missing API key or unknown model at build time with a typed error and fix instructions, instead of a raw 401/404 on the first call. - Per-LLM-call timeout —
.withLlmTimeout(ms)configures the local/Ollama per-call timeout (previously hardcoded at 120s); timeout errors name the model, elapsed time, and a cold-load/GPU-contention hint, and the in-flight local request is aborted server-side. See Local Models.
Honest abstention — a run that cannot succeed says so
Section titled “Honest abstention — a run that cannot succeed says so”When a task is structurally impossible (a required tool is unavailable, or synthesis is repeatedly ungrounded), the run terminates with terminatedBy: "abstained" and a typed result.abstention { reason, missing } instead of fabricating an answer. This is harness-forced, not model-initiated. See Structured Output.
Blueprint strategy — plan once, execute in parallel
Section titled “Blueprint strategy — plan once, execute in parallel”For static, decomposable tasks the whole plan is knowable up front. Blueprint (the 7th reasoning strategy) generates a plan, verifies it, executes independent steps in parallel with no per-step LLM call, then solves. Adaptive routing sends static-decomposable tasks to Blueprint automatically. See Choosing Strategies.
Two token-waste guards
Section titled “Two token-waste guards”.withStallPolicy(...)— when the model ignores required-tool nudges and makes no progress across consecutive iterations, the harness escalates and delivers accumulated artifacts (or fails) instead of looping to the full nudge cap — bounding wasted tokens on stuck runs while leaving progressing runs untouched..withFabricationGuard(mode)— an always-on verifier check (default"block") that rejects empirical performance numbers (benchmark timings, %-speedups) absent from the tool-observation corpus. High-precision — only perf measurements are policed. Soften to"warn"/"off"or via theRA_FABRICATION_GUARDenv var.
See Builder API.
Evaluation gate CLI
Section titled “Evaluation gate CLI”rax eval gate runs the project lift rule over a benchmark report (default-on | opt-in | reject); --ledger appends a weakness→hypothesis→verdict chain and rax eval ledger reads it. Benchmark runs capture a per-run RunDiagnosis (honesty label, failure modes) when a trace dir is set. See Eval.
Correctness sweep
Section titled “Correctness sweep”Highlights from a broad provider + kernel fix pass:
- gpt-5.x non-thinking calls work — the OpenAI adapter now picks the token-limit field by capability (
max_completion_tokensfor gpt-5.x/o-series,max_tokensfor the gpt-4o family), fixing a 400 on default gpt-5.x calls. - Thinking request shapes verified live — Anthropic uses the adaptive shape on current-generation models and legacy
budget_tokenson older ones;temperatureis dropped when thinking is on (both Anthropic and OpenAI reject it otherwise). withRetryPolicyretries the real path — it previously wrapped onlycomplete(); the reactive kernel runs throughstream()/completeStructured(), so transient failures were never retried. All three call sites are now retried.withMinIterations(N)enforces the full floor — previously a loneifforced a single extra pass regardless ofN; it now loops to the configured minimum.- Cross-provider tool-call arguments are never dropped — string-encoded JSON args (some Ollama models) are now coerced instead of silently reset to
{}. - Readable provider errors — a model typo produces one clean error line with a suggestion instead of duplicated raw JSON and an internal stack.
- Configured-off phases stay off —
runGuardedPhasenow honorsphase.skip, so disabled phases don’t run via direct callers. - Context & structured-output correctness — string-safe JSON repair, mid-thread user instructions kept over budget, boundary-matched + nested field provenance, duplicate-tool-name warnings, and a gated (O(N²)-removed) streaming reparse.
The withVerificationStep({ mode: "loop" }) option (documented but unimplemented) was removed; "reflect" is the only supported mode.
See the full 0.13.0 changelog for the complete list.
v0.12.0 — Durable & Honest (June 2026)
Section titled “v0.12.0 — Durable & Honest (June 2026)”The v0.12 line makes runs survive crashes, makes outputs typed and grounded, and makes “which capabilities are on” explicit and honest. Headline capabilities: typed structured output, durable execution, and HarnessProfile composition — plus a developer-experience pass that removes Effect from the common builder surface.
Typed Structured Output
Section titled “Typed Structured Output”Turn any agent into a typed extractor. Attach a schema at build time and read a fully-typed value off the result — no prompt engineering, no manual JSON parsing.
import { z } from "zod";
const Invoice = z.object({ total: z.number(), currency: z.string() });
const agent = await ReactiveAgents.create() .withModel({ provider: "anthropic", model: "claude-sonnet-4-6" }) .withOutputSchema(Invoice) // builder-only .build();
const result = await agent.run("Extract the invoice: total $4,200 USD");result.object; // { total: 4200, currency: "USD" } — typed as { total: number; currency: string }result.objectError; // populated instead (lenient) if the model's output didn't validate- Any Standard Schema — Zod, Valibot, ArkType, and Effect Schema all work through one adapter; JSON Schema is derived per-vendor so the model is never blind to the shape.
- Streaming —
agent.streamObject(task)yields{ object: DeepPartial<T> }as fields fill in. - Grounded mode —
.withOutputSchema(schema, { mode: "grounded" })runs extraction inside the loop with provenance, confidence, and abstention instead of guessing. - Top-level arrays, lenient-degrade — array schemas and partial outputs are handled gracefully; parse failures surface on
result.objectErrorrather than throwing (configurable via{ onParseFail: "throw" }).
Verified live across Anthropic, OpenAI, Gemini, and local Ollama (qwen3.5, gemma4). See Typed Structured Output.
Durable Execution — crash-resume
Section titled “Durable Execution — crash-resume”Opt a run into a durable store and resume it from its last checkpoint after a crash, restart, or graceful pause.
const agent = await ReactiveAgents.create() .withModel({ provider: "anthropic", model: "claude-sonnet-4-6" }) .withDurableRuns() .build();
const runs = await agent.listRuns({ status: "running" }); // discover interrupted runsconst result = await agent.resumeRun(runs[0].runId); // continue from last checkpointRun state is persisted on a content-addressed config hash (system prompt + provider), so a resumed run reattaches to the correct configuration. Verified cross-process with a hard-kill end-to-end test. See Durable Execution.
Durable human-in-the-loop — approval gates that survive process death
Section titled “Durable human-in-the-loop — approval gates that survive process death”Name the tool calls that require sign-off. A gated call pauses the run — on
both run() and runStream() — persists awaiting-approval plus the pending
action, and returns pendingApproval so the process can exit. A human approves or
denies from any process; the run resumes from its checkpoint to completion.
const agent = await ReactiveAgents.create() .withModel({ provider: "anthropic", model: "claude-sonnet-4-6" }) .withDurableRuns() .withApprovalPolicy({ tools: ["shell-execution", "file-write"], mode: "detach" }) .build();
// 1. A gated call pauses and returns status: "awaiting-approval".const result = await agent.run("clean up the temp files");if (result.status === "awaiting-approval") { console.log("awaiting approval:", result.pendingApproval.toolName);}
// 2. Later, from ANY process — decide on whatever is waiting:for (const p of await agent.listPendingApprovals()) { await agent.approveRun(p.runId); // resume + execute the call // or: await agent.denyRun(p.runId, "not allowed"); // resume, skip the call}Need same-process convenience? Pass onApproval and one run() call drives the
whole pause → decide → resume loop:
const result = await agent.run("clean up the temp files", { onApproval: ({ toolName, args }) => toolName !== "shell-execution",});Built on the same durable RunStore as crash-resume — the decision and the paused checkpoint live in SQLite, so approve/deny works across process and machine boundaries. See Durable Human-in-the-Loop.
Developer experience — Effect-free where it counts
Section titled “Developer experience — Effect-free where it counts”- Plain-function hooks —
.withHook()handlers now accept ordinary sync/async functions; the Effect form still works. NoEffect.genrequired to tap the lifecycle. See Lifecycle Hooks. - Faster
run()— the post-answer debrief LLM call was moved off the critical path (forked, non-blocking), cutting end-to-endrun()latency ~46%. Rich debrief is awaited lazily viaresult.debriefRich().
Opt-in evidence grounding
Section titled “Opt-in evidence grounding”.withGrounding({ mode }) makes numeric grounding explicit (default off), eliminating false “failed at evidence-grounded” warnings on correct figures. Blocking mode does a bounded retry then degrades — it never hard-fails a correct answer. See Verification.
HarnessProfile presets — one-line capability composition
Section titled “HarnessProfile presets — one-line capability composition”HarnessProfile replaces the leaky .withLeanHarness() with three named, explicit presets applied via .withProfile():
import { ReactiveAgents, HarnessProfile } from 'reactive-agents'
const agent = await ReactiveAgents.create() .withProvider('anthropic') .withProfile(HarnessProfile.balanced()) // canonical entry .build()| Preset | Composes |
|---|---|
HarnessProfile.lean() | Disables everything: memory plus the three registry-default capabilities (reactive intelligence, verifier, strategy switching) + skill persistence. The model is the entire harness — for latency/cost-sensitive paths and benchmark ablations. Fixes the historical .withLeanHarness() leak that left reactive intelligence on. |
HarnessProfile.balanced() | The full production stack: reactive intelligence + verifier + strategy switching (registry defaults) plus memory, enabled explicitly (memory is off in a bare builder as of v0.12). |
HarnessProfile.intelligent() | Balanced + skill persistence for cross-session compounding learning. |
Presets compose with individual builder methods — later calls win, so .withProfile(HarnessProfile.balanced()).withoutMemory() drops memory back off. See Choosing a Stack and Builder API.
New builder methods
Section titled “New builder methods”.withBudget({ tokenLimit?, costLimit? })— hard cumulative token/cost ceiling enforced inside the loop (a killswitch, distinct from.withCostTracking()accounting). See Builder API..withContract(taskContract)— declare aTaskContract: required + forbidden tools, fixtures, a minimum model floor, and a success oracle. Required tools become an execute-time gate; forbidden tools are excluded from the tool schema. Enforced atbuild()..withLearning({ tier?, dbPath? })— enable the cross-run learning store (experience + skill learning)..withSkillPersistence(enabled?)— persist learnedSkillRecords across process restarts (also enabled byHarnessProfile.intelligent()).
Capability-source honesty gate
Section titled “Capability-source honesty gate”When an agent builds for a (provider, model) whose capability profile resolves to a silent fallback source (no probe, cache, or static-table entry → an assumed 2048-token context), build() now surfaces it: a loud warning by default, or a hard error under .withStrictValidation(). This catches the misconfigured-context class of failures at build time for every user instead of silently running on a wrong budget. See Troubleshooting.
Behavior changes
Section titled “Behavior changes”- Memory is now OFF by default (reversing the v0.11 GH #122 default-on). A bare
.create()….build()is stateless — no surprise~/.reactive-agents/<agentId>/SQLite writes, predictable in CI. Opt in with one line:.withMemory(),.withLearning(), orHarnessProfile.balanced()/.intelligent()(all enable it explicitly). Migration: add.withMemory()to any v0.11 agent that relied on implicit cross-session memory. .withLeanHarness()is superseded byHarnessProfile.lean(), which additionally disables reactive intelligence (the old method did not). Existing chains keep working.
No breaking API removals — existing ReactiveAgents.create().with*() chains continue to compile and run; only the memory default changed (see migration note above).
v0.11.x — Production tooling + full observability (May 2026)
Section titled “v0.11.x — Production tooling + full observability (May 2026)”The focus: developer tooling that makes agents production-observable and repeatable, plus the first create-reactive-agent scaffolder, cross-runtime support, and three new capabilities (code-action strategy, skill persistence, interactive playground).
New packages
Section titled “New packages”@reactive-agents/observe— Zero-config OpenTelemetry tracing. SetOTEL_EXPORTER_OTLP_ENDPOINTand every run emits a workflow → LLM → tool span hierarchy, OpenInference-compliant, to any OTLP backend (Jaeger, Grafana Tempo, Langfuse, Arize Phoenix). See OpenTelemetry Tracing.@reactive-agents/replay— Deterministic trace replay. Record any run to a snapshot file and re-run it with a different model or prompt without calling the LLM again. Enables regression testing and prompt A/B comparisons. See Snapshot & Replay.@reactive-agents/runtime-shim— Cross-runtime support. The framework now runs on Node.js 22.5+ in addition to Bun. Provides unifiedDatabase,spawn,serve,glob,writeFile,readFile, andhashprimitives that delegate to the available runtime. FTS5 is optional — falls back to LIKE-based search on Node’s built-in SQLite. Unblocks Stackblitz WebContainers (Node-only) and Vercel/Netlify deployments.
New tooling
Section titled “New tooling”create-reactive-agentCLI —bunx create-reactive-agent my-appscaffolds a runnable agent project in seconds. Supports--template minimal|standard|tool-use|multi-agent|gateway,--provider,--model,--pm bun|npm|yarn|pnpm. See create-reactive-agent.
Interactive Playground
Section titled “Interactive Playground”Three live Stackblitz scenarios, zero install. Runs fully in-browser via WebContainers — no local runtime required. Default provider is Google Gemini (free tier).
| Scenario | What it shows |
|---|---|
| Hello Agent | Simple Q&A — minimal builder, one-step response |
| Tool Integration | Built-in code-execute + scratchpad tools working together |
| Strategy Demo | reactive vs plan-execute-reflect side-by-side on the same task |
See Playground.
code-action strategy (@experimental)
Section titled “code-action strategy (@experimental)”A 7th reasoning strategy in which the LLM generates a TypeScript IIFE that runs inside a Worker-thread sandbox. Tools are exposed as normal async functions and called via postMessage round-trips — no JSON schema juggling in the prompt. Best suited for multi-tool orchestration tasks where expressing control flow in code is cleaner than iterative tool calls.
Enable with defaultStrategy: "code-action". ToolService is optional; the strategy also handles pure computation tasks. See code-action.
Skill persistence
Section titled “Skill persistence”Learned SkillRecord objects now survive process restarts. The skill system uses a dual-store: the existing in-memory session store for fast within-run access, plus a new SQLite-backed SkillStore that persists across runs. On cold start, skills are resolved from the persistent store before any LLM call. skillFragmentToSkillRecord() is exported from reactive-agents for manual skill construction.
New runtime controls
Section titled “New runtime controls”-
RunHandle—runStream()now returns aRunHandlewith four controls and a status property:.pause()— suspends the loop at the next safe checkpoint.resume()— resumes a paused run.stop()— graceful shutdown: finishes the current step, then runs output synthesis.terminate()— immediate abort, skips synthesis.status—"running" | "paused" | "stopped" | "terminated" | "completed".result—Promisethat resolves when the run reaches a terminal state
See Compose API.
-
Killswitches — Six factory functions from
@reactive-agents/composethat wire stopping conditions into the agent loop. Pass them to.compose()or.withHarness():import { maxIterations, budgetLimit, timeoutAfter, watchdog, requireApprovalFor } from "@reactive-agents/compose";Factory Stops when… maxIterations(n)Loop count reaches nbudgetLimit({ maxTokens?, maxCostUSD? })Token or cost ceiling hit timeoutAfter(duration)Wall-clock duration exceeded watchdog({ timeout })No progress within timeoutrequireApprovalFor(toolName, approver)Named tool needs human approval See Compose API.
-
Compose API (
@stable) —.compose(fn)(alias:.withHarness(fn)) attaches a harness transform that intercepts tagged chokepoints (prompt.system,nudge.loop-detected,message.tool-result, etc.) viah.on(),h.tap(),h.before(),h.after(), andh.onError(). Existing builder methods.withSystemPrompt(),.withErrorHandler(), and.withHook()now desugar through the harness. See Compose API and Harness Tags.
Strategy switching on by default
Section titled “Strategy switching on by default”enableStrategySwitching now defaults to true. The reactive intelligence dispatcher will switch strategies automatically when entropy signals a stuck loop — no explicit opt-in required.
Decision tracing
Section titled “Decision tracing”Agents can capture the model’s stated why for every tool call. Tool-call rationale on the reactive/adaptive paths is opt-in (audit feature, not performance — pure token/latency cost):
auditRationaleopt-in —.withReasoning({ auditRationale: true })(or envRA_RATIONALE_AUDIT=1). When on, the kernel coaxes one<rationale call="N">{"why":"…","confidence":0-1}</rationale>block per tool call. Off by default.- Native function-calling capture —
parseRationaleBlocks()reads side-channel blocks fromthought+thinkingcontent and attaches each rationale to the matchingToolCallSpecby position. The parser tolerates fenced/prose-wrapped JSON, over-lengthwhy, and repeatedcall="N"attributes, so capture is reliable on small local models. - plan-execute-reflect enforcement (always on) —
LLMPlanStepSchemacarries arationale: { why, confidence? }field, MANDATORY for everytool_callstep (independent ofauditRationale). Failures after retry emit aplan_rationale_missingmetric — no synthetic fallback invented. AgentDebrief.rationale[]— Unified milestone-decision log: tool selections, curator decisions, strategy switches, reactive interventions, and terminations. All render indebrief.markdownunder## Decision Rationale.
See Decision Tracing for the full pipeline and Debrief & Chat for the result shape.
Context-window override (numCtx)
Section titled “Context-window override (numCtx)”Pin the exact context window the provider receives instead of relying on the model’s assumed maximum:
.withModel({ model, numCtx })—numCtxmaps to Ollama’snum_ctx; cloud providers without a context-window knob ignore it. Now a first-classAgentConfigfield, so it round-trips throughtoConfig()/fromJSON()and the config-driven path. See Builder API and Local Models.- Cortex Studio — exposed as a Context length (
numCtx) field in the Lab Builder’s Inference section, and used as the authoritative denominator for the context-usage gauge.
Cortex rich-trace debugger
Section titled “Cortex rich-trace debugger”The Cortex Run View’s Trace Panel adds a Timeline view: a fine-grained, filterable, chronological event stream (LLM exchanges with prompt-cache %, tool calls, strategy switches, verifier verdicts, guards) grouped by iteration, reusing the same TraceEvent model as rax diagnose. The classic per-iteration Frames view remains a click away. See Cortex.
v0.10.x — Local models run the full loop (May 2026)
Section titled “v0.10.x — Local models run the full loop (May 2026)”The biggest release since v0.9 — 0.10.0 through 0.10.6, shipped over four weeks. The headline: local Ollama models now run the same tool-calling agent loop as paid frontier APIs, thanks to a closed-loop healing pipeline and adaptive tool-calling. Read the full v0.10.0 changelog for engineering detail.
What you gain
Section titled “What you gain”Local models that actually work
Section titled “Local models that actually work”- Healing Pipeline — 4-stage closed-loop recovery on every tool call (tool-name fuzzy match → parameter-name aliasing → path resolution → type coercion). Deterministic repairs instead of an LLM reprompt. Ships on by default — see LLM Providers and Resilience.
- Adaptive tool calling — Each model gets fingerprinted on first run; native FC capable models route through the JSON path, weaker ones through a 3-tier text-parse cascade (XML → JSON → pseudo-code). The framework learns each model’s dialect after 5 runs and stops asking it to do things it can’t.
- Calibration system — Per-model observations (parallel-call capability, classifier reliability, tool-call dialect) adapt empirically. Auto-enabled when
.withReasoning()is on. - Cross-tier verification — the same agent loop exercised across frontier models (
claude-sonnet-4-6,claude-haiku-4-5,gpt-4o-mini,gemini-2.5-pro) and local models (gemma4:e4bat 4 GB,cogito:14bat 9 GB) during development.
Long agent runs stay cheap
Section titled “Long agent runs stay cheap”- Three-stage context curation — Tool results get compressed and stashed → curator renders only what’s needed → optional reactive trim. Long runs stay inside the context window with negligible per-step overhead. See Intelligent Context Synthesis.
- Reactive Intelligence dispatcher — 6 corrective interventions fire automatically when an agent shows entropy signs (early-stop, temperature adjust, strategy switch, context compress, tool inject, skill activate). Suppression gates prevent runaway dispatch. See Reactive Intelligence.
Production safety hardened
Section titled “Production safety hardened”@reactive-agents/diagnose— Standalone npm package detects system-prompt, API-key, credential, and internal-instruction leaks in any output. Deterministic regex-based detection with false-positive filters — no extra LLM call.- Single-owner termination — All 12 phases route stop decisions through one arbitrator. CI lint guard prevents future bypass paths. Agents always finish cleanly, never get stuck.
Better runtime + tooling
Section titled “Better runtime + tooling”@reactive-agents/cortex— Cortex Studio is now installable from npm:bunx @reactive-agents/cortexorrax cortexlaunches the live agent canvas, debrief UI, and visual builder. See Cortex.- Gateway chat mode — Per-sender SQLite session history, episodic context injection, daily compaction. Set
channels.mode: 'chat'for conversational webhooks; keep'task'for one-shot triggers. See Gateway and Messaging Channels. - Composable kernel architecture — Internal
kernel/reorganized by capability (act/·attend/·comprehend/·decide/·reason/·reflect/·sense/·verify/+loop/+state/). Doesn’t change the public API; makes contributing to the framework easier. See Composable Kernel. - 8,294 tests across 1061 files — verified by
bun teston every PR.
Patch releases
Section titled “Patch releases”| Version | Highlights |
|---|---|
0.10.0 | Phase 1 release — healing pipeline, calibration, diagnose, cortex npm |
0.10.1–0.10.2 | Documentation polish, version drift fixes across 28 packages |
0.10.3 | Coordinated package alignment, npm publish drift CI guard |
0.10.4 | Coordinated changeset release (single source of truth) |
0.10.5–0.10.6 | Static-asset serving in Cortex server, README + cookbook freshness |
Breaking changes
Section titled “Breaking changes”None. All existing ReactiveAgents.create().with*() builder chains keep working unchanged. New calibration fields are forward-compatible — existing ~/.reactive-agents/observations/ files decode cleanly.
v0.9.x — MCP Production Hardening + Pre-v0.10 Polish
Section titled “v0.9.x — MCP Production Hardening + Pre-v0.10 Polish”- MCP client rewritten on
@modelcontextprotocol/sdk— smart auto-detection between stdio and HTTP-only containers, two-phase docker lifecycle — see Tools - Composable kernel architecture (initial) —
react-kernel.tsreduced from ~1,700 to ~197 lines viamakeKernel({ phases })factory — see Composable Kernel - Permanently-failed required tools fix — tools that always error no longer cause loop-until-maxIterations — see Harness Control Flow
- Cortex MCP CRUD + JSON import — import Cursor/Claude-style MCP configs directly into Cortex — see Cortex
- StatusRenderer TUI — live terminal display with collapsible think panel (
tkey toggles),mode: 'stream' | 'status' - 3 new terminal tools —
git-cli,gh-cli, andgws-cliare now built-in - Web-search provider Serper.dev — third web-search backend alongside Tavily
crypto-pricebuilt-in tool — CoinGecko price lookup, no API key required- Observability on by default — minimal verbosity is now enabled out of the box
- Sub-agent
maxIterationsfully honored — the silent cap of 3 has been removed
v0.9.0 — MCP Production Hardening
Section titled “v0.9.0 — MCP Production Hardening”- MCP client rewritten on
@modelcontextprotocol/sdk— smart auto-detection between stdio and HTTP-only containers, two-phase docker lifecycle — see Tools - Composable kernel architecture —
react-kernel.tsreduced from ~1,700 to ~197 lines viamakeKernel({ phases })factory; phases are now individually swappable — see Composable Kernel - Permanently-failed required tools fix — tools that always error no longer cause loop-until-maxIterations; framework detects and stops early — see Harness Control Flow
- Cortex MCP CRUD + JSON import — import Cursor/Claude-style MCP configs directly into Cortex — see Cortex
effectmoved topeerDependencies— addeffectexplicitly if you import from it directly — see Installation
v0.8.5 — Native FC Hardening + Web Framework Adapters
Section titled “v0.8.5 — Native FC Hardening + Web Framework Adapters”- React, Vue, and Svelte adapters —
useAgentStream()anduseAgent()hooks/composables/stores for all three frameworks, consuming SSE endpoints — see Web Integration and Streaming - Provider adapter hook system — 4 kernel prompt hooks (
continuationHint,errorRecovery,synthesisPrompt,qualityCheck) plusparseToolCalls(normalizes malformed native tool calls in every providercomplete()/stream()); calibration composes additively with the tier adapter rather than replacing it — see LLM Providers - Dynamic stopping (3-layer) — novelty signal (Jaccard overlap), budget exhaustion phase transition, and per-tool call cap (
maxCallsPerTool) — see Harness Control Flow - Full prompt observability —
logModelIO: truelogs the complete FC conversation thread with no truncation — see Observability - Actionable failure messages — loop detection, required-tools, and stall detection all emit
Fix:suggestions with specific builder options — see Troubleshooting
v0.8.0 — Reactive Intelligence Layer
Section titled “v0.8.0 — Reactive Intelligence Layer”- Entropy-aware intelligence pipeline — 5-source composite entropy sensor, trajectory classifier, and reactive controller that takes corrective action automatically — see Reactive Intelligence
- Thompson Sampling strategy learner — SQLite-backed bandit learns which reasoning strategy wins per task category across runs — see Reactive Intelligence
- Builder hardening —
withStrictValidation(),withTimeout(),withRetryPolicy(),withFallbacks(),withHealthCheck(), andwithErrorHandler()— see Builder API - Automatic strategy switching — when entropy analysis detects a stuck loop, the agent switches reasoning strategy without user intervention — see Choosing Strategies
- Observability dashboard upgrade — chalk/boxen terminal UI with entropy grade (A–F), sparklines, and entropy-informed alerts — see Observability
v0.5.0 — A2A Protocol + Observability Foundation
Section titled “v0.5.0 — A2A Protocol + Observability Foundation”- Full A2A (Agent-to-Agent) protocol — JSON-RPC 2.0 server, streaming SSE, client, discovery, and capability matching based on Google’s A2A spec — see A2A Protocol
- Agent-as-tool pattern — wrap any local or remote A2A agent as a callable tool with
createAgentTool()/createRemoteAgentTool()— see Sub-agents - Live observability streaming —
withObservability({ live: true, verbosity })writes structured phase logs to stdout as each step fires — see Observability rax serve— expose any agent as an A2A-compliant HTTP server with a single CLI command — see CLI- EventBus reasoning events — all strategies publish
ReasoningStepCompleted; subscribe withagent.on()for custom monitoring — see Observability