Architecture Reference — Reactive Agents

SkillAI & models

Reactive Agents framework architecture — layer stack, dependency graph, build order, and package structure. Use when planning work, understanding package relationships, or determining build dependencies.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Architecture Reference — Reactive Agents skill

What this skill tells your AI

The instructions your AI receives, as published by tylerjrbuell/reactive-agents-ts in .agents/skills/architecture-reference/SKILL.md and read by ahel’s review.

For complete framework orientation, see AGENTS.md (root, sole entry point) and wiki/Development/Repo-Navigation.md (repo structure map + file mapping).

For architectural questions, prefer claude-obsidian:wiki-query "<topic>" over reading individual files. The wiki has MOCs, decisions, mechanism validations, and design specs that surface in semantic queries. See [[wiki/Development/Wiki-Workflow|Wiki-Workflow.md]] for the canonical pattern.

Wiki Resources for Architecture Lookup

QuestionWhere to look
"What's the kernel structure?"wiki/Architecture/Design-Specs/2026-07-11-harness-north-star-architecture.md (ratified kernel architecture)
"Why was decision X made?"wiki/Decisions/Decision Index.md
"What package contains Y?"wiki/Packages/00 Package Index.md
"Has mechanism Z been validated?"wiki/Experiments/M*.md (or wiki/Experiments/by-verdict.base)
"What failure modes apply here?"wiki/Failure-Modes/by-severity.base
"Current empirical state?"wiki/Hot.md (04-PROJECT-STATE.md is a deprecated 2026-04-27 snapshot)
"Roadmap?"root ROADMAP.md, or wiki/Architecture/Specs/09-UNIFIED-PROGRAM.md for sequencing (07-ROADMAP-v1.0.md is superseded)

Package Dependency Graph

Zero internal deps:

  • @reactive-agents/core — EventBus, types, Agent/Task services
  • @reactive-agents/runtime-shim — unified Bun/Node.js primitives; consumed by memory, tools, health, judge-server

Depends on core only:

  • @reactive-agents/llm-providercore
  • @reactive-agents/observabilitycore
  • @reactive-agents/identitycore
  • @reactive-agents/a2acore
  • @reactive-agents/interactioncore
  • @reactive-agents/observecore — OpenInference/OTel span exporter

Depends on core + llm-provider:

  • @reactive-agents/memorycore, llm-provider
  • @reactive-agents/toolscore, llm-provider
  • @reactive-agents/guardrailscore, llm-provider
  • @reactive-agents/costcore, llm-provider
  • @reactive-agents/evalcore, llm-provider
  • @reactive-agents/promptscore, llm-provider

Higher layers:

  • @reactive-agents/reasoningcore, llm-provider, memory, tools
  • @reactive-agents/verificationcore, llm-provider, memory
  • @reactive-agents/gatewaycore, llm-provider, tools
  • @reactive-agents/reactive-intelligencecore, llm-provider
  • @reactive-agents/replaycore, trace, runtime — deterministic trace replay
  • @reactive-agents/composecore, runtime — harness composition + 6 killswitches

Planned (branch feat/channels-package, not merged to main):

  • @reactive-agents/channelscore, gateway (external triggers, session bridge, webhook adapter); consumed by @reactive-agents/runtime via .withChannels() and optional dynamic import at start(). Gateway channelsaccessControl rename separates sender policy from chat/task mode. See wiki/Research/Debriefs/2026-05-03-channels-phase1-development-debrief.md.

Facade (depends on ALL):

  • @reactive-agents/runtime → all packages (composes layers via createRuntime())
  • reactive-agentsruntime (public API re-export)

Private (never published):

  • @reactive-agents/testingcore, llm-provider
  • @reactive-agents/benchmarksruntime
  • @reactive-agents/healthcore

Build Order

Build runs in dependency order. Lower layers must build before higher layers.

Phase 1: core → llm-provider
Phase 2: memory, tools, guardrails, cost, identity, observability, interaction, prompts, eval, a2a (parallel)
Phase 3: reasoning, verification, orchestration, gateway, reactive-intelligence (parallel)
Phase 4: runtime → reactive-agents (facade)
Phase 5: testing, benchmarks, health, cli, docs (parallel)

ExecutionEngine 10-Phase Loop

Phase 1:  BOOTSTRAP       MemoryService.bootstrap(agentId)
Phase 2:  GUARDRAIL        GuardrailService.checkInput(input)
Phase 3:  STRATEGY-SELECT  AdaptiveStrategy or config.defaultStrategy
Phase 4:  THINK            ReasoningService.execute() → kernel loop
Phase 5:  ACT              (synthetic — extracted from reasoning steps)
Phase 6:  OBSERVE          (synthetic — extracted from reasoning steps)
Phase 7:  MEMORY-FLUSH     MemoryExtractor + MemoryService.snapshot()
Phase 8:  VERIFY           VerificationService.verify(result) [optional]
Phase 9:  AUDIT            AuditService.log() [optional]
Phase 10: COMPLETE         EventBus.publish("AgentCompleted") + DebriefSynthesizer

Kernel Architecture (Reasoning)

All 6 strategies delegate to runKernel(reactKernel, input, options) in packages/reasoning/src/kernel/.

Composable Phase Pipeline

makeKernel({ phases?: Phase[] })
  ↓
kernel-runner.ts: runKernel() loop
  ↓ per turn:
  1. context-builder.ts  — buildSystemPrompt, toProviderMessage, buildConversationMessages, buildToolSchemas (pure data, no LLM)
  2. think.ts            — LLM stream, FC parsing, fast-path, loop detection, oracle hard gate
  3. guard.ts            — Guard[] pipeline, checkToolCall(guards), defaultGuards[]
  4. act.ts              — MetaToolHandler registry, final-answer gate, tool dispatch

Key Files

packages/reasoning/src/kernel/
  kernel-state.ts      — KernelState, Phase type, KernelContext, ThoughtKernel
  kernel-runner.ts     — the loop: runKernel() — DO NOT add per-turn logic here directly
  kernel-hooks.ts      — KernelHooks lifecycle hooks
  react-kernel.ts      — makeKernel() factory + reactKernel + executeReActKernel
  phases/
    context-builder.ts — pure data: builds what the LLM sees this turn
    think.ts           — LLM decision: stream, FC parsing, loop detection
    guard.ts           — Guard[] pipeline: is this tool call allowed?
    act.ts             — MetaToolHandler registry: what happens when tools run?
  utils/
    ics-coordinator.ts, reactive-observer.ts, loop-detector.ts
    tool-utils.ts, tool-execution.ts, termination-oracle.ts, strategy-evaluator.ts
    stream-parser.ts, context-utils.ts, quality-utils.ts, service-utils.ts, step-utils.ts

Two Independent State Records

state.messages[]  ← What the LLM sees (multi-turn FC conversation thread)
state.steps[]     ← What systems observe (entropy, metrics, debrief)

Do NOT conflate these. Debugging LLM behavior → inspect messages[]. Debugging metrics/entropy → inspect steps[].

Extending the Kernel

  • New phase: create phases/<name>.ts, insert into makeKernel({ phases: [...] })
  • New guard: add Guard fn to guard.ts, add to defaultGuards[]
  • New inline meta-tool: add one entry to metaToolRegistry in act.ts
  • Custom kernel: makeKernel({ phases: [myThink, act] })

See .agents/skills/kernel-extension/SKILL.md for full patterns.

Context Assembly — Canonical Path

  • context-manager.tsContextManager.build(state, input) returns { systemPrompt, messages } (pure, deterministic)
  • context-builder.ts — assembles raw conversation messages (buildConversationMessages), tool schemas, system prompt base
  • think.ts — invokes buildGuidanceSection(state.pendingGuidance) and appends Guidance: block to system prompt
  • context-engine.ts — retains only buildStaticContext, buildEnvironmentContext, buildRules; all dynamic/scoring code removed

MCP Client Architecture

Location: packages/tools/src/mcp/mcp-client.ts

Two Docker Patterns

PatternExamplesBehavior
stdio MCPGitHub MCP, filesystemContainer reads JSON-RPC from stdin
HTTP-onlymcp/context7Container starts HTTP server, ignores stdin

Both handled transparently via auto-detection.

Critical Rules

  • docker rm -f <containerName> is the ONLY reliable container stop. subprocess.kill() leaves the container alive in the Docker daemon.
  • Two-phase container naming: rax-probe-<name>-<pid> (initial stdio probe) → rax-mcp-<name>-<pid> (port-mapped HTTP if HTTP detected)
  • PID in name prevents conflicts between concurrent agents running the same MCP server
  • Transport auto-inferred: command"stdio", endpoint /mcp"streamable-http", other endpoint → "sse"
  • transport field is optional in MCPServerConfig — auto-inferred at runtime

See .agents/skills/mcp-integration/SKILL.md for full patterns.

Technology Stack

DecisionChoice
LanguageTypeScript (strict mode)
RuntimeBun >= 1.1
FP frameworkEffect-TS (^3.10)
Databasebun:sqlite (WAL mode), FTS5, sqlite-vec
LLM providersAnthropic, OpenAI, Ollama, Gemini, LiteLLM (40+)
Module systemESM ("type": "module")
Buildtsup (ESM + DTS)
Testbun:test
VersioningChangesets (fixed group)

Quick Navigation

What you needWhere to look
Full file-level system mapwiki/Architecture/Framework-Architecture-Index.md
Coding standardsCODING_STANDARDS.md
Effect-TS patterns.agents/skills/effect-ts-patterns/SKILL.md
LLM API signatures.agents/skills/llm-api-contract/SKILL.md
Memory/SQLite patterns.agents/skills/memory-patterns/SKILL.md
Spec documentsspec/docs/
Build commandsAGENTS.md (Build & Test Cycle) and README.md (quickstart/dev commands)
Extending the kernel.agents/skills/kernel-extension/SKILL.md
Debugging agent behavior.agents/skills/kernel-debug/SKILL.md
Provider streaming patterns.agents/skills/provider-streaming/SKILL.md
MCP client patterns.agents/skills/mcp-integration/SKILL.md
Full feature workflow.agents/skills/reactive-feature-dev/SKILL.md

Signals

GitHub stars
27
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
architecture-reference
Source
github.com/tylerjrbuell/reactive-agents-ts