Install an SDK
Add Chio to your application from your language's registry, then run a first program that earns one signed refusal.
On this page
One package per language puts the Computer API from the Quickstart, and the lower-level clients beneath it, into your application. Each talks to the kernel the CLI installed, so a program in any language opens the same computers, grants the same authority, and reads the same receipts.
By the end of step 3 your program has opened the Quickstart computer, given the fixer agent a slice of it, and printed the receipt for the one read your kernel refused. Install the CLI first.
1. Install the package for your language
npm install @chio-protocol/sdkpip install chio-sdkcargo add chiogo get github.com/backbay-labs/chio/sdks/go/chio-godependencies {
implementation("world.chio:chio-sdk-jvm:0.1.0")
}dotnet add package Backbay.Chio.package(url: "https://github.com/backbay-labs/chio-swift", from: "0.1.0")vcpkg add port chioThe packages need Node.js >=22, Python >=3.11, Rust 1.94, Go 1.23.0, Java 17, or net8.0. The Python distribution is chio-sdk and imports as chio; the PyPI name chio belongs to an unrelated project. The Rust crate starts its own runtime with #[chio::main], and the C++ package links with find_package(ChioCpp CONFIG REQUIRED).
2. Create your identity and the Quickstart computer
Your kernel signs every decision with your operator key, so create it once:
chio key initoperator did:chio:z6Mkf3…Qp9 kernel 4f1c…a2e9 stored ~/.chio/keys, mode 600
Then create the computer the program opens: a Python pricing package with three failing tests, one per open issue.
chio new quickstart && cd quickstartcreated quickstart, 14 tests, 3 failing: issues #412, #413, #414 computer quickstart, owned by did:chio:z6Mkf3…Qp9
3. Run a first program and read its refusal
The program opens the computer, forks it, grants the fixer the workspace, your model route, and two dollars for twenty minutes, runs issue #412, and prints the one refusal the run earns.
import { Computer, USD } from "@chio-protocol/sdk";
const project = await Computer.open("quickstart");
const fixer = await project.agent("fixer");
const fork = await project.fork();
const authority = fork.grant({
to: fixer,
resources: { "/workspace": ["read", "write"], "/models/default": ["invoke"] },
budget: USD(2),
expiresIn: "20m",
});
const run = await fixer.run("fix issue #412", { on: fork, authority });
for await (const event of run.events()) console.log(event.summary);
const [refusal] = await project.history.receipts({ outcome: "deny" });
console.log(refusal.describe());00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
from chio import Computer, USD
project = Computer.open("quickstart")
fixer = project.agent("fixer")
fork = project.fork()
authority = fork.grant(
to=fixer,
resources={"/workspace": ["read", "write"], "/models/default": ["invoke"]},
budget=USD(2),
expires_in="20m",
)
run = fixer.run("fix issue #412", on=fork, authority=authority)
for event in run.events():
print(event.summary)
refusal = project.history.receipts(outcome="deny")[0]
print(refusal.describe())00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
use chio::stream::StreamExt;
use chio::{Computer, Grant, USD};
#[chio::main]
async fn main() -> chio::Result<()> {
let project = Computer::open("quickstart").await?;
let fixer = project.agent("fixer").await?;
let fork = project.fork().await?;
let authority = fork.grant(
Grant::to(&fixer)
.resource("/workspace", ["read", "write"])
.resource("/models/default", ["invoke"])
.budget(USD(2))
.expires_in("20m"),
)?;
let mut run = fixer.run("fix issue #412").on(&fork).authority(authority).start().await?;
let mut events = run.events();
while let Some(event) = events.next().await {
println!("{}", event?.summary());
}
let refusal = project.history().receipts().outcome("deny").first().await?;
println!("{}", refusal.describe());
Ok(())
}00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
package main
import (
"context"
"fmt"
"log"
"time"
chio "github.com/backbay-labs/chio/sdks/go/chio-go"
)
func main() {
if err := quickstart(context.Background()); err != nil {
log.Fatal(err)
}
}
func quickstart(ctx context.Context) error {
project, err := chio.Open(ctx, "quickstart")
if err != nil {
return err
}
fixer, err := project.Agent(ctx, "fixer")
if err != nil {
return err
}
fork, err := project.Fork(ctx)
if err != nil {
return err
}
authority, err := fork.Grant(ctx, chio.Grant{
To: fixer,
Resources: chio.Resources{"/workspace": {"read", "write"}, "/models/default": {"invoke"}},
Budget: chio.USD(2),
ExpiresIn: 20 * time.Minute,
})
if err != nil {
return err
}
run, err := fixer.Run(ctx, "fix issue #412", chio.RunOptions{On: fork, Authority: authority})
if err != nil {
return err
}
for event, err := range run.Events(ctx) {
if err != nil {
return err
}
fmt.Println(event.Summary)
}
refusals, err := project.History().Receipts(ctx, chio.ReceiptFilter{Outcome: chio.Deny})
if err != nil {
return err
}
fmt.Println(refusals[0].Describe())
return nil
}00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
import kotlin.time.Duration.Companion.minutes
import world.chio.sdk.Computer
import world.chio.sdk.Outcome
import world.chio.sdk.USD
fun main() {
val project = Computer.open("quickstart")
val fixer = project.agent("fixer")
val fork = project.fork()
val authority = fork.grant(
to = fixer,
resources = mapOf(
"/workspace" to listOf("read", "write"),
"/models/default" to listOf("invoke"),
),
budget = USD(2),
expiresIn = 20.minutes,
)
val run = fixer.run("fix issue #412", on = fork, authority = authority)
run.events().forEach { println(it.summary) }
val refusal = project.history.receipts(outcome = Outcome.DENY).first()
println(refusal.describe())
}00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
using Backbay.Chio;
using static Backbay.Chio.Money;
var project = await Computer.OpenAsync("quickstart");
var fixer = await project.AgentAsync("fixer");
var fork = await project.ForkAsync();
var authority = fork.Grant(new GrantSpec
{
To = fixer,
Resources =
{
["/workspace"] = ["read", "write"],
["/models/default"] = ["invoke"],
},
Budget = USD(2),
ExpiresIn = TimeSpan.FromMinutes(20),
});
var run = await fixer.RunAsync("fix issue #412", fork, authority);
await foreach (var e in run.EventsAsync()) Console.WriteLine(e.Summary);
var refusals = await project.History.ReceiptsAsync(outcome: Outcome.Deny);
Console.WriteLine(refusals[0].Describe());00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
import Chio
let project = try await Computer.open("quickstart")
let fixer = try await project.agent("fixer")
let fork = try await project.fork()
let authority = try fork.grant(
to: fixer,
resources: ["/workspace": [.read, .write], "/models/default": [.invoke]],
budget: .usd(2),
expiresIn: .minutes(20)
)
let run = try await fixer.run("fix issue #412", on: fork, authority: authority)
for try await event in run.events() {
print(event.summary)
}
let refusals = try await project.history.receipts(outcome: .deny)
print(refusals[0].describe())00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
#include <chio/computer.hpp>
#include <iostream>
chio::Result<void> quickstart() {
CHIO_TRY(auto project, chio::Computer::open("quickstart"));
CHIO_TRY(auto fixer, project.agent("fixer"));
CHIO_TRY(auto fork, project.fork());
CHIO_TRY(auto authority, fork.grant(chio::Grant::to(fixer)
.resource("/workspace", {"read", "write"})
.resource("/models/default", {"invoke"})
.budget(chio::USD(2))
.expires_in(std::chrono::minutes(20))));
CHIO_TRY(auto run, fixer.run("fix issue #412").on(fork).authority(authority).start());
for (auto next : run.events()) {
CHIO_TRY(auto event, next);
std::cout << event.summary() << '\n';
}
CHIO_TRY(auto refusals, project.history().receipts().outcome(chio::Outcome::Deny).all());
std::cout << refusals.front().describe() << '\n';
return chio::Result<void>::success();
}
int main() {
auto done = quickstart();
if (!done) {
std::cerr << done.error().message << '\n';
return 1;
}
}00:00 admitted fixer runs "fix issue #412" on fork 51c07ae 00:03 read /workspace/src/pricing.py 00:05 read /workspace/tests/test_pricing.py 00:09 refused read /secrets/.env: outside the grant 00:12 invoke /models/default, USD 0.21 00:41 write /workspace/src/pricing.py 00:56 test pytest -k issue_412: passed spent USD 0.48 of 2.00 receipt rcpt-01a8…9c04 request fixer read /secrets/.env verdict deny: outside the grant grant cap-01a8…31f2 policy sha256 3c7b…8010 signed your kernel 4f1c…a2e9, signature verifies
You should see one refusal and a passing test. The fixer read the failing test, then tried /secrets/.env. The grant covers /workspace and /models/default only, so your kernel refused the read before the file was opened and signed receipt rcpt-01a8…9c04 for the refusal. The run spent USD 0.48 of its 2.00.
Every call in the program is in your language's reference: TypeScript, Python, Rust, Go, JVM, .NET, Swift, and C++.
An adapter puts the kernel in front of the stack you already run
A service that keeps its own HTTP framework or agent framework adds an adapter instead of rewriting its handlers. Each adapter installs from its registry under its own name and depends on the core package.
pip install chio-fastapi # FastAPI and other ASGI apps
pip install chio-django # Django
pip install chio-langgraph # LangGraph
pip install chio-temporal # Temporal workflows
pip install chio-prefect # Prefect flowsnpm install @chio-protocol/express
npm install @chio-protocol/fastify
npm install @chio-protocol/elysia
npm install @chio-protocol/node-http
npm install @chio-protocol/ai-sdkgo get github.com/backbay-labs/chio/sdks/go/chio-go-httpdependencies {
implementation("world.chio:chio-spring-boot:0.1.0")
}dotnet add package Backbay.Chio.MiddlewareFurther Python adapters cover chio-langchain, chio-crewai, chio-autogen, chio-llamaindex, chio-dagster, chio-airflow, and chio-ray. Every Python adapter requires Python >=3.11. The CLI and the SDKs write the same chio.receipt.v1 receipts, and chio conformance run executes the conformance scenarios against a peer-language adapter, so a prototype built on the CLI moves into an SDK with its records unchanged.
Read more in Add API Middleware.
Each Dagster, Airflow, and Ray task is admitted before its body runs
The Dagster, Airflow, and Ray adapters wrap the runtime's own unit of work, so the Chio sidecar evaluates each materialization, task, or remote call before its body runs. Each depends on chio-sdk and pydantic>=2.5. The examples are your nightly repricing jobs against the pricing and orders servers. Temporal and Prefect have their own guides: Temporal and Prefect.
Dagster
chio-dagster requires dagster>=1.8,<2. @chio_asset and @chio_op take every @asset and @op option and add a Chio scope, capability, and tool server.
pip install chio-dagsterfrom chio_sdk import ChioScope, Operation, ToolGrant
from dagster import AssetExecutionContext, Definitions, StaticPartitionsDefinition
from chio_dagster import chio_asset
TENANTS = StaticPartitionsDefinition(["harbor-goods", "ostrander"])
QUOTE_SCOPE = ChioScope(
grants=[
ToolGrant(
server_id="pricing",
tool_name="quote",
operations=[Operation.INVOKE],
)
]
)
@chio_asset(
scope=QUOTE_SCOPE,
capability_id="cap-nightly-reprice",
tool_server="pricing",
partitions_def=TENANTS,
)
def price_sheet(context: AssetExecutionContext) -> list[dict]:
# The partition key is part of the evaluation payload.
return pricing.quote_catalog(tenant=context.partition_key)
defs = Definitions(assets=[price_sheet])A deny raises PermissionError and Dagster records a FAILURE run state. An allow attaches chio_receipt_id, chio_verdict, and the capability and tool fields to the emitted AssetMaterialization, so the asset catalog shows each receipt. Because the partition key is evaluated, a guard can admit harbor-goods and refuse ostrander. ChioIOManager wraps an inner IO manager and checks every handle_output and load_input against the destination.
Airflow
chio-airflow requires apache-airflow>=2.8,<4 and covers both operator styles: wrap a classic operator in ChioOperator, or decorate a TaskFlow function with @chio_task.
pip install chio-airflowfrom airflow.decorators import dag
from chio_airflow import chio_task
@dag(schedule="@daily")
def nightly_reprice():
@chio_task(
scope=ORDERS_SCOPE,
capability_id="cap-nightly-reprice",
tool_server="orders",
)
def load_orders(day: str) -> list[dict]:
return orders.sql("select sku, qty from orders where day = %s", [day])
load_orders("{{ ds }}")
nightly_reprice()A denied task fails with AirflowException, whose __cause__ is a PermissionError. Receipt ids go into XCom, and ChioDAGListener, registered through the bundled AirflowPlugin, aggregates them into a run-level record on on_dag_run_success and on_dag_run_failed. ChioOperator passes standard scheduling arguments such as retries and trigger_rule through to the operator it owns.
Ray
chio-ray requires ray[default]>=2.10,<3. @chio_remote keeps the .remote(...) and ray.get(...) contract and every ray.remote keyword argument.
pip install chio-rayimport ray
from chio_ray import chio_remote
@chio_remote(
scope="pricing:quote",
capability_id="cap-bulk-quote",
tool_server="pricing",
)
def quote_sku(sku: str) -> dict:
return pricing.quote(sku, percent=10)
quotes = ray.get([quote_sku.remote(sku) for sku in ["sku-118", "sku-204", "sku-301"]])The node-local sidecar at http://127.0.0.1:9090 evaluates each call. A deny raises PermissionError in the worker, and the driver sees a RayTaskError wrapping it. For long-lived actors, subclass ChioActor with a StandingGrant and mark methods with @ChioActor.requires(...). A method outside the standing grant raises PermissionError with reason scope_exceeds_standing_grant before the sidecar is called, and StandingGrant.attenuate hands a worker actor a narrower scope.
Platform integrations govern workloads rather than application code
A Kubernetes controller with CRDs and admission webhooks, and an AWS Lambda extension (chio-lambda-extension), put the kernel in front of whole workloads. The SDK overview describes both.