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

Handle errors and retries safely

Distinguish build failures, execution failures, retry-safe transport errors, and ambiguous side effects.

Practical guide·14 min

Error layers

Handle failures at the boundary that understands them:

LayerExamplesTypical response
Buildduplicate tool, invalid policyfail at startup
Modelrate limit, bad responseroute or retry by classification
Toolinvalid input, denied capabilityreturn a safe tool result
Rundeadline, budget, cancellationterminate the run tree
Workflowlease loss, stale revisionrecover from durable state

Do not flatten all of these into one string. Preserve the typed source and a safe message for the caller.

Inspect the typed cause

Agent::prompt_text returns AgentError. Match the layer before converting it to your application's HTTP, queue, or CLI error. The wildcard keeps the code forward-compatible because public error enums are non-exhaustive.

use runifold::{Agent, AgentError};
 
async fn answer(agent: &Agent, prompt: &str) -> anyhow::Result<String> {
    match agent.prompt_text(prompt).await {
        Ok(text) => Ok(text),
        Err(AgentError::Model(error)) => {
            eprintln!(
                "model kind={:?} retry_safety={:?} provider={:?}",
                error.kind, error.retry_safety, error.provider
            );
            Err(error.into())
        }
        Err(AgentError::Budget(error)) => {
            eprintln!("budget stopped the run: {error}");
            Err(error.into())
        }
        Err(AgentError::AmbiguousCheckpoint { turn }) => {
            anyhow::bail!("turn {turn} may already have produced an external result")
        }
        Err(error) => Err(error.into()),
    }
}

Expose a stable application error code to callers, but retain the typed source and Run ID in controlled diagnostics. Never send provider bodies, prompts, tool arguments, or credentials back as an error detail.

Safe retry

Retry only when the adapter classifies the failure as safe. A connection error before a request was sent differs from a timeout after the provider may have accepted and billed it.

Use capped exponential backoff with jitter. Retry budgets should be smaller than the request's overall deadline and resource budget.

Circuit breakers

runtime() composes conservative retry and circuit-breaker defaults around a provider. Inspect route_health() for operational status and route away from a failing edge before every request pays the full timeout.

Circuit breakers protect capacity; they do not prove that a provider is healthy. Combine them with health checks and outcome metrics.

Ambiguous effects

Never blindly retry a non-idempotent external effect. Use an idempotency key when the destination supports one, or Runifold's write-ahead effect boundary to record intent before execution.

If completion cannot be proven, mark the effect ambiguous and require reconciliation. “Probably failed” is not safe enough for payments, email, or destructive tools.

Retry decision table

ObservationRetry automatically?Action
local validation or unsupported featurenofix input, feature policy, or model selection
cancelled or deadline exceedednoreturn the terminal state; a caller may start new work
transport failure classified safewithin policyuse capped backoff and remaining deadline
provider rate limit classified safewithin policyhonor provider delay and global budget
malformed provider protocolnormally nocapture safe diagnostics and route away
tool input rejectedno identical retrylet the model correct arguments within turn budget
idempotent write with confirmed keypolicy-dependentreplay through the Effect boundary
non-idempotent or ambiguous writenoreconcile with the destination first

Operational debugging sequence

  1. Find the root Run ID and terminal error kind.
  2. Check cancellation, deadline, and budget before investigating the provider.
  3. Inspect runtime.route_health() for open or half-open model routes.
  4. Correlate the failed attempt with journal events and telemetry without exposing content.
  5. Confirm whether an Effect intent, completion, or ambiguous state was persisted.
  6. Retry only through the same policy boundary; do not add an ad-hoc loop around prompt_text.