Architecture Overview¶
This document provides a comprehensive overview of the system architecture, explaining how components interact to create a flexible, extensible AI agent runtime.
The Kernel Philosophy¶
The kernel follows a fundamental principle: mechanism, not policy.
This means the kernel provides the how but never the what. It offers primitives for:
- Session management and lifecycle
- Event emission and subscription
- Module mounting and discovery
- Tool invocation and result handling
- Hook execution chains
What it explicitly avoids:
- Deciding which tools to expose
- Defining conversation strategies
- Implementing specific behaviors
- Making business logic decisions
This separation keeps the kernel minimal and stable while allowing infinite customization through modules. The kernel changes rarely; modules change constantly.
Session Lifecycle¶
Every interaction flows through a well-defined session lifecycle:
User Input
↓
┌─────────────────────────────────────────────────────────────────┐
│ SESSION │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ State: user_id, session_id, context, history │ │
│ └─────────────────────────────────────────────────────────┘ │
└────────────────────────────┬────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ COORDINATOR │
│ • Validates input │
│ • Manages conversation flow │
│ • Handles turn transitions │
└────────────────────────────┬────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ ORCHESTRATOR │
│ • Manages the agent loop │
│ • Dispatches to provider │
│ • Processes tool calls │
│ • Executes hooks at each phase │
└────────────────────────────┬────────────────────────────────────┘
↓
┌──────────────┴──────────────┐
↓ ↓
┌─────────────────────────┐ ┌─────────────────────────┐
│ PROVIDER │ │ TOOLS/HOOKS │
│ (Claude, GPT, etc.) │ │ (Mounted Modules) │
└─────────────────────────┘ └─────────────────────────┘
Session States¶
A session progresses through these states:
- INITIALIZING - Session created, loading configuration
- READY - All modules mounted, waiting for input
- PROCESSING - Actively handling a user turn
- AWAITING_TOOL - Waiting for tool execution results
- COMPLETED - Session ended normally
- ERROR - Session ended due to an error
The Agent Loop¶
The orchestrator runs the core agent loop:
┌──────────────────────────────────────────────────────────────┐
│ AGENT LOOP │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ User │───→│ Provider │───→│ Tool Calls? │ │
│ │ Input │ │ (LLM) │ └──────┬──────┘ │
│ └─────────┘ └──────────┘ │ │
│ Yes │ No │
│ ┌─────────────────┼──────────┐ │
│ ↓ ↓ │
│ ┌────────────────┐ ┌───────────┐ │
│ │ Execute Tools │ │ Return │ │
│ │ (with hooks) │ │ Response │ │
│ └───────┬────────┘ └───────────┘ │
│ │ │
│ └──────→ Back to Provider ─────────────┘│
│ │
└──────────────────────────────────────────────────────────────┘
The loop continues until the provider returns a response without tool calls, or a maximum iteration limit is reached.
Event Flow¶
The system uses an event-driven architecture for observability and extensibility. Events flow through a central bus, allowing modules to subscribe to what they need.
Event Categories¶
| Category | Purpose | Examples |
|---|---|---|
session.* |
Session lifecycle | session.started, session.ended |
turn.* |
Turn processing | turn.started, turn.completed |
tool.* |
Tool invocation | tool.called, tool.result |
provider.* |
LLM interactions | provider.request, provider.response |
hook.* |
Hook execution | hook.before, hook.after |
Event Structure¶
Every event follows a consistent structure:
{
"event_type": "tool.called",
"timestamp": "2024-01-15T10:30:00Z",
"session_id": "abc123",
"payload": {
"tool_name": "read_file",
"arguments": {"path": "/src/main.py"},
"invocation_id": "inv_456"
},
"metadata": {
"source_module": "tool-filesystem",
"turn_number": 3
}
}
Subscribing to Events¶
Modules subscribe to events using pattern matching:
# Subscribe to all tool events
@event_handler("tool.*")
async def on_tool_event(event):
logger.info(f"Tool event: {event.event_type}")
# Subscribe to specific event
@event_handler("session.started")
async def on_session_start(event):
await initialize_user_context(event.payload.user_id)
Module Mounting¶
Modules are the primary extension mechanism. They provide tools, hooks, context, and behaviors that customize the system.
Module Types¶
| Type | Purpose | Examples |
|---|---|---|
| Tool Modules | Provide callable tools | tool-filesystem, tool-web |
| Hook Modules | Intercept/modify flows | hook-auth, hook-logging |
| Context Modules | Inject system prompts | context-project, context-user |
| Provider Modules | LLM integrations | provider-anthropic, provider-openai |
| Behavior Modules | Complex behaviors | behavior-agents, behavior-memory |
Mount Order¶
Modules are mounted in a specific order:
- Core modules - Kernel-provided fundamentals
- Provider modules - LLM connectivity
- Context modules - System prompt building
- Tool modules - Available capabilities
- Hook modules - Processing interceptors
- Behavior modules - High-level behaviors
Within each category, modules mount in the order specified in configuration.
Module Resolution¶
When mounting, the system follows this flow:
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Discover │───→│ Validate │───→│ Initialize │
└────────────┘ └────────────┘ └────────────┘
│
↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Activate │←───│ Register │←───│ Ready │
└────────────┘ └────────────┘ └────────────┘
- Discovers - Finds the module by name/path
- Validates - Checks dependencies and compatibility
- Initializes - Calls the module's init function
- Registers - Adds tools/hooks to the session
- Activates - Marks the module as ready
Module Dependencies¶
Modules can declare dependencies on other modules:
# module.yaml
name: my-tool
version: 1.0.0
dependencies:
- tool-filesystem: ">=1.0.0"
- hook-auth: ">=2.0.0"
The mount system ensures dependencies are satisfied before loading.
Tool Registration¶
When a tool module mounts, it registers its tools:
class FilesystemModule:
def register_tools(self, registry):
registry.add_tool(
name="read_file",
description="Read contents of a file",
parameters=ReadFileParams,
handler=self.read_file
)
Hook Execution¶
Hooks allow modules to intercept and modify the processing flow at defined points.
Hook Points¶
| Hook Point | When | Use Cases |
|---|---|---|
pre_turn |
Before processing starts | Auth, rate limiting |
pre_provider |
Before LLM call | Prompt modification |
post_provider |
After LLM response | Response filtering |
pre_tool |
Before tool execution | Permission checks |
post_tool |
After tool execution | Result transformation |
post_turn |
After turn completes | Logging, cleanup |
Hook Chain¶
Multiple hooks at the same point form a chain:
Input → Hook1 → Hook2 → Hook3 → Continue Processing
↑
(can modify or abort)
Hooks execute in registration order. Any hook can: - Pass through - Let the chain continue - Modify - Change the data and continue - Abort - Stop the chain and return early
Hook Example¶
@hook("pre_tool")
async def validate_file_access(context, tool_name, arguments):
if tool_name == "write_file":
path = arguments.get("path", "")
if not is_allowed_path(path):
raise PermissionError(f"Cannot write to: {path}")
return arguments # Continue with (possibly modified) args
Key Takeaways¶
Understanding the architecture helps you work effectively with the system:
1. Kernel is Minimal¶
The kernel provides mechanisms, not policies. It's deliberately simple and stable. Customize through modules, not kernel changes.
2. Sessions are Stateful¶
Each session maintains its own state, mounted modules, and conversation history. Sessions are isolated from each other.
3. Events Enable Observability¶
Everything emits events. Use them for logging, debugging, metrics, and extending behavior without modifying core code.
4. Modules are the Extension Point¶
Need new functionality? Create a module. Need to modify behavior? Create a hook. The module system is designed for this.
5. Order Matters¶
Mount order, hook order, and event order all affect behavior. Be intentional about ordering in your configurations.
6. The Agent Loop is Central¶
Understanding the orchestrator's agent loop is key to understanding how conversations flow and how tools integrate.
Next Steps¶
With this architectural understanding, explore:
- Modules Deep Dive - Creating and configuring modules
- Hooks Guide - Building effective hooks
- Bundles Guide - Bundle composition patterns
- Advanced Topics - Custom modules and tools