> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent governance policies: guardrails, budget caps, model allowlists, approval gates

> Compose the four governance layers every production agent needs — prompt guardrails on safety_config, spend caps on cost and token budgets, model allowlists, and a separation-of-duties approval gate on prompt promotion.

# Agent governance policies

A production agent needs four distinct governance controls, and Orbit ships one for each on different fields of the agent (or organization) record. Use them together: prompt guardrails bound **what the agent says**, budget caps bound **what it spends**, the model allowlist bounds **which models it can resolve to**, and the approval gate bounds **who can promote a prompt change to production**.

| Layer                                                             | Scope                                                               | Where it lives                                                                                                              |
| ----------------------------------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| [Prompt guardrails](#prompt-guardrails)                           | Content safety on input, output, and tool calls                     | `safety_config` on the agent                                                                                                |
| [Budget caps](#budget-caps)                                       | Dollar caps per run / conversation, token budgets, daily token caps | `config.max_cost_per_run_cents`, `config.max_cost_per_conversation_cents`, `config.token_budget`, `config.downgrade_ladder` |
| [Model allowlists](#model-allowlists)                             | Which served models an override may resolve to                      | Platform allowlist; validated at every write boundary and every resolver                                                    |
| [Separation-of-duties approvals](#separation-of-duties-approvals) | A reviewer other than the author promotes prompt versions           | Org toggle `settings.agents.require_prompt_promotion_approval`                                                              |

## Prompt guardrails

Guardrails are part of the agent itself — set them under `safety_config` on create (`POST /agents`) or update (`PUT /agents/:id`). There is no separate guardrails endpoint.

* **`prompt_injection`** — screens inbound user text for injection probes (prompt extraction, persona jailbreaks, encoding tricks) before the turn runs. An activated probe is refused instead of answered.
* **`content_filter` / `harmful_content`** — blocks disallowed topic classes on the output.
* **`blocked_topics`** — a tenant-defined denylist of subject matter (for example "refund policy changes", "competitor pricing"). Anything in the list is refused.
* **`pii_detection` / `pii_redaction`** — detects PII in inbound or outbound text and substitutes `[REDACTED]` before it is stored or shown.
* **`pii_egress`** — scrubs the universal PII floor (email, phone, SSN, payment card) inside every tool call's arguments at dispatch, so PII never leaves Orbit through a connector.
* **`sensitive_words`** — a tenant-maintained word/phrase list that must never appear in output.
* **`max_response_length`** — caps the assistant message length.
* **`approval_required`** — suspends runs for human approval when set.

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/agent_abc123 \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "safety_config": {
      "prompt_injection": true,
      "content_filter": true,
      "pii_detection": true,
      "pii_redaction": true,
      "pii_egress": true,
      "blocked_topics": ["internal processes"],
      "max_response_length": 2000
    }
  }'
```

See [Creating agents](/agents/creating-agents) for the full `safety_config` field list, the [Sensitive-words guardrail](/agents/sensitive-words-guardrail) page for list management, and [Guardrail effectiveness](/agents/guardrail-effectiveness) to measure how often each gate fires on live traffic.

## Budget caps

Compose two families, both written per agent, that bound spend in two units:

**Dollar-denominated** — hard caps the run refuses to cross:

* `max_cost_per_run_cents` — aggregate cost of all LLM calls inside one run (one turn, tool-call iterations included).
* `max_cost_per_conversation_cents` — lifetime cost of a conversation; probed before every LLM iteration, so a capped conversation refuses further turns.

Both accept `0`–`10000` cents; an exceeded cap ends the run with a final `error` event (`COST_LIMIT` / `CONVERSATION_COST_CAP_REACHED`). Full semantics in [Agent cost controls](/agents/cost-controls).

**Token-denominated** — a progressive ladder that steps the model down instead of hard-stopping:

* `config.token_budget` — a per-conversation token allowance for this agent (`1`–`1_000_000_000`).
* `config.downgrade_ladder.daily_token_cap` — the agent's total tokens per UTC day.
* `config.downgrade_ladder.steps` — up to ten `{ at_percent, model }` rungs whose `at_percent` thresholds ascend strictly; each names an allowlisted model (see below). As daily utilization passes a threshold, new turns resolve to the cheaper model. A breached cap with no usable step reports the breach but keeps the primary model — an agent never resolves to an unvalidated id.

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/agent_abc123 \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "token_budget": 80000,
      "downgrade_ladder": {
        "daily_token_cap": 2000000,
        "steps": [
          { "at_percent": 50, "model": "claude-sonnet-4-6" },
          { "at_percent": 80, "model": "claude-haiku-4-5" }
        ]
      }
    }
  }'
```

A bad shape (non-integer, out of bounds, unsorted thresholds, more than ten steps, or a non-allowlisted model) is rejected with `422` at create/update.

## Model allowlists

Agent models resolve only from the served-Claude catalog. Every surface that names a model — the `model` field, `config.model_fallbacks`, `config.model_routing`, `config.budget_downshift_model`, and each `downgrade_ladder.steps[].model` — is checked against the allowlist:

* **Write boundaries** (create/update agent, model-routing addresses) reject a non-allowlisted id with a `422` validation error.
* **Resolvers** (model routing, fallback cascade, budget downshift, token-guardrail ladder) read with a defuse posture: a stored but no-longer-allowlisted override is ignored and the resolver falls back to a valid canonical model, logging a `model_router.override_rejected` metric. A stale override never routes a live turn to an unvalidated id.

Keep overrides pointed at the canonical served models; after a model retirement, an untouched legacy id on the agent row keeps working until you change it.

## Separation-of-duties approvals

Saved [agent versions](/agents/agent-versions) move a prompt change from candidate to production through `POST /agents/:id/versions/:vid/promote` (or the `prompt-rollback` alias). By default anyone with write access may promote. Turn on the org gate so the operator who **authored** a version cannot also **promote** it — the author ≠ approver control SOC2/HIPAA change-management asks for on AI behaviour.

```bash theme={null}
# Owner/admin: enable the org-wide gate
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/prompt-promotion-approval/settings \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "require_prompt_promotion_approval": true }'
```

With the gate on:

* The promoter must be a different authenticated user than the version's author (the version row's recorded creator). A self-promotion returns `403`.
* Auto-minted or API-key versions with no attributable author may be promoted — there is no identifiable self-promotion to block, and the audit row records the promoter.
* Roles do not exempt anyone: an owner or admin who authored the version still cannot approve their own change.
* Every promotion — allowed or blocked — lands in the agent audit chain, so the approval trail is reconstructable after the fact.

The gate is opt-in per organization and off by default; an org that never enables it sees no behaviour change. Pair it with [Human-in-the-loop oversight](/agents/human-in-the-loop-oversight) for runtime approvals, which pauses sensitive tool calls for a human in the loop rather than gating prompt promotion.

## Related pages

* [Creating agents](/agents/creating-agents)
* [Agent cost controls](/agents/cost-controls)
* [Agent versions](/agents/agent-versions)
* [Guardrail effectiveness](/agents/guardrail-effectiveness)
* [Sensitive-words guardrail](/agents/sensitive-words-guardrail)
* [Human-in-the-loop oversight](/agents/human-in-the-loop-oversight)
