Skip to content

The Agents Layer (L1)

What this layer is (in one breath)

If the kernel is the rulebook of empty socket shapes, the agents layer is the first set of appliances that actually plug in. It is the concrete intelligence of the framework: the real ReActAgent that thinks and acts, the real in-process runtime that drives it, the real middleware, guardrails, caches, and budget trackers.

The analogy

The kernel says "a HistoryProvider must have get_messages()." The agents layer says "here is InMemoryHistoryProvider, which actually stores them in a dict." Kernel = the job description. Agents = the employee who shows up and does the job.

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#E8EAF6','primaryTextColor': '#1A237E','primaryBorderColor': '#3949AB','lineColor': '#546E7A','fontSize': '13px'}}}%%
graph TB
    classDef l1 fill:#E8EAF6,stroke:#3949AB,color:#1A237E,font-weight:bold
    classDef l0 fill:#E3F2FD,stroke:#1565C0,color:#0D47A1,font-weight:bold
    classDef up fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20

    UP["capabilities (L2) · fabric (L3)<br/>concrete tools, RAG, flows"]:::up -->|"build on"| L1["agents (L1)<br/>ReActAgent, Runtime, middleware, trackers"]:::l1
    L1 -->|"implements the contracts in"| L0["kernel (L0)<br/>Protocols, dataclasses, enums"]:::l0

The one rule to remember: the agents layer may import down from kernel, but never up from capabilities or fabric. That keeps the intelligence reusable and the dependency graph acyclic (enforced in CI by uv run lint-imports).


Three views of the same system

The docs describe this layer at three zoom levels. Use whichever matches your question:

Zoom level Section Answers
Story Core Concepts Why does this exist? What problem does it solve?
Contract Kernel Reference What is the exact Protocol / dataclass shape?
Implementation this section Which concrete class does it, and how is it wired?

Each page below cross-links to its concept and kernel companions, so you can hop between the "why," the "what," and the "how."


The seven pages, in reading order

# Page What it implements Analogy
1 Agent Types The kernel Agent Protocol — ReActAgent, OrchestratorAgent, UserProxyAgent Workers who think-act-repeat
2 The In-Process Runtime EventLog/Journal/Scheduler/Inbox contracts (in-memory) + Worker + RunContext The dispatcher and the job paperwork
3 Context, Compaction & Memory HistoryProvider, BlobStore, VectorStore, GraphStore (in-memory) + compaction A diary plus an editor and desk drawers
4 The LLM Stack The kernel LLMClient (wrappers: cache, fallback, router) Nesting adapters around one socket
5 Middleware & Guardrails The middleware pipeline + safety guardrails Airport-security layers around the gate
6 Tools: Toolbox & Invoker ToolRegistry + the enforcement ToolInvoker A toolbox plus a safety inspector
7 Supervision, Budgets & Hooks The mutable trackers enforcing kernel budgets + lifecycle hooks HR headcount, a running tab, security cameras

How a single run flows through this layer

One ReActAgent run touches almost every piece. Follow the numbers from the reading order:

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#E8EAF6','primaryTextColor': '#1A237E','primaryBorderColor': '#3949AB','lineColor': '#546E7A','fontSize': '13px'}}}%%
graph TB
    classDef runtime fill:#E3F2FD,stroke:#1565C0,color:#0D47A1,font-weight:bold
    classDef agent   fill:#E8EAF6,stroke:#3949AB,color:#1A237E,font-weight:bold
    classDef store   fill:#F3E5F5,stroke:#6A1B9A,color:#4A148C,font-weight:bold
    classDef tool    fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20,font-weight:bold

    RT["② Runtime + Worker<br/>leases the run"]:::runtime --> AG["① ReActAgent.run(ctx, inbox)"]:::agent
    AG --> CTX["③ load history + compact"]:::store
    AG --> MW["⑤ middleware + guardrails<br/>wrap the call"]:::agent
    MW --> LLM["④ LLM stack<br/>cache to router to fallback to provider"]:::agent
    AG --> TOOLS["⑥ ToolInvoker<br/>runs tools with risk gating"]:::tool
    AG --> TRK["⑦ trackers + hooks<br/>budgets + observation"]:::agent
    AG -.->|"every step journaled"| RT

A few layer-wide facts worth knowing early

Stage 0 is in-process, but the code is production-ready

The runtime here runs everything as in-process asyncio with no serialization. The same ReActAgent code runs durably against Postgres + Redis by swapping the injected backends (in infrastructure/). You write the agent once.

Wrappers and trackers are composable by design

The LLM wrappers all implement LLMClient, so you can stack Router → Cache → Fallback → provider in any order. Middleware composes the same way. This is the layer's recurring pattern: small pieces that share a kernel contract and nest cleanly.

ContextVars must be stamped inside the Worker task

Things like the task-board's agent_id/thread_id ContextVars are not visible across the SSE generator → Worker task boundary. They are set inside ReActAgent._handle_message(), not in serving code. See Context, Compaction & Memory.


Start here: Agent Types