Chio/Docs
LOGIN · JOIN

Operate an Agentic OS

Kill processes, cancel work, expire authority, and recover only the outcomes the effect owner can prove.

Guide chio@5f63e6e

On this page

An agent operating system tells you what happened when a worker disappears. This control application runs failure exercises against the fleet and network services from the other chapters; it stops worker and host processes at named points, reads the retained accounting and adapter state, and records whether the work completed, was refused, or stays unresolved.

Run an exercise

A host crash leaves partial work unresolved and unpublished

Build it. Run it. Inspect it.

Recover an operating system without guessing its effects

Stop real workers and hosts, inspect their retained authority and effects, and reconcile before deciding what can safely run again.

Download project
Your inputs

Hosted records are retained for seven days. Use the downloaded project for local work and your own model credentials.

Loading the verified example result…

Choose a crash point and run the exercise. A host crash during a report leaves partial work and no published report. A lost acknowledgement happens after publication and is reconciled to the original operation. Cancellation interrupts active work, and an expired grant stays expired after restart. Compare the retained effect, accounting, and receipt before you decide what to do next.

Only the adapter’s operation record can resolve an outcome

Claims and grants live in the host’s retained state, so a restart keeps every refusal in place. The adapter’s own record of the effect decides completion.

OperationsChoose a lens.
claimreportoperation IDreconcilesgrantstale claimexpired grantκGrantaWorkerholds a claimKReport hostretained statedReport adapterρOperation recordoperation IDstale claimexpired grantκGrantaWorkerKReport hostdAdapterρRecord

Restart keeps refusals in place

The host retains the grant and each job's claim across process replacement. After a restart, a stopped worker's stale claim cannot publish, and a grant that expired stays expired. Recover an operation.

The operations application: the grant, a worker's claim, the report host, and the adapter's operation record. Connectivity failures and directory removal from the personal network are left out.

Each failure happens at a named point

The control application dispatches each named exercise to the fleet or personal-network service, and the failure description is part of the input and the retained run. A process termination, transport failure, or expired capability happens at its own boundary in the running service.

operations/src/lib.rsL28–75rust
pub async fn exercise(input: Value, run: Run, executable: PathBuf) -> Result<Value> {
    let exercise = input["exercise"]
        .as_str()
        .context("Select a recovery exercise")?;
    if ["lost-acknowledgement", "budget-exhaustion"].contains(&exercise) {
        let mut request = Fleet.sample();
        request["document"] = input["document"].clone();
        if exercise == "budget-exhaustion" {
            request["allowance"] = json!(30);
        }
        let child = Run::create(&run.directory()?.join("fleet-runs"), Fleet.name(), &request)?;
        let result = chio_worker_fleet::run_fleet(request, child.clone(), executable).await;
        child.finish(&result)?;
        let output = result?;
        run.emit(
            "operations.fleet",
            "operator",
            "Actual fleet restart followed by effect reconciliation",
            child.snapshot()?,
        )?;
        return Ok(json!({"exercise":exercise,"fleet":output}));
    }
    if exercise == "peer-removal" {
        let app = chio_personal_network::Personal;
        let mut request = app.sample();
        request["document"] = input["document"].clone();
        let child = Run::create(&run.directory()?.join("network-runs"), app.name(), &request)?;
        let result = chio_personal_network::run_network(request, child.clone(), executable).await;
        child.finish(&result)?;
        let output = result?;
        run.emit(
            "operations.network",
            "operator",
            "Live peer removal and restoration across node processes",
            child.snapshot()?,
        )?;
        return Ok(json!({"exercise":exercise,"network":output}));
    }
    anyhow::ensure!(
        [
            "worker-crash-before-dispatch",
            "host-crash-during-report",
            "cancel-running-report",
            "expired-authority"
        ]
        .contains(&exercise),
        "Choose a documented recovery exercise"
    );

Open this excerpt in the complete source

In the verified run, event 03 stops the worker and the host at crash point host-crash-during-report.

The adapter’s completed result survives replacement

The fleet’s report handler owns an operation record and its published report, and the control application reads that state across process replacement. A saved task record shows intent; the adapter’s own record of the effect is what makes reconciliation possible.

worker-fleet/src/server.rsL290–343rust
async fn reconcile(
    State(service): State<Arc<Service>>,
    headers: HeaderMap,
    Path(id): Path<String>,
) -> ApiResult {
    admin(&headers, &service)?;
    let mut stored = service.jobs.lock().await;
    let mut jobs = stored.clone();
    let job = jobs
        .iter_mut()
        .find(|job| job.operation_id.to_string() == id)
        .ok_or_else(|| error("Unknown operation"))?;
    if service.cancellations.lock().await.contains_key(&id) {
        return Err(error(
            "Worker is still executing; wait for its terminal state",
        ));
    }
    let file = service
        .config
        .directory
        .join("reports")
        .join(format!("{id}.json"));
    let resolution = if file.exists() {
        let artifact: Value =
            serde_json::from_slice(&std::fs::read(file).map_err(error)?).map_err(error)?;
        let expected =
            chio_core::sha256_hex(&chio_core::canonical_json_bytes(&job.input).map_err(error)?);
        if artifact["input_sha256"] != expected || artifact["operation_id"] != id {
            return Err(error(
                "Artifact does not match this operation; leave it unresolved",
            ));
        }
        let outcome = job.reconcile_published().map_err(error)?;
        json!({"state":"completed","reused_existing_effect":true,"artifact":artifact,"receipt_id":outcome["receipt_id"]})
    } else {
        json!({
            "state":job.label(),
            "reused_existing_effect":false,
            "recovery":"No published artifact proves completion. Inspect retained admission and partial output; this adapter does not blindly retry uncertain work."
        })
    };
    service.persist(&jobs).map_err(error)?;
    *stored = jobs;
    service
        .run
        .emit(
            "fleet.reconciled",
            "operator",
            "Reconciled the report's actual state",
            json!({"operation_id":id,"resolution":resolution}),
        )
        .map_err(error)?;
    Ok(Json(resolution))
}

Open this excerpt in the complete source

Cancellation is checked at the effect owner

Cancellation is checked against the retained job and the active operation. The host aborts the running report and keeps the job’s cancellation decision. A partial draft stays distinct from a published report, and the control application checks that cancellation left no accepted report behind.

worker-fleet/src/server.rsL252–279rust
async fn cancel(
    State(service): State<Arc<Service>>,
    headers: HeaderMap,
    Path(id): Path<String>,
) -> ApiResult {
    admin(&headers, &service)?;
    if let Some(flag) = service.cancellations.lock().await.get(&id) {
        flag.store(true, Ordering::SeqCst);
        return Ok(Json(json!({"cancellation_requested":true})));
    }
    let mut stored = service.jobs.lock().await;
    let mut jobs = stored.clone();
    let job = jobs
        .iter_mut()
        .find(|job| job.operation_id.to_string() == id)
        .ok_or_else(|| error("Unknown operation"))?;
    if matches!(job.state, JobState::Queued | JobState::Claimed { .. }) {
        job.cancel_before_dispatch().map_err(error)?;
        service.persist(&jobs).map_err(error)?;
        *stored = jobs;
        return Ok(Json(
            json!({"state":"cancelled_before_dispatch","receipt_id":null}),
        ));
    }
    Err(error(
        "No active worker; inspect the operation before attempting recovery",
    ))
}

Open this excerpt in the complete source

Evidence exports without repeating work

The capture path validates the run identity, event sequence, and completed-result digests before it returns the retained record, and it never re-enters the application. The docs reconnect operation uses the same native capture interface, so refreshing a page starts no second mission.

shared/src/events.rsL151–193rust
    pub fn capture(root: &Path, id: &str) -> Result<Value> {
        // IDs are server-generated UUIDs. Validate before constructing paths.
        let id = uuid::Uuid::parse_str(id)?.to_string();
        let directory = root.join(id);
        let mut manifest: Value =
            serde_json::from_slice(&read_bounded(&directory.join("run.json"))?)?;
        let path = directory.join("events.ndjson");
        let mut events = Vec::new();
        if path.exists() {
            let bytes = read_bounded(&path)?;
            for line in std::str::from_utf8(&bytes)?.lines() {
                anyhow::ensure!(
                    events.len() < 4096,
                    "Retained event count exceeds its bound"
                );
                events.push(serde_json::from_str::<Event>(line)?);
            }
        }
        anyhow::ensure!(
            events
                .iter()
                .enumerate()
                .all(|(index, event)| event.sequence == index + 1),
            "Retained event sequence is incomplete"
        );
        if manifest["status"] != "running" {
            anyhow::ensure!(
                manifest["output_sha256"]
                    == chio_core::sha256_hex(&chio_core::canonical_json_bytes(
                        &manifest["output"]
                    )?),
                "Retained output digest mismatch"
            );
            anyhow::ensure!(
                manifest["events_sha256"]
                    == chio_core::sha256_hex(&chio_core::canonical_json_bytes(&events)?),
                "Retained event digest mismatch"
            );
        }
        manifest["events"] = serde_json::to_value(events)?;
        Ok(manifest)
    }
}

Open this excerpt in the complete source

Event 04 refuses the stale worker request and leaves the operation unresolved, with 20 credits reserved and none spent.

A stale claim, a crash mid-report, and an expired grant stay refused

The sample input crashes the host during a report. The retained run shows what recovery could and could not prove:

Terminalbash
./run --run input.json
Retained events, captures/verified.json
01  operations.claimed        report-worker
    Independent worker retained its job claim
02  operations.effect_started report-host
    The governed report has written partial output
03  operations.processes_stoppedoperator
    Worker and authoritative host processes have stopped; 0 of 40 local demo credits
    spent
04  operations.reconciled     operator
    state unresolved; stale request: Claim is no longer executable; inspect the
    retained operation
  • Stop a worker after it claims work: its stale claim cannot publish after recovery.
  • Kill the host during report construction: no partial draft becomes a completed report.
  • Lose a committed response: recover the original operation and receipt instead of spending again.
  • Restart after authority expiry: the old grant stays expired.
  • Remove a peer: new and held-connection admission both observe the membership change.

The downloadable tests assert each effect or its absence: run cargo test --locked -p chio-operations from the extracted project.

Run the control application on your machine

Keep the run directory to connect the fault point, the retained operation, the effect state, and the reconciliation result.

From the extracted projectbash
cd chio-operations
./run

The archive holds the application, the shared host code, tests, sample input, pinned dependencies, and a README. The launcher builds and runs the Rust source included in this archive. Install Rust 1.94.1 and the README’s native prerequisites; filesystem isolation and operator workloads require the listed Linux host profile. Cargo resolves immutable public dependencies, so a sibling checkout is unnecessary.

For model workers, set OPENROUTER_API_KEY on the local host and select model mode; credentials stay on that host and never enter the docs form. The qualified model is openai/gpt-4.1-mini. Analysis, retrieval, and deterministic worker modes run without a model key. Ctrl-C stops the local web process and its active child work and keeps the run directory.

Download identity and source revision

Download complete project · View public source

Project archive SHA-256text
af5cb2898020bacc8ad56b8a695ad3fe63652f6de33f8bd658ab4c62acaf98cc

Add a fault exercise for every new adapter

Add one fault exercise for each new effectful adapter. Name the crash point, the authoritative effect record, and the evidence that makes recovery safe. Keep an outcome unresolved when the adapter cannot prove what happened, and derive any retry policy from that contract, never from whether a client happened to receive a response.

Next: build a shared worker fleet