Counting visitors…
Browse all docs
Start · 9Find your path through RunifoldLearn Runifold in 45 minutesUnderstand the complete Runifold platformYour first trustworthy runChoose the right execution APIChoose crates and Cargo featuresBuild common Runifold applicationsRunifold frequently asked questionsTroubleshoot Runifold applications
Execution kernel · 7Understand RunContextCoordinate external effects safelyBound work with budgets and cancellationHandle errors and retries safelyEvents, journals, and execution evidenceDesign capability-safe executionRecover safely from checkpoints
Models & providers · 7Route across models without duplicate outputChoose and configure a providerUse the provider-neutral model protocolBuild on the Provider Runtime contractUse OpenAI control-plane and Realtime APIsTest and benchmark provider adaptersSet up OpenAI, Anthropic, Gemini, and Ollama
Agents · 7Build and configure an AgentGive an Agent typed toolsAdd conversations and semantic memoryDelegate to child Agents safelyReturn structured Rust valuesStream without losing semanticsGround an Agent with retrieval
Durable workflows · 7Compose deterministic workflowsMake workflows durableOperate durable workflow workersCoordinate timers, signals, and durable waitsRun multi-tenant workflow infrastructureRun parallel branches and safe racesVersion and evolve durable workflows
Integrations · 7Connect through MCPChoose stores and persistence boundariesExpose durable work through MCP TasksBuild and evaluate retrieval pipelinesUse MCP Resources, Prompts, and SamplingCache MCP responses without crossing authorityDeploy Runifold in a Rust web service
Quality & operations · 10Test without the networkEvaluate quality and prevent regressionsObserve the complete run treeRun safely in browsers and at the edgeRead reliability claims preciselyRun reproducible evaluations in CIOperate Runifold with SLOsGovern Task retention and deletionArchive audit evidence to S3-compatible WORM storageManage compatibility and trusted releases
Docs/Production
NEW TO RUNIFOLD?Build the complete mental model in 45 minutes
Production

Observe the complete run tree

Keep execution journals separate from model transcripts and export GenAI telemetry through OpenTelemetry.

Practical guide·16 min

Three kinds of history

Keep three records separate:

  • the transcript is model-visible conversation state;
  • the journal is the runtime's semantic execution record;
  • telemetry is an operational projection for traces, metrics, and logs.

They have different retention, privacy, and correctness requirements. Reusing one as another creates accidental data exposure and weak recovery.

Structured journals

Journal stable domain events with run and parent IDs, phase, counters, and safe metadata. Consumers should tolerate new event variants and process events idempotently.

The journal is useful for audit and recovery, but it is not a dump of prompts, chain-of-thought, or provider payloads.

OpenTelemetry

Enable the otel feature to export GenAI-oriented traces and metrics through OpenTelemetry. Carry trace context across model, tool, child-Agent, and workflow boundaries.

Set service and deployment resource attributes at startup. Use sampling and attribute allowlists before data reaches an exporter.

Enable instrumentation

Enable both your provider and the otel feature. Runifold emits through the global OpenTelemetry providers; your application still owns SDK, sampler, resource, exporter, batching, and shutdown configuration.

Cargo.toml
[dependencies]
runifold = { version = "=0.9.0", features = ["otel"] }
runifold-providers = { version = "=0.9.0", features = ["openai"] }
use runifold::ProviderModelExt;
use runifold_providers::openai::OpenAiClient;
 
let runtime = OpenAiClient::from_api_key(std::env::var("OPENAI_API_KEY")?)?
    .runtime("gpt-5")?
    .with_otel();
let agent = runtime
    .agent("support-triage")
    .system("Classify the request and explain the decision.")
    .build()?;
 
let outcome = agent.prompt("My order has not arrived", &run).await?;
println!("run={} tokens={:?}", run.run_id(), outcome.usage);

Initialize the OpenTelemetry SDK before constructing this runtime and flush the provider during graceful shutdown. Create the runtime once and clone it into handlers; rebuilding it per request also resets shared circuit-breaker health.

For custom model and journal wiring, construct one OtelRuntime, then use model(...) and journal(...) from the same instance so causal correlation is shared. Content capture and provider error-message capture are disabled by default; enabling them is a deliberate privacy decision.

Production signals

Track at least:

  • success, cancellation, deadline, and budget-exhaustion rates;
  • latency by provider, model, Agent, and callable;
  • tokens, cost, turns, tool calls, and delegations;
  • retry, circuit-breaker, lease-recovery, and ambiguous-effect counts;
  • structured-output and retrieval-quality failures.

Keep tenant IDs out of high-cardinality metric labels. Use traces or controlled logs for per-run investigation.

Investigation workflow

When a request fails, start from the application request ID and Run ID. Locate the terminal Run event, then follow child Runs to model and callable attempts. Use the trace to answer where time was spent, the journal to answer which semantic transitions committed, and the transcript only when authorized to inspect model-visible content.

SymptomFirst signalNext check
slow first tokenmodel span latencyroute health, queue wait, provider latency
high total latencychild span waterfalltool/retrieval latency and retry count
unexpected costusage eventsturns, fallback routes, losing race reservations
repeated writeEffect journal stateidempotency key and reconciliation evidence
missing traceSDK/exporter healthglobal provider initialized before runtime
cardinality spikemetric attributesremove Run, request, tenant, and document IDs

Safe production defaults

Keep model content disabled, sample at the SDK boundary, allowlist attributes, and set retention separately for traces and journals. Alert on rates and percentiles, not individual tenant labels. Test exporter outage: telemetry backpressure must be bounded and must not silently change execution correctness.

Inspect runs without executing effects

Runifold 0.9 ships a separate read-only operations CLI. It reads exported events or canonical SQLite/PostgreSQL journals without loading Provider credentials, running migrations, or re-executing Effects:

cargo install runifold-cli --version 0.9.0 --locked
runifold run inspect --events events.json
runifold run tail --events events.json --limit 50
runifold run inspect --sqlite runifold.db --run-id 019...
runifold run replay --events events.json --output replay-evidence.json
runifold checkpoint diff before.json after.json
runifold budget explain budget.json usage.json
runifold doctor --events events.json

Checkpoint diffs report JSON Pointers and change kinds without printing values. Replay produces causal evidence only; actual Effect execution remains behind the runtime's explicit recovery policy. Use doctor first when an exported run appears incomplete, then follow its normalized finding into traces and the durable journal.