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/Models and providers
NEW TO RUNIFOLD?Build the complete mental model in 45 minutes
Models and providers

Build on the Provider Runtime contract

Compose provider identity, safe retry, circuit breaking, capability evidence, compatible endpoints, and adapter verification.

Practical guide·14 min

Provider responsibilities

A provider adapter has two core responsibilities: implement Model with a lossless canonical stream, and implement ProviderModel with a stable provider namespace. It must translate request content, response lifecycle, tool calls, reasoning, usage, warnings, typed errors, deadlines, cancellation, and retry safety.

It must not reimplement Agent loops, workflow recovery, budgets, capabilities, effects, or observability policy. Those layers remain provider-neutral.

Runtime composition

ProviderModelExt adds provider-qualified Agent construction, a resilient single-route builder, and ProviderRuntime. The Runtime wraps the canonical stream with same-route retry and an independent circuit breaker while remaining a Model.

Because the result is still a model boundary, it can be instrumented by OtelModel, placed behind ModelRouter, called directly, used by an Agent, or executed inside an AgentStep.

Adapter-owned safe defaults

In 0.9, each concrete adapter publishes a reviewed ProviderRuntimeProfile through ProviderModel::runtime_profile; the ordinary .runtime(model) path applies it automatically. Delivery mode, request options, retry permission, circuit policy and capability behavior therefore follow the actual protocol instead of one facade-wide guess.

Only errors marked retry-safe are eligible. Unknown, unsafe, cancellation and post-commit stream failures do not retry. Override the complete profile only through runtime_with_profile and only with deployment-specific evidence.

Choose a workload preset

use runifold::{BatchProfile, InteractiveProfile, ProviderModelExt};
use runifold_providers::openai::OpenAiClient;
 
let client = OpenAiClient::from_api_key(std::env::var("OPENAI_API_KEY")?)?;
let interactive = client
    .clone()
    .runtime_with_preset("gpt-5", InteractiveProfile)?;
let batch = client.runtime_with_preset("gpt-5", BatchProfile)?;
 
let audit = batch.capability_audit().await?;
for item in audit.review_required() {
    println!("{}: {}", item.feature, item.recommendation);
}

ProductionProfile keeps the adapter recommendation, InteractiveProfile commits streamed events promptly, and BatchProfile validates a complete response before Router commit. A capability audit is deployment evidence; it does not guess that an unknown model supports a feature.

Compatible endpoints

Protocol compatibility is not capability equivalence. An OpenAI-compatible endpoint may accept the same JSON shape while differing in streaming, structured output, usage, reasoning, error bodies, or cancellation.

Use a custom validated endpoint and stable provider identity. Keep credentials server-side. Record the exact model, endpoint family, enabled feature policy, and verified behaviors as part of deployment configuration.

Adapter acceptance

A provider is production-ready only when deterministic evidence covers request encoding, fragmented streaming, terminal completion, tool arguments, typed errors, retry safety, timeout, cancellation, truncation, credential redaction, concurrency isolation, and Runtime compatibility.

runifold-provider-testkit supplies cassette, conformance, and benchmark boundaries. Live tests complement protocol tests; they do not replace failure injection or fixed assertions.

Construct and share one runtime

use runifold::{ProductionProfile, ProviderModelExt};
use runifold_providers::openai::OpenAiClient;
 
let runtime = OpenAiClient::from_api_key(std::env::var("OPENAI_API_KEY")?)?
    .runtime_with_preset("gpt-5", ProductionProfile)?;
let health = runtime.route_health();
println!("initial routes: {health:?}");
 
let agent = runtime
    .agent("assistant")
    .system("Answer precisely and expose uncertainty.")
    .build()?;
let answer = agent.prompt_text("Why use a shared runtime?").await?;

Create ProviderRuntime once at service startup and clone it into handlers. Clones share retry and circuit-breaker state. Calling .runtime(...) for every request creates independent health state and defeats coordinated circuit protection. Prefer adapter defaults plus a standard preset; use .runtime_with_profile(...) only at an explicit reviewed override boundary.