chio.yaml Configuration
chio.yaml tells a Chio runtime where its signing key lives, which upstream APIs to wrap, which protocol edges to expose, where to write receipts, and which WASM guard modules to load. The schema lives in chio-config, applies deny_unknown_fields everywhere, and runs environment variable interpolation on the raw text before parsing. This page is the field-level reference.
Root Structure
The top-level object is ChioConfig with these sections:
| Field | Type | Required | Description |
|---|---|---|---|
kernel | object | Yes | Signing key, receipt store, kernel log level. |
adapters | array | Yes (min 1) | Upstream API connections. |
edges | array | No | Protocol edges (mcp, a2a) that expose adapters. |
receipts | object | No | Receipt store, retention, and checkpoint cadence. |
logging | object | No | Log level and output format. |
telemetry | object | No | OpenTelemetry span export. |
guards | object | No | Globally required guard names and advisory promotion. |
wasm_guards | array | No | WASM guard modules loaded at runtime. |
kernel
The only always-required section. It identifies the runtime to the rest of the system through its Ed25519 signing key.
| Field | Type | Default | Notes |
|---|---|---|---|
signing_key | string | required | Hex-encoded Ed25519 key, or the literal "generate" for dev mode. Empty values are rejected. |
receipt_store | string | "sqlite:///var/chio/receipts.db" | Receipt store URI used by the kernel directly. |
log_level | string | "info" | Kernel-subsystem log level. The top-level logging.level covers the rest of the runtime. |
signing_key: generate is not for production
"generate" creates an ephemeral keypair at startup. Receipts signed by an ephemeral key are unverifiable after restart. Use a persistent hex-encoded key in any deployment that has to survive a restart.adapters[]
Each adapter connects the kernel to one upstream API. At least one adapter is required.
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | Yes | Unique within the file. Referenced by edges. |
protocol | string | Yes | Adapter type: openapi, grpc, graphql, etc. |
upstream | string | Yes | URL of the upstream API. |
spec | string | No | Path to a spec file (for openapi, the OpenAPI YAML/JSON). |
auth | object | No | Upstream authentication. |
auth
auth:
type: bearer # one of: bearer, api_key, cookie, mtls, none
header: Authorization # required for bearer and api_keyValidation:
typemust be one ofbearer,api_key,cookie,mtls,none.- When
typeisbearerorapi_key, theheaderfield is required. cookie,mtls, andnonemay omitheader.
edges[]
Edges expose an adapter through a different protocol surface.
| Field | Type | Notes |
|---|---|---|
id | string | Unique within the file. |
protocol | string | Edge protocol: mcp, a2a, acp, etc. |
expose_from | string | Adapter id that this edge surfaces. Must reference a declared adapter. |
receipts
| Field | Type | Default | Notes |
|---|---|---|---|
store | string | "sqlite:///var/chio/receipts.db" | Receipt store URI. |
checkpoint_interval | u64 | 100 | Receipts between Merkle checkpoints. 0 disables. |
retention_days | u64 | 90 | Days to retain receipts before expiry. |
logging
| Field | Type | Default | Allowed values |
|---|---|---|---|
level | string | "info" | trace, debug, info, warn, error |
format | string | "json" | json, text |
telemetry
| Field | Type | Default | Notes |
|---|---|---|---|
enabled | bool | false | Master switch for OTel export. |
endpoint | string | "" | OTel collector URL (e.g., http://localhost:4317). |
service_name | string | "chio-acp-proxy" | Service identifier reported to the collector. |
include_parameters | bool | false | Include receipt parameters in span attributes. Off by default to avoid leaking sensitive data. |
batch_size | usize | 0 | Span batch size. 0 exports each span immediately. |
guards
Globally applied guard configuration. Per-guard configuration (forbidden paths, tool access, egress) belongs in a HushSpec policy; this section sets pipeline-wide knobs.
| Field | Type | Default | Notes |
|---|---|---|---|
allow_advisory_promotion | bool | false | When true, advisory-only verdicts can be promoted to deterministic blocking via overlay. |
required | string[] | [] | Guard names that must pass on every request, regardless of route. |
For details on which guards are configurable through HushSpec, see HushSpec Policy Format. For the runtime pipeline, see Default Pipeline.
wasm_guards[]
Each entry registers a WASM guard module for the pipeline. The loader walks up from path to read guard-manifest.yaml from the same directory.
| Field | Type | Default | Notes |
|---|---|---|---|
name | string | required | Surfaces in receipts and logs. |
path | string | required | Filesystem path to the .wasm module. |
fuel_limit | u64 | 10000000 | Max fuel units per invocation. |
priority | u32 | 1000 | Lower values run first. |
advisory | bool | false | When true, a failure is recorded but not blocking. |
See Custom WASM Guards for the manifest format, signing, and the host-import surface.
Environment Variable Interpolation
Interpolation runs on the raw YAML before parsing, so every string-typed field is eligible. Two patterns are supported:
${VAR} # required: error if VAR is unset
${VAR:-default} # optional: use VAR if set, otherwise the default literalVariable names match [A-Za-z_][A-Za-z0-9_]*. If multiple required variables are unset, the loader reports them all in a single error so you can fix everything in one pass. The sequence ${} with no variable name is left as literal text.
kernel:
signing_key: "${CHIO_SIGNING_KEY}"
log_level: "${CHIO_LOG_LEVEL:-info}"
adapters:
- id: petstore
protocol: openapi
upstream: "http://${API_HOST}:${API_PORT:-8080}/api"
auth:
type: bearer
header: AuthorizationValidation
Validation runs after interpolation and YAML deserialization. All errors collect into a single ConfigError::Validation so the operator can fix everything at once.
- deny_unknown_fields. Every section rejects unknown keys at parse time. Typos like
recieiptsfail before validation runs. - At least one adapter. An empty adapter list is rejected.
- Unique adapter IDs. Duplicates are rejected by string comparison. Empty IDs are also rejected.
- Unique edge IDs. Same rule. Empty edge IDs are rejected.
- Reference integrity. Every
edge.expose_frommust match an adapteriddeclared in the same file. - Auth completeness.
typevalues are enumerated;bearerandapi_keyrequire aheader. - Non-empty signing key.
kernel.signing_keymust not be the empty string. - Logging enums.
levelandformatare checked against their fixed value sets.
Loading from Code
Programmatic callers use the loader entry points in chio-config:
use chio_config::{load_from_file, load_from_str, ChioConfig};
// From a file path:
let config: ChioConfig = load_from_file(Path::new("/etc/chio/chio.yaml"))?;
// From a string (e.g., loaded over the network):
let config: ChioConfig = load_from_str(yaml_text)?;Both helpers run interpolation, parse with deny_unknown_fields, and run the validation pass before returning. Errors are surfaced as ConfigError with Io, Interpolation, Parse, and Validation variants.
No universal chio start command
chio start --config chio.yaml entry point. Individual subcommands and embedded runtimes that consume chio.yaml opt in through their own flags or programmatic APIs. To validate a config outside of a running process, call chio_config::load_from_file from a small Rust binary or a test harness.CLI Policy Checks
The chio CLI exposes commands for evaluating policies (a separate file from chio.yaml) but does not offer a top-level chio config validate subcommand today. The policy-facing commands are:
# Spawn an agent under a HushSpec policy.
$ chio run --policy ./policy.yaml -- agent --task my-task
# Evaluate a single tool call against a policy without spawning anything.
$ chio check --policy ./policy.yaml \
--tool read_file \
--params '{"path": "/etc/passwd"}' \
--server '*'
# Scaffold a new project with a sample chio.yaml and policy.
$ chio init my-deploymentFor configuration validation in CI, write a small Rust test that calls load_from_file and asserts Ok, or shell out from a build script.
Worked Example
A complete chio.yaml for a small deployment: one MCP edge over an OpenAPI adapter, one external guard reachable via the policy compiler, and one custom WASM guard. Secrets are interpolated from the environment.
kernel:
signing_key: "${CHIO_SIGNING_KEY}"
receipt_store: "sqlite:///var/lib/chio/receipts.db"
log_level: "${CHIO_KERNEL_LOG_LEVEL:-info}"
adapters:
- id: petstore
protocol: openapi
upstream: "https://${PETSTORE_HOST}/v1"
spec: ./specs/petstore.openapi.yaml
auth:
type: bearer
header: Authorization
edges:
- id: petstore-mcp
protocol: mcp
expose_from: petstore
receipts:
store: "sqlite:///var/lib/chio/receipts.db"
checkpoint_interval: 200
retention_days: 365
logging:
level: "${CHIO_LOG_LEVEL:-info}"
format: json
telemetry:
enabled: true
endpoint: "http://${OTEL_HOST:-localhost}:4317"
service_name: chio-petstore-edge
include_parameters: false
batch_size: 100
guards:
required:
- forbidden-paths
- secret-leak
- patch-integrity
allow_advisory_promotion: false
wasm_guards:
- name: tool-denylist
path: /etc/chio/guards/tool-denylist/tool_denylist_guard.wasm
fuel_limit: 5000000
priority: 100
- name: org-pii-scanner
path: /etc/chio/guards/pii-scanner/pii_guard.wasm
fuel_limit: 20000000
priority: 200
advisory: falseExternal provider guards (Bedrock, Azure, Vertex, Safe Browsing, VirusTotal, Snyk) are wired through the policy compiler under the guards.cloud_guardrails and guards.threat_intel blocks of the HushSpec policy file, not in chio.yaml. See External Guards for that surface.
Next Steps
- HushSpec Policy Format · the policy file that pairs with
chio.yaml - Custom WASM Guards · author the modules referenced from
wasm_guards - External Guards · cloud content-safety and threat-intel integration
- Wrap an MCP Server · a deployment that exercises the adapter/edge surface