Skip to content

Runtime Architecture

The Runra Runtime is the open-source orchestration layer that connects AI agents to sandbox infrastructure. It provides a unified interface for agents to create sandboxes, execute code, and receive structured observability events — regardless of which agent, LLM, or sandbox provider you use.

Runra Runtime is built on three principles:

  1. Agent-agnostic: Works with any AI coding agent (Claude Code, Codex, OpenCode, custom).
  2. Provider-pluggable: Swap sandbox providers, LLM backends, and observability exporters without changing agent code.
  3. Event-driven: All operations emit typed events that flow to your observability stack.
┌─────────────────────────────────────────┐
│ Your Application │
│ (Next.js, Express, CLI tool, Worker) │
└───────────────┬─────────────────────────┘
┌───────────────▼─────────────────────────┐
│ Agent Adapters │
│ Claude Code │ Codex │ OpenCode │ Custom│
└───────────────┬─────────────────────────┘
┌───────────────▼─────────────────────────┐
│ Runra Runtime │
│ ┌─────────────────────────────────────┐ │
│ │ Orchestrator │ │
│ │ - Sandbox lifecycle management │ │
│ │ - Tool execution dispatch │ │
│ │ - Event bus │ │
│ └─────────────────────────────────────┘ │
│ ┌──────────────┬──────────────────────┐ │
│ │ Sandbox │ Observability │ │
│ │ Provider │ Exporters │ │
│ │ Interface │ Interface │ │
│ └──────────────┴──────────────────────┘ │
└───────────────┬─────────────────────────┘
┌───────────────▼─────────────────────────┐
│ Sandbox Providers │
│ Runra Sandbox │ CubeSandbox │ Docker │
│ E2B │ Custom │
└─────────────────────────────────────────┘

Your application code. This is where you instantiate the Runra runtime, configure providers, and start agents. The runtime exposes a simple top-level API:

import { Runra } from "@runra/runtime";
const runra = new Runra({
sandbox: { provider: "runra-sandbox", apiKey: "..." },
agent: { provider: "claude-code", model: "claude-sonnet-4-20250514" },
observability: { provider: "axiom", token: "..." },
});
await runra.start({ prompt: "Build a React todo app" });

Agent adapters translate between Runra’s tool interface and each agent’s native protocol. See Agent Adapters for details.

The core runtime manages:

  • Sandbox lifecycle: Create, pause, resume, terminate sandboxes through the configured sandbox provider.
  • Tool dispatch: When an agent requests a tool (e.g., bash, edit, read), the orchestrator routes it to the sandbox.
  • Event bus: Every operation (sandbox created, command executed, file written) emits typed events.
  • Concurrency: Manages parallel sandbox operations with configurable limits.

The runtime defines two key interfaces:

interface SandboxProvider {
create(config: SandboxConfig): Promise<SandboxHandle>;
get(id: string): Promise<SandboxHandle>;
list(opts?: ListOptions): Promise<SandboxHandle[]>;
pause(id: string): Promise<void>;
resume(id: string): Promise<void>;
terminate(id: string): Promise<void>;
execute(id: string, command: string, opts?: ExecuteOptions): Promise<ExecuteResult>;
writeFile(id: string, path: string, content: string): Promise<void>;
readFile(id: string, path: string): Promise<string>;
}
interface ObservabilityExporter {
export(events: RuntimeEvent[]): Promise<void>;
flush(): Promise<void>;
}

Any implementation of these interfaces can plug into the runtime. See Sandbox Providers and Observability for built-in and custom implementations.

All runtime operations emit typed events. Events flow from the orchestrator to all configured observability exporters.

Every event has a common envelope:

interface RuntimeEvent {
id: string; // UUID
timestamp: string; // ISO 8601
type: string; // Event type discriminator
sandboxId: string; // Which sandbox
runId: string; // Which agent run
data: Record<string, unknown>; // Type-specific payload
}
Event TypeDescriptionKey Data Fields
sandbox.createdSandbox provisionedimage, resources
sandbox.pausedSandbox pausedruntimeDurationMs
sandbox.resumedSandbox resumedpausedDurationMs
sandbox.terminatedSandbox destroyedtotalRuntimeMs
exec.completedCommand finishedcommand, exitCode, stdout, stderr, durationMs
exec.streamedCommand output chunkstream, content
file.createdFile writtenpath, sizeBytes
file.readFile readpath
file.deletedFile removedpath
port.exposedPort exposedport, url
port.closedPort closedport
agent.thinkingAgent reasoningthought
agent.tool_callTool requesttool, args
agent.tool_resultTool responsetool, result
cost.runtimeResource usage costcost, durationMs

Every component is pluggable. See the dedicated pages:

A typical agent run through the runtime:

1. Application calls runra.start({ prompt: "..." })
2. Orchestrator creates a sandbox via SandboxProvider
3. Agent adapter starts the agent with the prompt
4. Agent requests a tool (e.g., "run bash command")
5. Orchestrator dispatches to SandboxProvider.execute()
6. Result returned to agent
7. Agent processes output, requests next tool
8. Events emitted to ObservabilityExporters
9. Agent completes; sandbox paused or terminated