Why Traits?
OneClaw uses traits as contracts for each layer. This design decision provides several key benefits:Modularity
Swap implementations without changing other layers
Testability
Use noop implementations for isolated unit testing
Extensibility
Create custom implementations for domain-specific needs
Zero Dependencies
Core traits have no external dependencies
The Trait Hierarchy
Every layer follows the same pattern:Layer-by-Layer Trait Examples
L0: Security Trait
Fromsecurity/traits.rs:75:
NoopSecurity(security/traits.rs:96): Always grants accessDefaultSecurity(security/default.rs:19): Production deny-by-default security
L1: Orchestrator Traits
ModelRouter
Fromorchestrator/router.rs:36:
NoopRouter: Returns placeholderDefaultRouter: Maps complexity to provider/model
ChainExecutor
Fromorchestrator/chain.rs:183:
NoopChainExecutor(orchestrator/chain.rs:189): Returns input as outputDefaultChainExecutor(orchestrator/chain.rs:217): Executes steps sequentially
ContextManager
Fromorchestrator/context.rs:
NoopContextManager: Returns input unchangedDefaultContextManager: Enriches with memory and system state
L2: Memory Trait
Frommemory/traits.rs:110:
NoopMemory(memory/traits.rs:134): In-memory Vec (test only)SqliteMemory(memory/sqlite.rs): Production SQLite + FTS5 + vector
L3: Event Bus Trait
Fromevent_bus/traits.rs:71:
NoopEventBus(event_bus/traits.rs:93): Discards all eventsDefaultEventBus(event_bus/bus.rs): Sync queue-basedAsyncEventBus(event_bus/async_bus.rs): Tokio broadcast (opt-in)
L4: Tool Trait
Fromtool/traits.rs:59:
NoopTool(tool/traits.rs:69): Always succeeds- Built-in tools:
SystemInfoTool,FileWriteTool,NotifyTool(from oneclaw-tools crate)
L5: Channel Trait
Fromchannel/traits.rs:27:
NoopChannel(channel/traits.rs:38): Discards sends, never receivesCliChannel,TcpChannel,TelegramChannel,MqttChannel(from oneclaw-channels crate)
Noop Implementations
Every layer has a Noop implementation that does nothing (or minimal work). This serves several purposes:1. Testing Isolation
Test a single layer without dependencies:2. Graceful Degradation
OneClaw can boot with all Noop layers for testing: Fromruntime.rs:65:
3. Incremental Implementation
When building a new vertical (domain-specific application), you can:- Start with all Noop implementations
- Swap in real implementations one layer at a time
- Test each layer independently
Custom Implementations
The trait system allows domain-specific implementations without modifying core code.Example: Custom Security for Medical Devices
Example: Custom Memory for Time-Series Data
Example: Custom Channel for WebSocket
Trait Object vs Generic
OneClaw uses trait objects (Box<dyn Trait>) rather than generics for layer implementations.
Why Trait Objects?
- Runtime selection: Choose implementation based on config
- Smaller binary: One
Runtimetype instead ofRuntime<S1, M1, ...>,Runtime<S2, M2, ...>, etc. - Simpler API: Users don’t need to specify type parameters
- Virtual dispatch overhead: ~2ns per call (negligible)
- Heap allocation: Requires
Box<dyn>(acceptable for long-lived objects)
runtime.rs:29 for the full Runtime definition.
Registry Pattern
OneClaw uses a Registry to resolve trait implementations from configuration. Fromregistry.rs:
config/oneclaw.toml
runtime.rs:112, the runtime loads from config:
Send + Sync Requirements
All traits requireSend + Sync for thread-safety:
- Send: Can be transferred across thread boundaries
- Sync: Can be accessed from multiple threads via
&self
- Tokio async runtime (moves futures across threads)
- Shared access via
Arc<Runtime> - Parallel event processing
runtime.rs:857, the event loop runs on the tokio runtime:
Testing with Noop Traits
Fromruntime.rs:1097:
Design Principles Summary
1. Traits Define Contracts
1. Traits Define Contracts
Each layer’s trait specifies what it does, not how. Implementations provide the “how.”
2. Noop Implementations Always Exist
2. Noop Implementations Always Exist
Every trait has a minimal “do nothing” implementation for testing and graceful degradation.
3. Default Implementations Are Production-Ready
3. Default Implementations Are Production-Ready
Default implementations provide full functionality for standard use cases.
4. Custom Implementations Are Encouraged
4. Custom Implementations Are Encouraged
The trait system is designed for extension. Add domain-specific behavior without forking core.
5. Configuration Over Hardcoding
5. Configuration Over Hardcoding
The Registry pattern allows runtime selection of implementations based on config.
Next Steps
Layer Details
Deep dive into each layer’s trait
Security Model
SecurityCore trait in depth
Building Verticals
Create domain-specific applications
Testing Guide
Using Noop traits for testing