Skip to main content
The Runtime struct is the main entry point for the OneClaw Core Runtime. It owns all layer implementations (Security, Orchestrator, Memory, Event Bus, Tools) and manages the main event loop.

Struct Definition

pub struct Runtime {
    pub config: OneClawConfig,
    pub security: Box<dyn SecurityCore>,
    pub router: Box<dyn ModelRouter>,
    pub context_mgr: Box<dyn ContextManager>,
    pub chain: Box<dyn ChainExecutor>,
    pub memory: Box<dyn Memory>,
    pub event_bus: Box<dyn EventBus>,
    pub tool_registry: Arc<ToolRegistry>,
    pub metrics: Metrics,
    pub shutdown: Arc<AtomicBool>,
    pub provider: Option<Box<dyn Provider>>,
    pub embedding: Option<Box<dyn EmbeddingProvider>>,
}

Fields

config
OneClawConfig
The active configuration loaded from TOML or defaults
security
Box<dyn SecurityCore>
The security core implementation (Layer 0) - handles authorization, device pairing, and access control
router
Box<dyn ModelRouter>
The model router for LLM provider selection (Layer 1)
context_mgr
Box<dyn ContextManager>
The context manager for prompt enrichment (Layer 1)
chain
Box<dyn ChainExecutor>
The chain executor for multi-step pipelines (Layer 1)
memory
Box<dyn Memory>
The memory backend implementation (Layer 2) - SQLite or NoopMemory
event_bus
Box<dyn EventBus>
The event bus implementation (Layer 3) - for event-driven operations
tool_registry
Arc<ToolRegistry>
Tool registry (Layer 4) - manages all registered tools available to the agent
metrics
Metrics
Operational metrics with AtomicU64 counters for monitoring
shutdown
Arc<AtomicBool>
Shutdown flag - set by signal handler or “exit” command to gracefully stop the event loop
provider
Option<Box<dyn Provider>>
v1.5 sync Provider for LLM calls (None = offline/no API key)
embedding
Option<Box<dyn EmbeddingProvider>>
Embedding provider for vector search (None = disabled, FTS only)

Constructor Methods

with_defaults

Create runtime with all Noop implementations (for testing or bare boot).
pub fn with_defaults(config: OneClawConfig) -> Self
config
OneClawConfig
required
Configuration struct with runtime settings
return
Self
A new Runtime instance with Noop trait implementations
Example:
use oneclaw_core::config::OneClawConfig;
use oneclaw_core::runtime::Runtime;

let config = OneClawConfig::default_config();
let runtime = Runtime::with_defaults(config);
runtime.boot()?;

with_security

Create runtime with DefaultSecurity (production mode). Other layers remain Noop until configured.
pub fn with_security(
    config: OneClawConfig,
    workspace: impl Into<std::path::PathBuf>
) -> Self
config
OneClawConfig
required
Configuration struct with runtime settings
workspace
impl Into<std::path::PathBuf>
required
Workspace directory path for security constraints
return
Self
A new Runtime instance with DefaultSecurity enabled
Example:
use oneclaw_core::config::OneClawConfig;
use oneclaw_core::runtime::Runtime;
use std::env;

let config = OneClawConfig::default_config();
let workspace = env::current_dir()?;
let runtime = Runtime::with_security(config, workspace);
runtime.boot()?;

from_config

Create runtime from config using Registry to resolve all traits based on configuration.
pub fn from_config(
    config: OneClawConfig,
    workspace: impl Into<std::path::PathBuf>
) -> Result<Self>
config
OneClawConfig
required
Configuration struct - determines which implementations to use
workspace
impl Into<std::path::PathBuf>
required
Workspace directory path
return
Result<Self>
A new Runtime instance with all traits resolved from config, or an error if resolution fails
Example:
use oneclaw_core::config::OneClawConfig;
use oneclaw_core::runtime::Runtime;
use std::env;

let config = OneClawConfig::load("oneclaw.toml")?;
let workspace = env::current_dir()?;
let runtime = Runtime::from_config(config, workspace)?;
runtime.boot()?;

Key Methods

boot

Boot the runtime and initialize all 5 layers.
pub fn boot(&self) -> Result<()>
return
Result<()>
Ok if all layers initialized successfully, otherwise an error
Example:
let runtime = Runtime::with_defaults(config);
runtime.boot()?;
// Runtime is now ready

run

Run the main event loop with a single channel. Receives messages, processes through security + pipeline, and responds.
pub async fn run(&self, channel: &dyn Channel) -> Result<()>
channel
&dyn Channel
required
The communication channel to receive/send messages (e.g., CLI, Telegram, MQTT)
return
Result<()>
Ok when loop exits gracefully, error if channel fails critically
Example:
use oneclaw_core::channel::CliChannel;

let cli = CliChannel::new();
runtime.run(&cli).await?;

run_multi

Run the main event loop with multiple channels via ChannelManager. Polls all channels round-robin.
pub async fn run_multi(&self, manager: &ChannelManager) -> Result<()>
manager
&ChannelManager
required
Channel manager containing multiple active channels
return
Result<()>
Ok when loop exits gracefully, error if manager fails critically
Example:
use oneclaw_core::channel::ChannelManager;

let mut manager = ChannelManager::new();
manager.add(Box::new(cli_channel));
manager.add(Box::new(mqtt_channel));

runtime.run_multi(&manager).await?;

run_chain

Run a chain with the current runtime context (provider, memory, event bus, tools).
pub async fn run_chain(
    &self,
    chain: &Chain,
    input: &str
) -> Result<ChainResult>
chain
&Chain
required
The chain definition to execute
input
&str
required
Input text to pass to the first chain step
return
Result<ChainResult>
Chain execution result with output and metadata, or error
Example:
use oneclaw_core::orchestrator::Chain;

let chain = Chain::new("analyze-and-respond")
    .with_step("analyze", "Analyze the user's question")
    .with_step("respond", "Generate a helpful response");

let result = runtime.run_chain(&chain, "What is the weather?").await?;
println!("Chain output: {}", result.output);

with_async_event_bus

Replace the event bus with an AsyncEventBus for realtime events (opt-in for sub-10ms latency).
pub fn with_async_event_bus(
    &mut self,
    capacity: usize
) -> tokio::sync::broadcast::Sender<Event>
capacity
usize
required
Broadcast channel capacity (e.g., 256)
return
tokio::sync::broadcast::Sender<Event>
The broadcast sender - use sender.subscribe() to create receivers
Example:
let sender = runtime.with_async_event_bus(256);
let mut rx = sender.subscribe();

tokio::spawn(async move {
    while let Ok(event) = rx.recv().await {
        println!("Event: {:?}", event);
    }
});

Built-in Commands

The runtime processes these commands internally:
  • help - Show all available commands
  • status - Show agent status, uptime, and layer information
  • metrics - Show operational metrics (counters, latency)
  • health - Health check all 5 layers
  • pair - Generate device pairing code
  • verify CODE - Pair device with 6-digit code
  • devices - List all paired devices
  • unpair ID - Remove a paired device
  • tools - List registered tools
  • tool X k=v - Execute tool X with parameters
  • channels - List active channels
  • events - Show event bus status and recent events
  • providers - List LLM providers and status
  • remember X - Store X in memory
  • recall X - Search memory for X
  • ask Q - Ask AI a question
  • reload - Check config file for changes (report only)
  • exit/quit/q - Shut down the agent

Security Model

Only exit, help, pair, and verify are always-open commands. All other commands require security authorization first. The runtime checks:
  1. Rate limiting - Default 60 requests/minute
  2. Device pairing - Device must be paired via pair + verify
  3. Per-command authorization - Each command checks ActionKind + resource
See the Security docs for details.

Build docs developers (and LLMs) love