1. The least agency checklist
Walk every key — new or existing — through these six gates in the key editor (/console/token). Setting any of them requires the Developer role or
above; the two policy planes (§5–6) are authored separately and bound here.
model_limits — pin the models
model_limits — pin the models
Set
model_limits to the exact list this agent needs (and enable
model_limits_enabled). A call to any model outside the list is rejected
before it leaves the gateway, so a hijacked agent can’t escalate to a
pricier or more capable model.
Check: is the list as short as the job allows — ideally one model?
Depth: Model limits.allow_ips — pin the source
allow_ips — pin the source
Set
allow_ips to the source addresses or CIDR the agent actually calls
from. A leaked key presented from anywhere else is rejected at the auth
layer. Empty means all IPs are allowed.
Check: for a fixed-host or scheduled agent, is the list non-empty and
scoped to that egress? Depth:
IP allow-list.credit_limit_usd — cap the spend
credit_limit_usd — cap the spend
Set
credit_limit_usd to a ceiling the agent should never cross in its
lifetime. The gateway enforces it against the key’s spend. 0 means
unlimited — a runaway loop can drain your whole balance.
Check: is the cap a real budget, not 0? Depth:
Quota, cap & expiry.expired_time — give it a deadline
expired_time — give it a deadline
Set
expired_time to an absolute expiry — the end of the sprint, the
deployment, or the CI run. -1 means never expires. A short-lived key
can’t linger as forgotten attack surface.
Check: does an ephemeral or contractor key have a real expiry, not
-1? Depth: Expiring keys.guardrail_id — bind a content policy
guardrail_id — bind a content policy
Attach a guardrail via
guardrail_id so the
request (and, where supported, the response) text is screened for PII,
secrets, and injection intent before it reaches the model.
Check: does a key that handles sensitive prompts have a guardrail
bound, or inherit a workspace default? See §5.firewall_policy_id — bind a tool policy
firewall_policy_id — bind a tool policy
Attach a firewall policy via
firewall_policy_id so
every tool call, MCP dispatch, and egress this key issues is evaluated
against an allow-list of what the agent legitimately needs.
Check: does an agent that calls tools have a firewall policy bound, or
inherit the workspace default? See §6.2. What / how often / where
Three questions turn the checklist from a one-time chore into a posture.What
The six gates above, in order:
model_limits → allow_ips →
credit_limit_usd → expired_time → guardrail_id →
firewall_policy_id.How often
On every key at creation, and on a recurring review — when an
agent’s scope changes, when you rotate a key,
and on a fixed cadence for long-lived keys.
Where
In the console key editor (
/console/token), as a Developer+. The two
policies are authored in their own consoles, then bound on the key.3. One concrete least-agency key
A scheduled agent that summarizes support tickets with one cheap model, from one host, needs almost no agency. A fully hardened key:| Field | Value | Why |
|---|---|---|
model_limits | one summarization model | can’t escalate to a frontier model |
allow_ips | the scheduler’s egress CIDR | a leaked key is useless elsewhere |
credit_limit_usd | a weekly ceiling | a runaway loop can’t drain the balance |
expired_time | end of the deployment | auto-expires, can’t linger |
guardrail_id | a PII-masking guardrail | request text is screened |
firewall_policy_id | allow-lists only its tools | no surprise tool calls |
4. The /v1 relay call vs the console
The checklist is configured in the console with your session (a Developer+ user). Your agent never touches those config routes — it presents its scoped relay key (sk-orca-…) on the /v1/* inference calls, and the
limits and bound policies above are enforced on each one.
model_limits doesn’t include openai/gpt-4o-mini, this call is
rejected before it leaves the gateway. If the caller’s IP isn’t in
allow_ips, it’s rejected at the auth layer. The agent code stays the same;
the key decides the blast radius.
5. Gate 5 — the bound guardrail
guardrail_id binds a workspace-scoped, ordered content policy to the
key. Resolution is the key’s explicit guardrail (if it exists and is enabled),
else the workspace default, else none.
Guardrails are a strict off-switch when disabled: a disabled or deleted
guardrail_id means the key gets no guardrail — it does not fall back
to the workspace default. This is the opposite of the firewall plane (§6), so
verify the bound guardrail is enabled, not just attached.block, mask, or flag. The
PII Shield preset, for instance, masks PII in the request before it ever
reaches the model. Author and attach guardrails as Developer+ — see
Guardrails and
Bind policies.
6. Gate 6 — the bound firewall policy + gateway scope
firewall_policy_id binds a workspace-scoped tool-call policy. It governs
the actions an agent takes — advertised tools, model-emitted tool_calls,
MCP dispatches, and outbound egress — against an ordered rule list whose
verdicts are allow, audit, deny, sanitize, pending_approval, or
cap_cost.
The firewall plane resolves differently from guardrails: a disabled
attached firewall policy falls back to the workspace default, it does not
turn enforcement off. So binding a policy and disabling it reverts the key to
the workspace default — it never silently goes unprotected.
tight / balanced / permissive), with one-click undo. See
Firewall §8.
7. After the checklist
Secure-agents baseline
The recommended starting posture — one autonomy switch, then tune from
real traffic.
Bind policies
How
guardrail_id and firewall_policy_id attach and resolve.Excessive agency
The threat this checklist is built to contain.
Leaked key
What to do the moment a scoped key is exposed.
