Chio/Docs
LOGIN · JOIN

HushSpec Policy Format

Write a HushSpec policy, inspect the controls it compiles to, and look up any field, default, or inheritance rule.

Reference chio@5f63e6e

On this page

A HushSpec policy is one YAML document that sets an agent's tool authority, filesystem and network rules, output checks, resource limits, and approval requirements. The compiler resolves the policy's local bases and emits request guards, output hooks, and a default capability scope for the host to install on the kernel.

A child policy inherits every rule block it leaves out

The examples govern the pricing service from Quickstart part 2 and its three tools: quote, refund, and discount. Download the HushSpec examples and unpack them anywhere. The parent permits quote with an argument limit of 4,096 bytes; the child adds a pattern for your live API keys and inherits the whole tool_access block without repeating it.

hushspec-policies/base.yaml · completeyaml
hushspec: "0.1.0"
name: pricing-base
rules:
  tool_access:
    enabled: true
    default: block
    allow: [quote]
    max_args_size: 4096
hushspec-policies/policy.yaml · completeyaml
hushspec: "0.1.0"
extends: base.yaml
rules:
  secret_patterns:
    enabled: true
    patterns:
      - name: larkfield-api-key
        pattern: 'lark_live_[A-Za-z0-9]{24}'
        severity: error
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/policy.yaml
Output
policy     hushspec-policies/policy.yaml  extends hushspec-policies/base.yaml
grants     quote on server *  max_args_size 4096
guards     1 mcp-tool
           2 secret-leak
output     1 hook
approvals  none

The child compiles to two request guards, one output hook, and one grant: invoke quote on any server with arguments under 4,096 bytes. A refund request finds no grant at all. The host installs those controls and issues a capability for the intended server and agent; Policy Compilation shows the complete serialized scope.

A rule block the child declares replaces the parent's block whole

Under both merge and deep_merge, a declared rule block takes the parent's place entirely. Repeat every field whose restriction you want to keep.

Resolving one rule blockChoose what the child declares.
π₀base.yamlπ₁policy.yaml∅field defaultsdefaultblockallow[quote]max_args_size4096κtool_namequotemax_args_size4096π₀base.yamlπ₁child∅field defaultsdefaultblockallow[quote]max_args_size4096κtool_namequotemax_args_size4096

An omitted block is inherited whole

policy.yaml declares only secret_patterns, so tool_access resolves to the base block: default block, allow [quote], max_args_size: 4096. The default grant names quote with a 4,096-byte argument limit. Author a policy.

The tool_access block of base.yaml resolved under policy.yaml, strict.yaml, and incomplete.yaml, with the first default grant from each captured compile. Other rule blocks, extensions, and the runtime-assurance constraint are left out.

strict.yaml keeps quote, lowers the argument limit to 2,048 bytes, and requires an attested runtime by repeating the complete block.

hushspec-policies/strict.yaml · completeyaml
hushspec: "0.1.0"
extends: policy.yaml
rules:
  tool_access:
    enabled: true
    default: block
    allow: [quote]
    max_args_size: 2048
    require_runtime_assurance_tier: attested
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/strict.yaml
Output
policy     hushspec-policies/strict.yaml  extends hushspec-policies/policy.yaml
grants     quote on server *  max_args_size 2048, runtime assurance attested
guards     1 mcp-tool
           2 secret-leak
output     1 hook
approvals  none

The three strategies differ in what they do with extensions and with the parent as a whole:

  • deep_merge (default). Extension sub-blocks merge with their own functions: posture states by name, origin profiles by id. runtime_assurance and metadata are replaced whole when the child supplies them, and rule blocks are replaced whole, as under merge.
  • merge. Each rule or extension sub-block the child declares replaces the parent's. Omitted sub-blocks carry forward.
  • replace. The child replaces the parent. The extends chain is still loaded for source provenance, and no fields carry forward.

Whether a list is appended depends on the extension's merge function. For environment overlays, see Inherit & Merge Policies.

Setting one field resets the rest of the block

incomplete.yaml is valid YAML that looks as though it changes only the argument limit. The tool fields it omits deserialize to their own defaults: default becomes allow and allow becomes empty.

hushspec-policies/incomplete.yaml · intentionally incompleteyaml
hushspec: "0.1.0"
name: incomplete-override
extends: policy.yaml
rules:
  tool_access:
    max_args_size: 2048
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/incomplete.yaml
Output
policy     hushspec-policies/incomplete.yaml  extends hushspec-policies/policy.yaml
grants     * on server *  max_args_size 2048
guards     1 mcp-tool
           2 secret-leak
output     1 hook
approvals  none

The compiler emits a wildcard tool grant with the smaller size limit: an agent holding it may call refund and discount as freely as quote. The secret checks survive because the child omits secret_patterns. Inspect the resolved scope before installing any override, and use the strict.yaml form to keep a named-tool restriction.

Compilation turns the resolved document into guards, hooks, and a default scope

The loader parses the YAML, resolves and merges its local bases, and compiles the result into CompiledPolicy: request guards, output hooks, and a default capability scope. The host installs those pipelines and issues authority for its workload.

Policy loadingInspect a stage.
policy_hashrefused loadPpolicy.yamlℓreadload_policyπparseφfingerprintKkernelbuild_kernelρreceipthₛsource hashsource:hₚpolicy hashpolicy:policy_hashrefused loadPpolicy.yamlℓreadload_policyπparseφfingerprintKkernelbuild_kernelρreceipthₛsource hashsource:hₚpolicy hashpolicy:

The policy hash names the policy the kernel applies

SHA-256 over a JSON fingerprint of the parsed policy: its format, kernel settings, guard configuration, and default capabilities. Comments and formatting are not part of it. The kernel binds this hash into every receipt as policy_hash, and chio check prints it on its policy: line. Matching hashes mean two decisions ran under the same policy; a changed hash does not say which rule changed. Receipts.

In Rust · loader.rs:4414 lines
pub fn load_policy(path: &Path) -> Result<LoadedPolicy, PolicyError> {
    let contents = std::fs::read_to_string(path)?;
    let source_hash = hash_bytes(contents.as_bytes());

    if chio_policy::is_hushspec_format(&contents) {
        return load_hushspec_policy(path, source_hash);
    }

    let policy: ChioPolicy = serde_yml::from_str(&contents)?;
    policy.kernel.validate()?;
    let default_capabilities = build_runtime_default_capabilities(&policy)?;
    let runtime_hash = runtime_hash_for_chio_yaml(&policy, &default_capabilities)?;
    // …
}
The policy loader the CLI uses at the pinned revision, from one file to the kernel it builds. The source hash identifies the file’s bytes; the policy hash identifies the policy the kernel applies and is the value each receipt records.Write a policy

The separate evaluate interpreter returns Allow, Warn, or Deny directly from the policy and runs none of the compiled guards. chio check builds a short-lived compiled kernel instead, and Testing Guards & Policies matches each test to a deployment. External cloud-guardrail and threat-intel adapters take the control plane's separate external-guard configuration.

Read more in Policy Compilation, with the complete serialized scope, the rule mapping, and the compiler entry points.

Schema version

Required document headeryaml
hushspec: "0.1.0"

The supported version is 0.1.0. The hushspec key identifies the format, and validation rejects any other value. A document is a YAML mapping, and unknown root keys are rejected. A version-only document is valid and carries no explicit restrictions.

Top-level fields

Only hushspec is required. The other fields configure behavior, choose a base, or describe the policy for people and deployment tooling.

FieldTypeRequiredWhat it carries
hushspec
string
Yes
Required schema version: 0.1.0.
name
string
No
Human-readable policy identifier.
description
string
No
Free-form prose explaining intent.
extends
string
No
One base reference. The filesystem resolver expects a local path.
merge_strategy
enum
No
How this document folds into its parent. Defaults to deep_merge.
rules
object
No
Per-guard configuration.
extensions
object
No
Domain-specific add-ons: posture, origins, detection, reputation, runtime assurance, and the chio overlay.
metadata
object
No
Governance fields for people and deployment tooling. The compiler reads none of them.

Base policies

extends takes one reference string. resolve_from_path and create_composite_loader load local files, and a relative path resolves from the referring policy's directory. A parent may extend another file; resolution merges the chain back toward the child.

Reference or APIWhat it loadsHow to use it
extends: base.yaml
A file beside the child policy
Ship that file with the child, as in the example archive.
extends: ../base/team.yaml
A file relative to the child
Keep the directory relationship intact when deploying.
Absolute filesystem path
The named local file
The default resolver accepts paths outside the project directory.
rulesets::builtin_yaml(name)
Embedded YAML for a named built-in
Accepts a bare name, chio: prefix or hushspec: prefix; returns YAML to the Rust host.
rulesets::load_builtin(name)
A parsed and compiled built-in
A separate Rust API; the filesystem loader still reads built-in names as paths.
HTTP or HTTPS URL
Unsupported by the default loaders
Fetch and review the base as a local file first.

Built-in names: ai-agent, cicd, default, panic, permissive, remote-desktop, strict. The team example includes builtin-default.yaml as a file, copied from the public default ruleset. Review that base together with the child, since a child can replace its restrictions.

hushspec-policies/wrong-builtin.yaml · unsupported file referenceyaml
hushspec: "0.1.0"
extends: "chio:default"
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/wrong-builtin.yaml
Output
error[CHIO-CLI-POLICY]: invalid policy: failed to read HushSpec document at hushspec-policies/chio:default: No such file or directory (os error 2)
  help: fix the policy entry the message names, then run the command again
  code: urn:chio:error:policy:compile-failed
  docs: https://chio.computer/docs/reference/errors#error-policy-compile-failed

The filesystem loader reads chio:default as a file name beside the child and fails, and the command exits 2 before any control exists.

Cycles, missing bases, and resolution limits

The resolver compares canonical source paths and rejects a cycle with its chain. Default limits are 4 MiB per document and 32 documents in the inheritance chain, counting the starting document. A missing base or an invalid parent also fails resolution, even when the child uses replace. Policy Compilation describes the resolver APIs and limits.

Rule blocks

The rules object holds 14 optional blocks. A missing block installs no guard for that rule, and enabled: false skips it. Capability defaults are a separate output: omitting tool_access can produce a permissive default scope, so inspect both the guard list and the scope before installing a policy.

BlockStructCompiles to
forbidden_paths
ForbiddenPathsRule
ForbiddenPathGuard
path_allowlist
PathAllowlistRule
PathAllowlistGuard
egress
EgressRule
EgressAllowlistGuard, plus InternalNetworkGuard as its SSRF companion
secret_patterns
SecretPatternsRule
SecretLeakGuard for input checks; a SanitizerHook for output handling
patch_integrity
PatchIntegrityRule
PatchIntegrityGuard
shell_commands
ShellCommandsRule
ShellCommandGuard
tool_access
ToolAccessRule
McpToolGuard, plus the capability grants and their MaxArgsSize and MinimumRuntimeAssurance constraints
computer_use
ComputerUseRule
ComputerUseGuard
remote_desktop_channels
RemoteDesktopChannelsRule
RemoteDesktopSideChannelGuard
input_injection
InputInjectionRule
InputInjectionCapabilityGuard
browser_automation
BrowserAutomationRule
BrowserAutomationGuard
code_execution
CodeExecutionRule
CodeExecutionGuard
velocity
VelocityRule
VelocityGuard for invocation or spending limits; AgentVelocityGuard for per-agent or per-session request limits
human_in_loop
HumanInLoopRule
Constraint::RequireApprovalAbove { threshold_units } on the compiled grants

egress adds a companion internal-network check, so an allowed hostname still leaves private and metadata addresses refused. secret_patterns configures input checks and creates output handling, mapped in Policy Compilation.

Rule fields and defaults

These are the accepted wire names and Rust value types. A default applies when the enclosing block exists and the field is omitted; it never creates a missing block. Unknown rule or field names are rejected.

FieldTypeDefault
forbidden_paths.enabled
bool
true
forbidden_paths.patterns
Vec<String>
[]
forbidden_paths.exceptions
Vec<String>
[]
path_allowlist.enabled
bool
false
path_allowlist.read
Vec<String>
[]
path_allowlist.write
Vec<String>
[]
path_allowlist.patch
Vec<String>
[]
egress.enabled
bool
true
egress.allow
Vec<String>
[]
egress.block
Vec<String>
[]
egress.default
DefaultAction
block
secret_patterns.enabled
bool
true
secret_patterns.patterns
Vec<SecretPattern>
[]
secret_patterns.skip_paths
Vec<String>
[]
patch_integrity.enabled
bool
true
patch_integrity.max_additions
usize
1000
patch_integrity.max_deletions
usize
500
patch_integrity.forbidden_patterns
Vec<String>
[]
patch_integrity.require_balance
bool
false
patch_integrity.max_imbalance_ratio
f64
10.0
shell_commands.enabled
bool
true
shell_commands.forbidden_patterns
Vec<String>
[]
tool_access.enabled
bool
true
tool_access.allow
Vec<String>
[]
tool_access.block
Vec<String>
[]
tool_access.require_confirmation
Vec<String>
[]
tool_access.default
DefaultAction
allow
tool_access.max_args_size
Option<usize>
unset
tool_access.require_runtime_assurance_tier
Option<RuntimeAssuranceTier>
unset
tool_access.prefer_runtime_assurance_tier
Option<RuntimeAssuranceTier>
unset
tool_access.require_workload_identity
Option<WorkloadIdentityMatch>
unset
tool_access.prefer_workload_identity
Option<WorkloadIdentityMatch>
unset
computer_use.enabled
bool
false
computer_use.mode
ComputerUseMode
guardrail
computer_use.allowed_actions
Vec<String>
[]
remote_desktop_channels.enabled
bool
false
remote_desktop_channels.clipboard
bool
false
remote_desktop_channels.file_transfer
bool
false
remote_desktop_channels.audio
bool
true
remote_desktop_channels.drive_mapping
bool
false
input_injection.enabled
bool
false
input_injection.allowed_types
Vec<String>
[]
input_injection.require_postcondition_probe
bool
false
browser_automation.enabled
bool
false
browser_automation.allowed_domains
Vec<String>
[]
browser_automation.blocked_domains
Vec<String>
[]
browser_automation.allowed_verbs
Vec<String>
[]
browser_automation.credential_detection
bool
true
browser_automation.extra_credential_patterns
Vec<String>
empty
code_execution.enabled
bool
false
code_execution.language_allowlist
Vec<String>
[]
code_execution.module_denylist
Vec<String>
[]
code_execution.network_access
bool
false
code_execution.max_execution_time_ms
Option<u64>
unset
code_execution.max_scan_bytes
Option<usize>
unset
velocity.enabled
bool
true
velocity.max_invocations_per_window
Option<u32>
unset
velocity.max_spend_per_window
Option<u64>
unset
velocity.max_requests_per_agent
Option<u32>
unset
velocity.max_requests_per_session
Option<u32>
unset
velocity.window_secs
u64
60
velocity.burst_factor
f64
1.0
human_in_loop.enabled
bool
true
human_in_loop.require_confirmation
Vec<String>
[]
human_in_loop.approve_above
Option<u64>
unset
human_in_loop.approve_above_currency
Option<String>
unset
human_in_loop.timeout_seconds
Option<u64>
unset
human_in_loop.on_timeout
HumanInLoopTimeoutAction
deny

These blocks default enabled to false: path_allowlist, computer_use, remote_desktop_channels, input_injection, browser_automation, code_execution. Set enabled: true when installing them; the remaining blocks default it to true. In remote_desktop_channels, audio defaults to permitted while clipboard, file transfer, and drive mapping default to disabled.

Tool access constraints

Permit a tool before asking for confirmation on it. This document allows quote and refund, blocks discount, limits arguments, and requires attestation. Its confirmation pattern matches the allowed refund grant, so every refund waits for an approver such as your pricing lead.

hushspec-policies/tool-access.yaml · completeyaml
hushspec: "0.1.0"
name: scoped-pricing-tools
rules:
  tool_access:
    enabled: true
    default: block
    allow: [quote, refund]
    block: [discount]
    require_confirmation: [refund]
    max_args_size: 4096
    require_runtime_assurance_tier: attested
    prefer_runtime_assurance_tier: verified
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/tool-access.yaml
Output
policy     hushspec-policies/tool-access.yaml
grants     quote on server *   max_args_size 4096, runtime assurance attested
           refund on server *  max_args_size 4096, approval required, runtime assurance attested
guards     1 mcp-tool
output     none
approvals  refund on every call

max_args_size becomes MaxArgsSize, and require_runtime_assurance_tier becomes MinimumRuntimeAssurance. A matching require_confirmation produces RequireApprovalAbove with threshold_units: 0; at admission, the kernel holds a call under it as pending until a person approves that exact request. prefer_runtime_assurance_tier is an interpreter preference and compiles to no second minimum.

Workload identity requirements

workload.yaml adds this requirement to the tool-access document. Replace the trust domain and permitted identity paths with your operator's values.

Under rules.tool_access in workload.yamlyaml
require_workload_identity:
  scheme: spiffe
  trust_domain: larkfield.example
  path_prefixes: ["/agents/"]
  credential_kinds: [x509_svid]
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/workload.yaml
Output
policy     hushspec-policies/workload.yaml
grants     none  workload identity has no default-grant form
guards     1 mcp-tool
output     none
approvals  none

The compiler emits no default grants when required or preferred workload identity is present. The policy interpreter evaluates these identity fields, and the compiler encodes none of them as capability constraints. Workload Identity covers the host integrations that supply and evaluate identity evidence. Credential kinds are uri, x509_svid, and jwt_svid; the supported scheme is spiffe.

Conditions

Conditions live outside the YAML. A Rust caller passes a map of rule names to Condition values to evaluate_with_context; compile_policy takes no such map. The interpreter's decision describes that evaluation, separate from the compiled kernel pipeline.

PredicateInputMeaning
time_window
start, end, optional timezone and days
Match the runtime time against a window.
context
Key/value expectations
Match environment or values from the user, agent, session, request, deployment and custom maps.
all_of
Nested conditions
Require every child condition.
any_of
Nested conditions
For a nonempty list, require at least one child.
not
One nested condition
Invert that condition's result.

A false condition removes its rule from the effective policy and leaves the request to the remaining rules. Gating a deny-by-default tool rule on environment: production removes that rule whenever the environment is absent, so keep mandatory restrictions unconditional. Unknown rule names in the map are rejected with a denial, and recursion checks stop a nested evaluation beyond depth eight. Review composition, especially negation, as policy logic.

Extensions

The extensions object has a fixed set of sub-blocks, and unknown names are rejected. Each sub-block takes effect through the integration that reads it:

  • posture. Posture states, capabilities, budgets, and transition definitions. The compiler mapping names the installed enforcement path.
  • origins. Per-origin profiles with their own tool_access and egress overrides; the default behavior is deny or minimal_profile.
  • detection. Prompt-injection, jailbreak, and threat-intel detectors, regex and similarity based.
  • reputation. Reputation tiers, scoring weights, promotion and demotion triggers, and metrics requirements.
  • runtime_assurance. Runtime assurance tier and verifier configuration, interpreted by the runtime integration.
  • chio. Threshold approver configuration, plus descriptive integration fields for market hours, signing, namespaces, and rollback.

Within extensions.chio, market_hours, signing, k8s_namespaces, and rollback are carried configuration that compiles to no runtime guard. human_in_loop.approvers differs: the compiler requires an authenticated approver directory and refuses the plain compile entry point when that configuration is present. Use the threshold-aware compiler entry point.

Governance metadata

Metadata records who owns a policy and how it was reviewed, for people and deployment systems. The compiler reads none of it: approved_by is a label rather than an authenticated approval, and effective_date and expiry_date neither schedule activation nor revoke issued authority.

FieldTypeNotes
author
string
Free-form.
approved_by
string
Free-form.
approval_date
string
RFC 3339 recommended.
classification
enum
public | internal | confidential | restricted
change_ticket
string
Reference to your change-management system.
lifecycle_state
enum
draft | review | approved | deployed | deprecated | archived
policy_version
int
Internal version counter, separate from hushspec.
effective_date
string
Recorded intended start date.
expiry_date
string
Recorded intended expiry date.

Team policy example

This document combines a project tool allowlist, filesystem boundaries, egress rules, secret detection, and velocity limits. The export tool is allowed explicitly and matched by confirmation. Its local base, builtin-default.yaml, ships in the archive.

hushspec-policies/team-policy.yaml · completeyaml
hushspec: "0.1.0"
name: larkfield-pricing-data
description: Pricing analysis with scoped read, query, and export tools.
extends: builtin-default.yaml
merge_strategy: deep_merge

rules:
  tool_access:
    enabled: true
    default: block
    allow:
      - read_file
      - list_directory
      - search_files
      - sql
      - export_to_csv
    block:
      - run_command
    require_confirmation:
      - export_to_csv
    max_args_size: 8192

  forbidden_paths:
    enabled: true
    patterns:
      - "**/.env*"
      - "**/secrets/**"
      - "**/.aws/credentials"
      - "**/id_rsa*"
    exceptions:
      - "/workspace/.env.testing"

  path_allowlist:
    enabled: true
    read:
      - "/workspace/src/**"
      - "/workspace/config/*.yaml"
    write: ["/workspace/exports/**"]
    patch: []

  egress:
    enabled: true
    default: block
    allow:
      - "pricing.larkfield.example"
      - "pypi.org"

  secret_patterns:
    enabled: true
    patterns:
      - name: aws_access_key
        pattern: "AKIA[0-9A-Z]{16}"
        severity: critical
      - name: larkfield-api-key
        pattern: "lark_live_[A-Za-z0-9]{24}"
        severity: error

  velocity:
    enabled: true
    max_invocations_per_window: 200
    window_secs: 60
    burst_factor: 1.5

  human_in_loop:
    enabled: true
    require_confirmation:
      - "export_*"
    timeout_seconds: 300
    on_timeout: deny

extensions:
  chio:
    market_hours:
      tz: "America/New_York"
      open: "09:30"
      close: "16:00"
      days: [Mon, Tue, Wed, Thu, Fri]

metadata:
  author: "larkfield-pricing"
  approved_by: "Mara Okafor"
  classification: confidential
  lifecycle_state: deployed
  policy_version: 7
  effective_date: "2026-10-01"
Terminal · beside hushspec-policiesbash
chio policy explain hushspec-policies/team-policy.yaml
Output
policy     hushspec-policies/team-policy.yaml  extends hushspec-policies/builtin-default.yaml
grants     read_file on server *       max_args_size 8192
           list_directory on server *  max_args_size 8192
           search_files on server *    max_args_size 8192
           sql on server *             max_args_size 8192
           export_to_csv on server *   max_args_size 8192, approval required
guards     1 forbidden-path
           2 velocity
           3 egress-allowlist
           4 internal-network
           5 mcp-tool
           6 secret-leak
           7 patch-integrity
           8 path-allowlist
output     1 hook
approvals  export_to_csv on every call

chio policy explain compiles the document only; chio policy explain --tool <T> --params <JSON> walks one call through the guards in order. Adapt the tools, paths, and domains to your application, then send allowed and refused requests through its host. The child's forbidden_paths replaces the base's entire list, so base entries it omits, such as **/.ssh/**, no longer apply. The market-hours overlay and the metadata are carried as description and set no trading window or activation date.

Validation failures

FailureLayerAction
Unknown field or rule name
Parsing
Use the exact names in this reference. conditions belongs to a separate API.
Unsupported hushspec version
Validation
Use the supported schema version; a recognized format can still fail validation.
Scalar or sequence instead of a mapping
Parsing
Start with a YAML object containing hushspec.
Oversized quoted whitespace run
Parser precheck
Correct the scalar; the precheck bounds pathological parser input.
Missing base, cycle, URL or resolution limit
Resolution
Ship local bases, break the cycle and keep the chain within limits.
Invalid or unsafe regex
Validation or compilation
Correct patterns in secret_patterns, shell_commands or patch_integrity.
Invalid default action or severity
Parsing
Default actions are allow or block. A secret pattern requires severity: critical, error or warn.
Undefined posture state
Validation
Define the initial and transition states. A transition cannot target *.
Threshold approvers without an authenticated directory
Compilation
Use the threshold-aware compiler with the operator's directory.

Parsing and validation check structure and references. Validation does not link every origin profile to a posture state or enforce metadata dates, so inspect the resolved scope and exercise application requests, including refusals, before deploying a change.

The field inventory is generated from the public rule definitions. chio policy explain lists the controls a document compiles to; a signed receipt comes from executing a call, as Testing Guards & Policies shows.

Next: change a working policy