Skip to content

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

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.

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:

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)
LocalScheduleRunnerIn-process execution of due local schedules
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?;

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:

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.