Kernel Philosophy¶
The Amplifier kernel (amplifier-core) follows a philosophy inspired by the Linux kernel: provide mechanisms, not policy.
Core Tenets¶
1. Mechanism, Not Policy¶
The kernel exposes capabilities and stable contracts. Decisions about behavior belong outside the kernel.
| Kernel Does (Mechanism) | Kernel Doesn't (Policy) |
|---|---|
| Load modules | Choose which modules |
| Emit events | Decide what to log |
| Validate contracts | Format output |
| Provide hooks | Select providers |
| Manage sessions | Schedule execution |
Litmus test: If two teams could want different behavior, it's policy → keep it out of kernel.
2. Small, Stable, and Boring¶
The kernel is intentionally minimal (~2,600 lines) and changes rarely.
- Small: Can be audited in an afternoon
- Stable: Backward compatibility is sacred
- Boring: No clever tricks, no surprises
3. Don't Break Modules¶
Backward compatibility in kernel interfaces is sacred.
- Additive evolution only
- Clear deprecation with migration paths
- Long sunset periods for changes
4. Extensibility Through Composition¶
New behavior comes from plugging in different modules, not from toggleing flags.
# Not this (configuration explosion)
session = Session(
use_streaming=True,
enable_approval=True,
log_level="debug",
...
)
# This (composition)
mount_plan = {
"orchestrator": "loop-streaming",
"hooks": ["hooks-approval", "hooks-logging"]
}
What Belongs in the Kernel¶
Kernel Responsibilities (Mechanisms)¶
- Stable contracts: Protocol definitions for modules
- Lifecycle coordination: Load, unload, mount, unmount
- Event emission: Canonical events for observability
- Capability enforcement: Permission checks, approvals
- Minimal context: Session IDs, basic state
Kernel Non-Goals (Policies)¶
- Orchestration strategies
- Provider/model selection
- Tool behavior or domain rules
- Output formatting
- Logging destinations
- Business defaults
Invariants¶
These properties must always hold:
- Backward compatibility: Existing modules work across kernel updates
- Non-interference: Faulty modules can't crash the kernel
- Bounded side-effects: Kernel doesn't make irreversible external changes
- Deterministic semantics: Same inputs = same behavior
- Minimal dependencies: No transitive dependency sprawl
Evolution Rules¶
1. Additive First¶
Extend contracts without breaking them. Prefer optional capabilities.
# Good: Optional new parameter
async def complete(self, request: ChatRequest, **kwargs) -> ChatResponse:
thinking = kwargs.get("thinking", None) # New, optional
...
# Bad: Required new parameter
async def complete(self, request: ChatRequest, thinking: ThinkingConfig) -> ChatResponse:
... # Breaks existing providers
2. Two-Implementation Rule¶
Don't promote a concept into kernel until ≥2 independent modules converge on the need.
Module A needs X → Prototype X in Module A
Module B needs X → Prototype X in Module B
A and B converge → Extract X to kernel
3. Spec Before Code¶
Kernel changes begin with a short spec:
- Purpose
- Alternatives considered
- Impact on invariants
- Test strategy
- Rollback plan
4. Complexity Budget¶
Each kernel change must justify its complexity. Additions should retire equivalent complexity elsewhere.
Interface Guidance¶
Small and Sharp¶
Prefer few, precise operations over broad, do-everything calls.
# Good: Focused operations
coordinator.mount("providers", provider, name="anthropic")
coordinator.unmount("providers", "anthropic")
# Bad: Swiss army knife
coordinator.manage("providers", operation="mount", module=provider, name="anthropic", options={...})
Stable Schemas¶
Version any data shapes crossing kernel boundaries.
class ChatRequest(BaseModel):
"""Versioned request format."""
schema_version: str = "1.0"
messages: list[Message]
# New fields are optional with defaults
temperature: float = 1.0 # Added in 1.1
Explicit Errors¶
Fail closed with actionable diagnostics. No silent fallbacks.
# Good: Clear error
raise ModuleNotFoundError(
f"Module '{module_id}' not found. "
f"Available modules: {available}. "
f"Check your mount plan configuration."
)
# Bad: Silent fallback
if module not found:
use_default_module() # Hidden behavior
Security Posture¶
Deny by Default¶
Kernel offers no ambient authority. Modules must request capabilities explicitly.
# Module must explicitly request
coordinator.register_capability("file_system", implementation)
# And explicitly use
fs = coordinator.get_capability("file_system")
Sandbox Boundaries¶
All calls across boundaries are validated, attributed, and observable.
# Every tool call is observable
await coordinator.hooks.emit("tool:pre", {
"tool_name": tool.name,
"input": sanitized_input,
"session_id": session_id
})
Non-Interference¶
Module failures are isolated. The kernel stays up.
try:
result = await tool.execute(input)
except Exception as e:
# Log error, don't crash kernel
await coordinator.hooks.emit("tool:error", {"error": str(e)})
return ToolResult(success=False, error=str(e))
Red Flags¶
Watch for these anti-patterns:
| Anti-Pattern | Why It's Wrong |
|---|---|
| "Add a flag for this use case" | Flags accumulate; use modules |
| "Pass whole context for flexibility" | Violates minimal capability |
| "Break API now, adoption is small" | Sets bad precedent |
| "Add to kernel now, figure out policy later" | Policy will leak in |
| "It's only one more dependency" | Dependencies compound |
North Star¶
- Unshakeable center: A kernel so small and stable it can be maintained by one person
- Explosive edges: A flourishing ecosystem of competing modules
- Forever upgradeable: Ship improvements weekly at edges, kernel updates are rare and boring
References¶
- → KERNEL_PHILOSOPHY.md - Complete philosophy document
- → DESIGN_PHILOSOPHY.md - Design principles