Runtime
everruns-runtime is the agentic runtime — the entrypoint to the Everruns agentic framework. It runs an agent harness entirely inside your own Rust process. There is no PostgreSQL, no control-plane server, and no worker boundary — just the harness, your capabilities, and your code.
It is the Rust-native counterpart to the SDKs: where the SDKs talk to a running Everruns server over HTTP, the runtime is the engine, linked straight into your binary.
Use the runtime when you want to:
- Run a harness in-process with no external services
- Register your own capabilities, drivers, and tools
- Provide your own backend stores (files, messages, sessions, …)
- Inspect the assembled turn context before execution
It ships in-memory by default, so the smallest useful host is a single build().await? away.
Install
Requires Rust 1.94+ (edition 2024).
cargo add everruns-runtimeThe crate also depends on everruns-core for shared types (capabilities, drivers, models):
cargo add everruns-coreQuickstart
Build an in-process runtime with an in-memory backend and a simulated LLM, then run a turn:
use everruns_core::{ CapabilityRegistry, DriverId, DriverRegistry, PlatformDefinition, ResolvedModel,};use everruns_core::llmsim_driver::LlmSimConfig;use everruns_runtime::InProcessRuntimeBuilder;
let platform = PlatformDefinition::new(CapabilityRegistry::new(), DriverRegistry::new());
let runtime = InProcessRuntimeBuilder::new() .platform_definition(platform) .llm_sim(LlmSimConfig::fixed("hello from everruns-runtime")) .default_model(ResolvedModel { model: "llmsim-model".into(), provider_type: DriverId::LlmSim, api_key: Some("fake-key".into()), base_url: None, provider_metadata: None, }) // .capability(...) // .backends(...) // .harness(...) // .session(...) .build() .await?;The quickstart uses the built-in llmsim driver for deterministic, offline runs. To talk to a live provider, register that provider’s driver and point default_model at it — see Talk to OpenAI below.
Capability registry
InProcessRuntimeBuilder::new() includes a runtime-safe built-in capability
registry by default. That registry contains capabilities that work with the
runtime’s in-process services, such as session files, session storage, egress,
prompt helpers, guardrails, and tool-search helpers.
When you call .platform_definition(platform), the supplied platform replaces
that default. Use CapabilityRegistry::runtime_builtins() as the starting point
when you want the default runtime catalog plus custom capabilities:
use everruns_core::{CapabilityRegistry, DriverRegistry, PlatformDefinition};
let mut capabilities = CapabilityRegistry::runtime_builtins();capabilities.register(MyCapability);
let platform = PlatformDefinition::new(capabilities, DriverRegistry::new());Hosted Everruns product capabilities and capabilities that require optional host services, such as platform management, session tasks, schedules, session SQL databases, provider credentials, or knowledge stores, are not in the runtime default. Register them explicitly only when your host provides the required services.
Talk to OpenAI
A real provider needs two things, not one: the provider’s driver must be registered in the DriverRegistry, and default_model must select it. Setting default_model alone is not enough — the runtime resolves provider_type against the registry, so an unregistered driver fails at turn time.
Add the provider crate:
cargo add everruns-openaiThen register its driver and select it as the default model:
use everruns_core::driver_registry::DriverRegistry;use everruns_core::{CapabilityRegistry, DriverId, PlatformDefinition, ResolvedModel};use everruns_runtime::InProcessRuntimeBuilder;
// 1. Register the OpenAI driver so `DriverId::OpenAI` can be resolved.let mut drivers = DriverRegistry::new();everruns_openai::register_driver(&mut drivers);
// 2. Build the platform from that registry.let platform = PlatformDefinition::new(CapabilityRegistry::new(), drivers);
// 3. Point the runtime's default model at OpenAI.let runtime = InProcessRuntimeBuilder::new() .platform_definition(platform) .default_model(ResolvedModel { model: "gpt-5.5".into(), provider_type: DriverId::OpenAI, api_key: Some(std::env::var("OPENAI_API_KEY")?), base_url: None, provider_metadata: None, }) .single_session(|s| { s.harness("assistant", "You are a concise, helpful assistant.") .agent("assistant-agent", "Answer in one short sentence.") .session_title("OpenAI Session") }) .build() .await?;
let session_id = runtime.default_session_id().expect("single_session id");let result = runtime .run_text_turn(session_id, "Say hello from everruns-runtime in one sentence.") .await?;println!("{}", result.response);The same pattern works for any provider crate — swap everruns-openai for everruns-anthropic (DriverId::Anthropic), everruns-openrouter (DriverId::OpenRouter), and so on, matching the crate to its DriverId. To reach an OpenAI-compatible endpoint (a local gateway, Ollama, …), set base_url and pick the DriverId that matches the API the server speaks: DriverId::OpenAI for the Responses API, or DriverId::OpenAICompletions for the Chat Completions API.
A complete, runnable version lives at crates/runtime/examples/openai_runtime.rs:
export OPENAI_API_KEY=sk-...cargo run -p everruns-runtime --example openai_runtimeInspect the turn context
load_context(session_id) returns the exact merged context the reason phase will use — before the first turn or after messages already exist:
let context = runtime.load_context(session_id).await?;println!("messages = {}", context.messages.len());println!("model = {}", context.runtime_agent.model);println!("tools = {}", context.runtime_agent.tools.len());The context bundles the harness chain, optional agent, session, filtered message history, resolved model, and the assembled RuntimeAgent. With no messages yet, context.messages is empty and model/locale resolution falls back to merged harness, agent, session, and platform defaults.
The harness’s base system prompt is optional. Pass an empty string (or, when constructing a Harness directly, leave system_prompt as None) for a harness that only contributes capabilities or MCP servers. The prompt-composition layer trims empty fragments, so runtime_agent.system_prompt is assembled purely from whatever layers — parent harness, agent, session, capabilities — actually contribute text, and may be empty if none do.
Execute-time hosts use everruns_core::assemble_turn_context(...) while inspection uses everruns_core::inspect_turn_context(...); both share the same assembly logic, so in-process and worker-backed behavior stay aligned.
Custom backends
The runtime ships in-memory defaults, but public extension traits let you supply your own stores:
| Trait | Backs |
|---|---|
RuntimeHarnessStore | Harness definitions |
RuntimeAgentStore | Agent configurations |
RuntimeSessionStore | Sessions |
RuntimeMessageStore | Message history |
RuntimeFileStore | Session files |
RuntimeProviderStore | LLM providers |
EventBus | Emitted events (extends EventEmitter) |
Pass them through RuntimeBackends on the builder; any store you don’t override stays in-memory:
use everruns_runtime::{InProcessRuntimeBuilder, RuntimeBackends};
let runtime = InProcessRuntimeBuilder::new() .backends( RuntimeBackends::in_memory() .with_file_store(my_file_store) .with_message_store(my_message_store) .with_event_bus(my_event_bus), ) .build() .await?;The default in-memory EventBus retains emitted events for InProcessRuntime::events(); production buses inherit the default collected_events and return an empty Vec.
Local backends
In-memory stores vanish when the process exits. For an embedded, single-process host that should survive restarts — a terminal coding agent, a personal agent, a long-lived CLI — the companion everruns-local crate provides SQLite-backed, file-persisted implementations of the optional host-backend slots:
| Type | Backs |
|---|---|
LocalSessionTaskRegistry | Session tasks and their message channel |
LocalScheduleStore | Session schedules (with a local metadata JSON bag) |
LocalScheduleRunner | In-process execution of due local schedules |
LocalPlatformStore | Subagent-critical platform store core |
LocalProfile | Local data dir, workspace, and identity defaults |
LocalBackends | Composes the above into RuntimeBackends |
Task and message state persists to a SQLite file, so a freshly-spawned process can read, continue, and inspect work an earlier process started.
cargo add everruns-localuse everruns_local::{LocalBackends, LocalProfile};use everruns_runtime::{InProcessRuntimeBuilder, RuntimeBackends};
// LocalProfile stores plain filesystem paths and does not expand a leading// `~`; pass an absolute path your application owns. Its SQLite file is derived// from the data dir.let profile = LocalProfile::new("/var/lib/everruns") .with_workspace_root("/var/lib/everruns/workspace");
// Layer the local stores over a set of runtime backends. Any store (or event// bus) you set on `RuntimeBackends` is preserved.let local = LocalBackends::new(profile, RuntimeBackends::in_memory())?;
let runtime = InProcessRuntimeBuilder::new() .platform_definition(platform) .backends(local.runtime_backends.clone()) .build() .await?;If the embedded platform enables scheduled monitors, persistence alone is not
enough: start the local executor with the same LocalSessionRunner used to
drive live sessions. If that runner cannot deliver to every session in the
organization, implement routable_session_ids with a current route snapshot;
an empty snapshot claims no schedules. Retain the handle for the host lifetime
and shut it down gracefully:
let schedule_runner = local.start_schedule_runner(session_runner.clone())?;let local = local.with_platform_runner(session_runner);
// During host shutdown:schedule_runner.shutdown().await?;The runner atomically claims due SQLite records only for routable sessions,
recovers stale claims after an interrupted process, advances timezone-aware
recurring schedules, and retries failed send_message delivery after the
configured claim timeout. Delivery is at-least-once across the narrow crash
window between the host accepting a message and SQLite recording its
completion.
LocalBackends only adds the local stores — it preserves a caller-supplied event bus (via RuntimeBackends) and session file-system factory (via the platform’s PlatformDefinition), so it composes with the custom backends above rather than replacing them. See docs.rs/everruns-local for the full API.
Local MCP servers
MCP server tools are first-class runtime tools. Local-process (stdio) MCP servers are gated behind the mcp-stdio feature, off by default so the hosted server/worker never compile stdio in:
cargo add everruns-runtime --features mcp-stdioBuilt with the runtime
-
yolop — a minimal terminal coding agent built on
everruns-runtime(codex/claude-code in spirit). It started as thecoding-cliexample below, promoted into a standalone, releasable project, and is where active development happens: interactive TUI, real-filesystem tools, abashtool, multi-provider LLMs (OpenAI, Anthropic, Gemini, OpenRouter, Ollama), MCP servers (stdio + HTTP), resumable sessions, and Zed editor integration over ACP.Terminal window brew install everruns/tap/yolop# orcargo install yolop --locked -
examples/coding-cli— the in-tree reference embedder for the public crate: a single-binary coding agent with a ratatui TUI, real-filesystem tools onRealDiskFileStore, a custombashtool, skills, and infinity-context trimming. It lives at the workspace edge and depends on the public crate exactly the way an external embedder would. -
examples/weekend-concierge-host— a root-level host app that defines its own capability, private tool data, seeded files, and an in-process turn loop.
Run the in-tree examples:
cargo run -p everruns-runtime --example in_process_runtimecargo run -p everruns-runtime --example inspect_contextcargo run -p everruns-runtime --example openai_runtime # needs OPENAI_API_KEYcargo run --manifest-path examples/coding-cli/Cargo.tomlcargo run --manifest-path examples/weekend-concierge-host/Cargo.tomlSee also
- Embedding Everruns — compose your own
PlatformDefinition, server, and worker; the runtime is the in-process slice of that story. - SDKs — client libraries for talking to a running Everruns server over HTTP.
- Harnesses — the agent execution templates the runtime runs.
- Capabilities — the tools and behaviors you register on a harness.
- docs.rs/everruns-runtime — full API reference.