Pre-Approval Policies
Every secret use requires an active pre-approval policy that matches the (secret, tool, host) triple. Without a matching policy, the request is denied, even if the agent has the secret.use:<name> capability.
Policies answer the question: "Is this agent allowed to use secret X with tool Y to reach host Z?"
Policies are persisted to SQLite and survive daemon restarts. No re-registration is required after restarting agentd.
Creating a Policy
ash secrets policy add \
--label "OpenRouter API access" \
--secret "openrouter-key" \
--tool "web.fetch" \
--host "openrouter.ai"
All fields:
ash secrets policy add \
--label "Nightly analytics batch" \
--secret "analytics-api-key" \ # glob: which secrets
--tool "web.fetch" \ # glob: which tools
--host "api.analytics.example.com" \ # optional: which host
--expires "2026-12-31T00:00:00Z" \ # optional: expiry
--max-uses 100 \ # optional: use limit
--trust-level "trusted" # optional: agent trust level floor
Policy Fields
| Field | Type | Description |
|---|---|---|
--label | string | Human-readable name for audit entries |
--secret | glob | Matches secret names (openai-*, db-password, *) |
--tool | glob | Matches tool names (web.fetch, sandbox.exec, *) |
--host | glob | Optional. Matches destination host for network tools |
--expires | RFC3339 | Optional. Policy stops applying after this time |
--max-uses | integer | Optional. Policy disabled after N auto-approvals |
--trust-level | level | Optional. Only applies to agents at this trust level or above |
Listing Policies
ash secrets policy list
# ID LABEL SECRET TOOL EXPIRES
# a1b2c3d4-... OpenRouter API access openrouter-* web.fetch never
# e5f6a7b8-... Nightly analytics batch analytics-* web.fetch 2026-12-31
Inspecting a Single Policy
ash secrets policy show a1b2c3d4-e5f6-...
# ID: a1b2c3d4-e5f6-...
# Label: OpenRouter API access
# Secret: openrouter-*
# Tool: web.fetch
# Host: openrouter.ai
# Expires: never
# Max uses: unlimited
# Use count: 42
# Created by: operator
# Created at: 2026-01-15T10:00:00Z
Removing a Policy
ash secrets policy remove <policy-id>
Immediately revokes the policy. Subsequent secret resolutions that would have matched this policy are denied.
Manifest-Declared Policies
Policies can be declared in the manifest so they are applied automatically at spawn time:
spec:
capabilities:
- secret.use:openrouter-key
secret_policy:
- label: "LLM completions"
secret_pattern: "openrouter-key"
tool_pattern: "web.fetch"
host_pattern: "openrouter.ai"
max_uses: 1000
Manifest-level policies are scoped to the specific agent spawned from that manifest. Runtime policies created via ash secrets policy add can optionally be scoped by agent_matcher.
Policy Matching
When an agent uses a secret handle in a tool call, agentd checks all active policies for a match:
- Does
secret_patternmatch the secret name? - Does
tool_patternmatch the tool being invoked? - If
host_patternis set, does it match the destination host in the request? - Is the policy not expired?
- Is the policy under its
max_useslimit? - If
agent_matcheris set, does the calling agent match?
If all matching conditions pass, the policy approves the use, increments its use_count, and records the policy ID in the audit trail.
If no policy matches, the request is denied with NoPolicyMatch and the event is logged as a warning. Full HITL queue routing for unmatched requests is planned for a future phase.