Skip to content
DocumentationBuild a durable workflow
On this page

Page resources

Open Markdownllms.txtView source

Last updated

This recipe follows the checked support-triage application, where a durable workflow records policy lookup before an agent can propose ticket escalation. The .one excerpt mirrors the current owning example; the smaller Rust result handling excerpts are illustrative end-product syntax.

1. Separate workflow decisions from activities

one 1

semantic example.support
    domain one.contracts@1
    workflow SupportTriageLifecycle@1
        accepts example.support#TriageRequest@1
        returns example.support#TriageResponse@1
        concurrency "support/request"
        retention 30d
        evidence support.request example.support#TriageRequest@1
        evidence support.policy example.support#TriageResponse@1

        activity lookup_policy
            operation example.support#Policy.Lookup@1
            effect replay safe
            maximum attempts 1
            owns cancellation true
            on accepted terminal
            on rejected terminal
            on unsupported terminal
            on unsatisfied terminal
            on cancelled terminal
            on pending approval terminal
            on defect terminal
            on outcome unknown terminal

The workflow declares durable coordination and exhaustively classifies every activity outcome. The read-only policy lookup is replay-safe and attempted at most once.

2. Write deterministic decisions

match lookup_policy(request).await {
    ActivityResult::Accepted(policy) => continue_with(policy),
    ActivityResult::Rejected(fault) => stop_rejected(fault),
    ActivityResult::PendingApproval(request) => suspend(request),
    ActivityResult::OutcomeUnknown(effect) => suspend_for_reconciliation(effect),
    ActivityResult::Cancelled => stop_cancelled(),
    other => stop_with_exact_disposition(other),
}

The workflow cannot read ambient time, randomness, network, filesystem, or secrets. Timers, signals, human decisions, activity outcomes, and provider observations arrive as retained events.

3. Reconcile an uncertain activity

match ctx.activity(escalate_ticket(request)).await {
    ActivityResult::Completed(ticket) => complete(ticket),
    ActivityResult::Rejected(reason) => return_to_operator(reason),
    ActivityResult::OutcomeUnknown(effect) => {
        ctx.suspend_for_reconciliation(effect).await?
    }
    ActivityResult::Cancelled => stop_without_redispatch(),
}

OutcomeUnknown is not converted to failure and is never automatically redispatched. Reconciliation updates the same effect relationship with exact observation and receipt evidence.

4. Prove replay and interruption

cargo test -p support-triage-agent --all-targets --offline
one check --workspace systems/system-idl/examples/support-triage-agent --offline

Replay validates compatible decisions against retained history without repeating external effects. An incompatible workflow revision reports the exact history range it cannot serve.

5. Select the durable engine later

Planning selects inference, encrypted durable session, Authority, History, Build, and local-release providers independently. Replacing the deterministic inference provider with the admitted HTTP provider does not revise the workflow or agent declaration.

Executable evidence

The checked-in support-triage project owns the exact source and lock, Rust one::agent parity test, deterministic provider execution, bounded tool/effect trace, complete public lifecycle, and idempotent resume evidence.

See durable work and recovery and continuity.