PlatformAuthoring
chio.yaml Configuration
A field reference for chio.yaml: runtime signing keys, upstream APIs, protocol endpoints, and guard modules.
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 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. |
deadlines | object | kernel defaults | Hot-path wall-clock budgets. Optional; an absent table falls back to kernel defaults. See below. |
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.kernel.deadlines
An optional sub-section exposing the runtime hot-path wall-clock budgets. Only the scalar budgets are set from the file; the per-guard and per-server override maps are wired programmatically. Every field is optional, so an absent kernel.deadlines table is valid — each Some value replaces the matching kernel default and each omitted field keeps it. The section applies deny_unknown_fields.
| Field | Type | Notes |
|---|---|---|
guard_pipeline_budget_ms | u64 (optional) | Wall-clock budget for the full guard pipeline. |
dispatch_budget_ms | u64 (optional) | Budget for dispatch to the tool server. |
receipt_append_budget_ms | u64 (optional) | Budget for appending a receipt. |
receipt_writer_poll_ms | u64 (optional) | Receipt-writer poll interval. |
receipt_writer_stall_ms | u64 (optional) | Threshold before the receipt writer is treated as stalled. |
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[]
Each edge exposes an adapter through a protocol endpoint.
| 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.
Additional guard configuration
guards — per-guard blocks such as internal_network.extra_blocked_hosts, agent_velocity.max_requests_per_agent, data_flow, behavioral_sequence, response_sanitization.min_level/action, and the advisory knobs (anomaly, data-transfer, promotion rules). These configure individual individual guards. Each guard's reference page documents its own block — see, for example, Network Guards for internal_network and Filesystem Guards for the path guards.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 | Intended to order evaluation (lower = earlier) and validated as such by chio-config, but the kernel's guard registration path does not currently sort by priority. Insertion order — the order wasm_guards[] entries appear in the file — determines actual evaluation order. Order your entries accordingly. |
advisory | bool | false | When true, a failure is recorded but not blocking. |
See Custom WASM Guards for the manifest format, signing, and host imports.
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. The CLI does ship a chio doctor probe that parses chio.yaml and checks a minimal marker schema — the top-level version and policy keys, not the adapter/edge runtime schema on this page (see below). For the full runtime schema, 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 a CLI-level check, chio doctor runs six ordered health probes; the sixth parses chio.yaml and checks for two top-level marker keys, version and policy, reporting errors with line and column anchors. chio doctor --fix scaffolds a minimal file containing exactly those keys (version: 1, policy: ./policy.yaml).
The doctor probe validates a different, minimal schema
version/policy marker schema is a separate contract from the kernel/adapters/edges runtime schema this page documents. A well-formed adapter/edge chio.yaml carries neither version nor policy and does not satisfy the probe. For full validation of the runtime schema 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-path
- 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) use a distinct policy schema. They are not configured through chio.yaml or a guards: block inside a HushSpec document. Their cloud-guardrail and threat-intel configuration lives on the control-plane external-guard policy schema (the cloud_guardrails and threat_intel fields on GuardPolicyConfig), which the control plane compiles into a pipeline via build_guard_pipeline and build_post_invocation_pipeline (re-exported from chio_control_plane::policy). Within a HushSpec document, threat-intel-driven detection is instead configured at extensions.detection.threat_intel (compiling to the EmbeddingAnomalyGuard). See External Guards for that schema.
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 uses adapters and protocol endpoints