Layered Architecture¶
Status: Implemented — migrated 2026-05-29
Background: The original kernel/ mixed pure contracts with full concrete implementations — LocalRuntime (643 lines), SagaCoordinator (411 lines), ResourceLockManager (354 lines), and more — all frozen alongside pure ABCs and Protocols. This document records the diagnosis that motivated the six-layer split, the design rationale for each layer, and the migration map that describes what moved where.
The Problem That Was Solved¶
The kernel was supposed to be "pure contracts — no I/O, no concrete implementations." What it actually contained:
| File | Lines | What it actually was |
|---|---|---|
kernel/runtime/_local.py | 643 | Full concrete LocalRuntime with asyncio loops |
kernel/runtime/_saga.py | 411 | Complete SagaCoordinator implementation |
kernel/runtime/_resource_lock.py | 354 | Complete ResourceLockManager with async locking |
kernel/runtime/_checkpoint.py | 296 | Full checkpoint store implementation |
kernel/runtime/_client_channel.py | 310 | Concrete ClientWriteChannel |
kernel/hooks.py | 289 | Complete HookManager with deque-based dispatch |
kernel/governance/_contracts.py | 241 | GovernancePolicy, CoalitionDetector, QuarantineActuator |
kernel/scheduler/_contracts.py | 212 | SchedulerContract, ResourceClaim, PreemptionSignal |
kernel/semantics/_contracts.py | 225 | SemanticInvariantChecker, SemanticDivergenceDetector |
The kernel was mixing four fundamentally different levels into one frozen bucket:
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
quadrantChart
title What is actually inside kernel/
x-axis "Low abstraction (primitives)" --> "High abstraction (platform)"
y-axis "Protocol-only (correct)" --> "Full implementation (wrong)"
quadrant-1 Should be platform/ or guardrails/
quadrant-2 Should be fabric/ (separate layer)
quadrant-3 Belongs in kernel
quadrant-4 Should be reasoning/ or fabric/
AgentId: [0.05, 0.05]
ToolRisk: [0.08, 0.05]
ContentBlock: [0.10, 0.05]
BaseMemory: [0.15, 0.10]
BaseTool: [0.18, 0.12]
BaseGuardrail: [0.20, 0.15]
ModelContext: [0.22, 0.08]
MessageContext: [0.25, 0.10]
ExecutionMiddlewarePipeline: [0.35, 0.65]
HookManager: [0.40, 0.70]
LocalRuntime: [0.42, 0.90]
SagaCoordinator: [0.55, 0.88]
ResourceLockManager: [0.50, 0.85]
MutationPolicy: [0.72, 0.15]
GovernancePolicy: [0.85, 0.12]
EconomicLedger: [0.88, 0.14]
SchedulerContract: [0.82, 0.12]
SemanticInvariant: [0.90, 0.15]
KillSwitch: [0.88, 0.18] The consequence is architectural: when you want to add a new governance rule that references both EconomicSignal and MutationKind (both currently in kernel/), you cannot implement it anywhere — the kernel cannot import from extensions/, and extensions/ cannot import freely from kernel/governance/ without pulling everything.
The Six-Layer Model¶
A truly autonomous agent system needs six independent capabilities, each built on the one below it. These are the layers the codebase is now structured around:
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#334155", "lineColor": "#64748b"}}}%%
flowchart TD
P0["🔵 L0 · Core<br/>Pure types · ABCs · Protocols<br/>Zero behavior · Zero I/O"]:::l0
P1["🟢 L1 · Fabric<br/>Message routing · Dispatch<br/>Runtime · Supervision · Saga"]:::l1
P2["🟡 L2 · Reasoning<br/>ReAct loop · Memory<br/>Guardrails · Middleware · Hooks"]:::l2
P3["🟠 L3 · Orchestration<br/>Multi-agent workflows<br/>Handoffs · Shared memory"]:::l3
P4["🔴 L4 · Guardrails<br/>Mutation gates · Governance<br/>Budget limits · Kill-switch"]:::l4
P5["🟣 L5 · Platform<br/>Observability · Scheduling<br/>Batch · Evals · RAG"]:::l5
P0 --> P1 --> P2 --> P3 --> P4 --> P5
classDef l0 fill:#1e3a5f,stroke:#60a5fa,color:#eff6ff
classDef l1 fill:#14532d,stroke:#4ade80,color:#f0fdf4
classDef l2 fill:#713f12,stroke:#fbbf24,color:#fffbeb
classDef l3 fill:#7c2d12,stroke:#fb923c,color:#fff7ed
classDef l4 fill:#7f1d1d,stroke:#f87171,color:#fef2f2
classDef l5 fill:#4a1d96,stroke:#c084fc,color:#faf5ff Each layer can import from any layer below it. Nothing ever imports upward.
Layer-by-Layer Breakdown¶
L0 — Kernel (the frozen contract layer)¶
The absolute bedrock. Only pure Python types: dataclasses, enums, ABCs with no logic in their bodies, and Protocols. No asyncio, no Pydantic @field_validator with business logic, no concrete method bodies. If a file has more than a few lines per class, it does not belong here.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
flowchart LR
subgraph P0["L0 · Kernel — kernel/"]
direction TB
T["types/<br/>ContentBlock · TextBlock<br/>ImageBlock · AudioBlock · JsonObject"]
I["identity/<br/>AgentId · TopicId<br/>PrincipalId · DelegationToken"]
M["messages/<br/>BaseClientMessage<br/>SystemMessage · UserMessage<br/>AssistantMessage<br/>ToolCallMessage · ToolResultMessage"]
PR["protocols/<br/>AgentRuntime · BaseTool<br/>BaseMemory · BaseModelClient<br/>BaseGuardrail · ModelContext<br/>BaseMiddleware · LineageStore"]
R["results/<br/>ToolResult · ToolRisk<br/>HitlMode · RunStatus<br/>AgentRunResult · GuardrailResult"]
REG["plugin/<br/>@register_* decorators<br/>registry dict · PluginSpec"]
ENC["encoders/<br/>OpenAI · Anthropic · Gemini<br/>wire format adapters"]
end
style P0 fill:#1e3a5f,stroke:#60a5fa,color:#eff6ff What was removed from kernel/ during the migration:
Was in kernel/ | Moved to |
|---|---|
runtime/_local.py (LocalRuntime — full concrete) | L1 · Fabric |
runtime/_base.py (BaseRuntime — abstract but with concrete methods) | L1 · Fabric |
runtime/_saga.py (SagaCoordinator — full impl) | L1 · Fabric |
runtime/_resource_lock.py (ResourceLockManager) | L1 · Fabric |
runtime/_checkpoint.py (CheckpointStore impl) | L1 · Fabric |
runtime/_client_channel.py (ClientWriteChannel) | L1 · Fabric |
runtime/_dispatcher.py, _mailbox.py, _supervisor.py | L1 · Fabric |
agents/actor.py (ActorAgent ABC — refs runtime internals) | L1 · Fabric |
agent_catalog/_catalog.py (AgentCatalog — 789 lines) | L1 · Fabric |
hooks.py (HookManager — concrete, 289 lines) | L2 · Reasoning |
execution/pipeline.py (ExecutionMiddlewarePipeline — concrete runner) | L2 · Reasoning |
memory/unbounded_memory.py (reference impl) | L1 · Fabric |
storage/local.py (LocalFileStore — concrete) | L1 · Fabric |
safeguards/_mutation.py | L4 · Guardrails |
safeguards/_breaker.py | L4 · Guardrails |
governance/_contracts.py | L4 · Guardrails |
economic/_ledger.py, _signals.py | L4 · Guardrails |
observability/_killswitch.py, _replay.py | L4 · Guardrails |
scheduler/_contracts.py | L5 · Platform |
semantics/_contracts.py | L5 · Platform |
ranking/_contracts.py | L5 · Platform |
observability/_spans.py | L5 · Platform |
What stays in kernel/ (L0): pure types, ABCs with no implementations, Protocols, the plugin registry. After the migration the kernel sits at ~11.8k LOC / 95 files, bounded by CI ceilings of 14k LOC / 115 files. The remaining code is genuinely frozen — it changes only when a new fundamental primitive is needed.
L1 — Fabric (the runtime infrastructure)¶
The fabric makes agents addressable, routes messages between them, supervises their lifecycle, and handles exactly-once execution of critical actions. It is the "operating system" for the agent mesh.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
flowchart TB
subgraph F["L1 · Fabric — fabric/"]
direction TB
subgraph RT["runtime/"]
BR["BaseRuntime<br/>ABC · shared register / subscribe"]
LR["LocalRuntime<br/>asyncio implementation"]
DR["DistributedRuntime<br/>Redis / gRPC implementation"]
LR --> BR
DR --> BR
end
subgraph AC["actors/"]
AA["ActorAgent ABC<br/>name · runtime · key<br/>start() / stop()<br/>on_message() — abstract<br/>send() / publish()"]
SC["StreamChannel Protocol"]
SE["StreamEnvelope"]
end
subgraph IN["internals/"]
DI["Dispatcher<br/>routes Envelope to Mailbox"]
MB["Mailbox<br/>BackpressurePolicy<br/>asyncio.Queue per agent"]
SV["Supervisor<br/>Erlang-style restart<br/>AgentLifecycleState"]
LK["ResourceLockManager<br/>advisory locking"]
SG["SagaCoordinator<br/>exactly-once semantics<br/>compensating rollback"]
CH["CheckpointStore<br/>recovery snapshots"]
end
subgraph CAT["catalog/"]
AGC["AgentCatalog<br/>per-agent registry<br/>models · memories · tools · contexts"]
end
subgraph REF["reference/"]
UM["UnboundedMemory<br/>in-memory list store"]
LFS["LocalFileStore<br/>filesystem store"]
end
end
style F fill:#14532d,stroke:#4ade80,color:#f0fdf4 The key distinction from the current arrangement: ActorAgent moves from kernel/ to fabric/. It belongs here because its start() method calls runtime.register() — it has a concrete dependency on the fabric. The kernel (L0 Core) should contain only protocols; ActorAgent with its concrete start(), stop(), send(), publish() methods is a fabric object.
The fabric is also where SagaCoordinator and ResourceLockManager live. These are not abstract contracts — they are full working implementations. Having them in a supposedly "frozen" layer was the mistake.
L2 — Reasoning (how one agent thinks)¶
Reasoning is everything a single agent needs to think, remember, act, and introspect — without caring about other agents, multi-tenancy, or production operations.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
flowchart LR
subgraph C["L2 · Reasoning — reasoning/"]
direction TB
subgraph LP["loop/"]
RL["ReAct loop<br/>think → act → observe<br/>_react_loop · _tool_execution<br/>_guardrail_runner · _stream_handler"]
end
subgraph MEM["memory/"]
CTX["Context strategies<br/>SlidingWindowContext<br/>TokenBudgetContext<br/>SummarizingContext · HybridContext"]
SM["SessionManager<br/>cross-session orchestration"]
LIN["InMemoryLineageStore<br/>append-only audit trail"]
end
subgraph GR["guardrails/"]
GRN["Parallel runner<br/>asyncio.gather over BaseGuardrail list"]
BGS["Built-ins<br/>PII · ContentFilter · PromptInjection<br/>MaxToken · LLMJudge · ToolCallValidation"]
end
subgraph MW["middleware/"]
EMP["ExecutionMiddlewarePipeline<br/>before → execute → after → on_error"]
BMW["Built-ins<br/>AuditLogger · Cache<br/>RateLimiter · Retry · HistoryTruncator"]
end
subgraph HK["hooks/"]
HM["HookManager<br/>on_run_start · on_llm_start<br/>on_tool_start · on_handoff"]
end
subgraph ST["structured/"]
SOP["StructuredOutputResult<br/>Pydantic model extraction<br/>JSON schema validation"]
end
end
style C fill:#713f12,stroke:#fbbf24,color:#fffbeb The single concrete agent implementation (AssistantAgent) lives here, at the top of the reasoning layer. The key insight about reasoning: it is stateless with respect to other agents. AssistantAgent receives a task, runs a loop against its own memory and tools, and returns a result. It does not know about orchestration, workflows, or other agents. That awareness belongs in the orchestration layer.
L3 — Orchestration (how agents cooperate)¶
Orchestration is the layer where individual reasoning agents become a system. Patterns here describe how tasks get routed, how results get combined, how context flows between agents.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
flowchart TB
subgraph CO["L3 · Orchestration — orchestration/"]
direction LR
subgraph AG["agents/"]
UA["UserProxyAgent<br/>bridges external callers<br/>ask() / ask_stream()"]
OA["OrchestratorAgent<br/>routes tasks to sub-agents<br/>via runtime.send_message()"]
FA["FlowAgent<br/>sequential / parallel<br/>step execution"]
end
subgraph WF["workflows/"]
WFR["WorkflowRunner<br/>parses pipeline JSON<br/>instantiates agents and flows"]
CR["ConditionWorkflowRunner<br/>branching via expressions"]
LR2["LoopWorkflowRunner<br/>loop until condition"]
CG["codegen.py<br/>JSON graph to Python"]
end
subgraph SH["shared/"]
SHM["Shared memory<br/>cross-agent memory scope<br/>binding pattern"]
HO["Handoff protocol<br/>HandoffTool · agent delegation"]
end
end
style CO fill:#7c2d12,stroke:#fb923c,color:#fff7ed Orchestration agents (OrchestratorAgent, FlowAgent) are ActorAgent subclasses (L1) whose on_message() implementations dispatch to other agents via runtime.send_message(). They are architecturally identical to reasoning agents — the difference is that their logic is routing, not thinking.
L4 — Guardrails (how the system stays trustworthy)¶
Guardrails is the layer that constrains what agents are permitted to do. It is intentionally separate from reasoning and orchestration because safety rules must be enforceable independently of how agents are implemented. A governance policy should not need to know whether it is gating an AssistantAgent or an OrchestratorAgent.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
flowchart LR
subgraph SA["L4 · Guardrails — guardrails/"]
direction TB
subgraph MU["mutation/"]
MP["MutationPolicy Protocol<br/>gates self-evolution"]
MK["MutationKind enum<br/>PROMPT_REWRITE · TOOL_ADD<br/>TOOL_REMOVE · WEIGHT_UPDATE<br/>BEHAVIOR_DIVERGENCE"]
MR["MutationRequest · MutationPermission"]
end
subgraph BR["circuit/"]
CB["CircuitBreaker<br/>CLOSED → OPEN → HALF_OPEN<br/>protects downstream services"]
end
subgraph GV["governance/"]
GP["GovernancePolicy Protocol<br/>ALLOW / QUARANTINE / ESCALATE"]
CD["CoalitionDetector Protocol<br/>detects agent collusion"]
QA["QuarantineActuator Protocol<br/>isolates misbehaving agents"]
GE["GovernanceEvidence · RiskScore"]
end
subgraph EC["economic/"]
BL["BudgetLedger Protocol<br/>reserve / commit / release tokens"]
ES["EconomicSignal · EconomicSignalSource"]
BE["BudgetExhausted exception<br/>stops the agent loop"]
end
subgraph KS["killswitch/"]
OK["OperatorKillSwitch Protocol<br/>scoped to agent / tenant / global"]
KR["KillSwitchRule · KillSwitchDecision"]
end
subgraph SM["semantic/"]
SIC["SemanticInvariantChecker<br/>detects behavioral drift"]
SDD["SemanticDivergenceDetector<br/>compares against baseline"]
end
end
style SA fill:#7f1d1d,stroke:#f87171,color:#fef2f2 Why guardrails is a separate layer and not part of reasoning:
An agent's reasoning (L2) decides what to do. Guardrails (L4) decides whether it is allowed to do it. These are different authorities — in production you want to strengthen guardrail rules without redeploying reasoning logic, and vice versa.
Before the migration, MutationPolicy lived in kernel/safeguards/ and GovernancePolicy in kernel/governance/ — both contracts with no implementations, impossible to compose. Moving both to guardrails/ (L4) fixed this: contracts and implementations share a layer, and the layer boundary is enforced by import-linter. The guardrails/ layer can import from orchestration/ downward; orchestration/ cannot import from guardrails/.
L5 — Platform (how the system operates at scale)¶
Platform concerns are orthogonal to what agents do — they describe how the operator observes, schedules, evaluates, and scales the system.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#475569"}}}%%
flowchart LR
subgraph PL["L5 · Platform — platform/"]
direction TB
subgraph OB["observability/"]
SP["EnvelopeSpanRecorder Protocol<br/>OTel span shaping"]
RG["ReplayGate Protocol<br/>admission for event replay"]
MT["Metrics · traces · OTel setup"]
end
subgraph SC["scheduling/"]
SCH["SchedulerContract Protocol<br/>ResourceClaim · SlotGrant<br/>PreemptionSignal"]
TMP["Temporal.io integration<br/>activities · workflows · worker"]
end
subgraph BT["batch/"]
BP["BatchProcessor<br/>fan-out over dataset<br/>concurrency · retries"]
end
subgraph EV["evals/"]
ER["EvalRunner<br/>EvalCase · EvalDataset · EvalReport"]
LJ["LLMJudge<br/>CORRECTNESS · SAFETY · grading criteria"]
end
subgraph RA["rag/"]
RAG["RAG pipeline<br/>chunkers · loaders<br/>VectorStore · GraphStore · reranker"]
SEM["SemanticCache<br/>embedding-based dedup"]
end
subgraph RK["ranking/"]
RNK["RankingPolicy Protocol<br/>FeedRanker · attention weights · scoring"]
end
end
style PL fill:#4a1d96,stroke:#c084fc,color:#faf5ff RAG lives in platform/rag/ because retrieval is not a single-agent reasoning operation — it is a data-platform concern shared across agents and tenants. An AssistantAgent calls a tool that queries the RAG pipeline; the RAG pipeline itself is a platform service.
The Full Picture¶
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#1e293b", "primaryTextColor": "#f1f5f9", "primaryBorderColor": "#334155", "lineColor": "#64748b", "clusterBkg": "#0f172a"}}}%%
flowchart TD
subgraph SV["server / services"]
S1["FastAPI routes<br/>ORM models · DI wiring"]
end
subgraph CAT["catalog/"]
S2["Tools · Skills · Connectors<br/>Data pipelines"]
end
subgraph INTG["integrations/"]
S3["OpenAI · Anthropic · Gemini<br/>Redis · Postgres · S3 · MCP"]
end
subgraph PLAT["platform/ — L5"]
S4["Observability · Scheduling<br/>Batch · Evals · RAG · Ranking"]
end
subgraph SAFE["guardrails/ — L4"]
S5["Mutation gates · Governance<br/>Budget limits · Kill-switch<br/>Semantic drift detection"]
end
subgraph COORD["orchestration/ — L3"]
S6["OrchestratorAgent · FlowAgent<br/>UserProxyAgent · WorkflowRunner"]
end
subgraph COG["reasoning/ — L2"]
S7["AssistantAgent · ReAct loop<br/>Guardrail runner · Middleware<br/>Memory strategies · Hooks"]
end
subgraph FAB["fabric/ — L1"]
S8["LocalRuntime · ActorAgent<br/>Dispatcher · Mailbox · Supervisor<br/>Saga · ResourceLock · AgentCatalog"]
end
subgraph KER["kernel/ — L0"]
S9["ContentBlock · AgentId<br/>Message types · ABCs<br/>Protocols · Enums · Plugin registry"]
end
SV --> CAT --> INTG --> PLAT --> SAFE --> COORD --> COG --> FAB --> KER
style KER fill:#1e3a5f,stroke:#60a5fa,color:#eff6ff
style FAB fill:#14532d,stroke:#4ade80,color:#f0fdf4
style COG fill:#713f12,stroke:#fbbf24,color:#fffbeb
style COORD fill:#7c2d12,stroke:#fb923c,color:#fff7ed
style SAFE fill:#7f1d1d,stroke:#f87171,color:#fef2f2
style PLAT fill:#4a1d96,stroke:#c084fc,color:#faf5ff
style INTG fill:#065f46,stroke:#34d399,color:#ecfdf5
style CAT fill:#1e3a5f,stroke:#94a3b8,color:#e2e8f0
style SV fill:#334155,stroke:#94a3b8,color:#e2e8f0 shared/ and configs/ remain orthogonal utilities (cross-cutting infrastructure: Pydantic settings, JWT auth, database sessions, event bus). They are importable by any layer above L0.
Why the Six Layers Enable Better Autonomous Agents¶
Problem 1: Minimal agent dependency was impossible¶
Before the migration the only agent was AssistantAgent in extensions/agents/assistant/. Using it meant depending on the whole extensions/ bucket — guardrail runner, context strategies, HITL, middleware, orchestration, and RAG as undifferentiated peers.
Now: AssistantAgent depends on reasoning/ which depends on fabric/ which depends on kernel/. The dependency chain is explicit and minimal. Taking just reasoning/ gives a fully working single agent with no multi-agent, no governance, no platform concerns.
Problem 2: Safety contracts had no home¶
MutationPolicy was in kernel/safeguards/ but implementations had to live in extensions/. GovernancePolicy was in kernel/governance/ but implementations were nowhere — there was no clear place to put them.
Now: guardrails/ contains both contracts and implementations. A TenantBudgetPolicy(BudgetLedger) lives in guardrails/economic/ alongside the contract it implements. The layer boundary is enforced: guardrails/ can import from orchestration/ downward, but orchestration/ cannot import from guardrails/.
Problem 3: The "frozen" constraint was unenforceable¶
The kernel had 16,895 LOC including full asyncio implementations. Import-linter prevented upward imports but could not prevent the kernel from growing with concrete code.
Now: The kernel sits at ~11.8k LOC / 95 files (CI ceiling: 14k / 115). Only contracts remain — adding a feature never requires editing L0.
Problem 4: No guidance for where new features live¶
"I want to add a budget-aware retry that stops the agent when it hits $10 in LLM costs. Where does this go?"
Before: unclear — kernel/economic/ had the contract, extensions/resilience/ had retry, extensions/middleware/ had another retry, nothing was wired together.
Now: Budget-aware retry is a guardrails + reasoning composition. Write BudgetAwareRetryMiddleware in guardrails/economic/ (it reads from BudgetLedger) and register it as middleware. The layer guarantees it can import from reasoning/ (middleware protocol) and guardrails/ (economic ledger).
What Moved Where¶
Complete file-to-layer reference for the migration.
| Old path | Current path | Layer |
|---|---|---|
kernel/runtime/_local.py | fabric/runtime/local.py | L1 |
kernel/runtime/_base.py | fabric/runtime/base.py | L1 |
kernel/runtime/_dispatcher.py | fabric/runtime/dispatcher.py | L1 |
kernel/runtime/_mailbox.py | fabric/runtime/mailbox.py | L1 |
kernel/runtime/_supervisor.py | fabric/runtime/supervisor.py | L1 |
kernel/runtime/_saga.py | fabric/saga.py | L1 |
kernel/runtime/_resource_lock.py | fabric/locks.py | L1 |
kernel/runtime/_checkpoint.py | fabric/checkpoint.py | L1 |
kernel/runtime/_client_channel.py | fabric/channel.py | L1 |
kernel/agents/actor.py | fabric/actors/actor.py | L1 |
kernel/agent_catalog/ | fabric/catalog/ | L1 |
kernel/memory/unbounded_memory.py | fabric/memory/unbounded.py | L1 |
kernel/storage/local.py | fabric/storage/local.py | L1 |
kernel/hooks.py | reasoning/hooks/manager.py | L2 |
kernel/execution/pipeline.py | reasoning/middleware/pipeline.py (then kernel) | L2→L0 |
(old extensions) agents/assistant/ | reasoning/agents/assistant/ | L2 |
(old extensions) context/ | reasoning/memory/ | L2 |
(old extensions) guardrails/ | reasoning/guardrails/ | L2 |
(old extensions) middleware/ | reasoning/middleware/ | L2 |
(old extensions) structured/ | reasoning/structured/ | L2 |
(old extensions) agents/orchestrator/ | orchestration/agents/ | L3 |
(old extensions) agents/flow/ | orchestration/agents/ | L3 |
(old extensions) agents/user_proxy/ | orchestration/agents/proxy/ | L3 |
(old extensions) pipelines/ | orchestration/workflows/ | L3 |
kernel/safeguards/ | guardrails/mutation/ | L4 |
kernel/governance/ | guardrails/governance/ | L4 |
kernel/economic/ | guardrails/economic/ | L4 |
kernel/observability/_killswitch.py | guardrails/ | L4 |
kernel/semantics/ | guardrails/semantic/ | L4 |
kernel/observability/_spans.py | platform/observability/ | L5 |
kernel/scheduler/ | platform/scheduling/ | L5 |
kernel/ranking/ | platform/ranking/ | L5 |
evals/ | platform/evals/ | L5 |
(old extensions) rag/ | platform/rag/ | L5 |
(old extensions) batch/ | platform/batch/ | L5 |
Stays in kernel/ (L0): kernel/messages/, kernel/tools/base_tool.py, kernel/memory/base_memory.py, kernel/context/, kernel/guardrails/base_guardrail.py, kernel/middleware/base.py, kernel/llm/base_client.py, kernel/storage/base.py, kernel/structured/result.py, kernel/runtime/_identity.py, kernel/runtime/_protocol.py, kernel/runtime/_contracts.py, kernel/runtime/_errors.py, kernel/plugin/, kernel/contracts/, kernel/agents/agent_result.py, kernel/safeguards/ (contracts only), kernel/governance/ (contracts only), kernel/economic/ (contracts only), kernel/observability/ (contracts only), kernel/semantics/ (contracts only).
Migration Summary¶
The migration was completed in six phases on 2026-05-29. All 1297 tests pass. Import-linter reports 0 violations. Kernel sits at ~11.8k LOC / 95 files.
| Phase | What was done | CI status |
|---|---|---|
| 1 — Fabric | Moved LocalRuntime, runtime internals, ActorAgent, AgentCatalog, SagaCoordinator, ResourceLockManager, UnboundedMemory | Green |
| 2 — Reasoning | Moved AssistantAgent, context strategies, guardrail runner and built-ins, middleware, HookManager | Green |
| 3 — Orchestration | Moved OrchestratorAgent, FlowAgent, UserProxyAgent, pipeline runners → orchestration/workflows/ | Green |
| 4 — Guardrails | Moved MutationPolicy, CircuitBreaker, governance contracts, economic ledger, kill-switch, semantic invariants | Green |
| 5 — Platform | Moved OTel span recorder, replay gate, scheduler contracts, evals, RAG, batch, ranking | Green |
| 6 — Kernel strip | Removed all upward re-export shims from kernel __init__.py files; deleted dead extensions/ tree; lowered CI ceilings | Green |
What Did Not Change¶
- The
catalog/,integrations/,server/,services/,shared/directories are unchanged. - The plugin registry API (
@register_agent,@register_guardrail, etc.) is unchanged. - The
AgentRuntimeprotocol andAgentId/TopicIdtypes are unchanged — they remain inkernel/. - The
Envelopedataclass stays inkernel/(pure value type with no runtime dependency). BaseTool,BaseMemory,BaseGuardrail,BaseModelClient,ModelContextABCs stay inkernel/.
Import Paths After Migration¶
There is no backward compatibility. Old kernel.runtime._local.LocalRuntime style imports must be updated:
| What you need | Current import |
|---|---|
LocalRuntime | from ravi.fabric.runtime.local import LocalRuntime |
ActorAgent | from ravi.fabric.actors.actor import ActorAgent |
StreamChannel, StreamEnvelope | from ravi.fabric.actors.actor import StreamChannel, StreamEnvelope |
AgentCatalogRegistry | from ravi.fabric.catalog import AgentCatalogRegistry |
UnboundedMemory | from ravi.fabric.memory.unbounded import UnboundedMemory |
AssistantAgent | from ravi.reasoning.agents.assistant.agent import AssistantAgent |
UserProxyAgent | from ravi.orchestration.agents.proxy.agent import UserProxyAgent |
AgentId, TopicId | from ravi.kernel.runtime._identity import AgentId, TopicId |
AgentRuntime (protocol) | from ravi.kernel.runtime._protocol import AgentRuntime |
BaseTool, ToolResult | from ravi.kernel.tools.base_tool import BaseTool, ToolResult |
BaseMemory | from ravi.kernel.memory.base_memory import BaseMemory |
BaseGuardrail | from ravi.kernel.guardrails.base_guardrail import BaseGuardrail |