Skip to content

Runtime

The everruns-runtime crate runs an Everruns 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).

Terminal window
cargo add everruns-runtime

The crate also depends on everruns-core for shared types (capabilities, drivers, models):

Terminal window
cargo add everruns-core

Quickstart

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.

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:

Terminal window
cargo add everruns-openai

Then 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:

Terminal window
export OPENAI_API_KEY=sk-...
cargo run -p everruns-runtime --example openai_runtime

Inspect 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:

TraitBacks
RuntimeHarnessStoreHarness definitions
RuntimeAgentStoreAgent configurations
RuntimeSessionStoreSessions
RuntimeMessageStoreMessage history
RuntimeFileStoreSession files
RuntimeProviderStoreLLM providers
EventBusEmitted 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:

TypeBacks
LocalSessionTaskRegistrySession tasks and their message channel
LocalScheduleStoreSession schedules (with a local metadata JSON bag)
LocalPlatformStoreSubagent-critical platform store core
LocalProfileLocal data dir, workspace, and identity defaults
LocalBackendsComposes 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.

Terminal window
cargo add everruns-local
use 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?;

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:

Terminal window
cargo add everruns-runtime --features mcp-stdio

Built with the runtime

  • yolop — a minimal terminal coding agent built on everruns-runtime (codex/claude-code in spirit). It started as the coding-cli example below, promoted into a standalone, releasable project, and is where active development happens: interactive TUI, real-filesystem tools, a bash tool, 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
    # or
    cargo 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 on RealDiskFileStore, a custom bash tool, 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:

Terminal window
cargo run -p everruns-runtime --example in_process_runtime
cargo run -p everruns-runtime --example inspect_context
cargo run -p everruns-runtime --example openai_runtime # needs OPENAI_API_KEY
cargo run --manifest-path examples/coding-cli/Cargo.toml
cargo run --manifest-path examples/weekend-concierge-host/Cargo.toml

See 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.