> ## 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.

# Troubleshooting: agent outbound-call and voice-clone guard codes

> Resolve OUTBOUND_CALLING_DISABLED (409), triage the reserved GUARDRAIL_VIOLATION code, and satisfy VOICE_CLONE_CONSENT_REQUIRED (422) before your agent can place a call or clone a voice.

# Troubleshooting: agent outbound-call and voice-clone guard codes

Three guard codes stop an agent call or a voice-clone request before any
telephony or synthesis work begins. Each one blocks a different surface —
the agent's outbound-calling toggle, the agent's guardrail envelope, and
the voice-clone consent attestation — and each fails fast at the gate, so
nothing downstream (a call record, a clone row, a synthesis credit) is
created. This page tells you which gate fired, which surface to re-check,
and when to escalate instead of retrying.

## Code matrix — symptom to fix

| Error code                     | HTTP   | Surface it fires on                                             | What it means                                                                                               | First move                                                                                                   |
| ------------------------------ | ------ | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `OUTBOUND_CALLING_DISABLED`    | 409    | `POST /api/v1/agents/:id/calls`                                 | The agent's outbound-calling toggle is off — no call record is created                                      | Enable the toggle first — see [Outbound calling disabled](#outbound-calling-disabled)                        |
| `GUARDRAIL_VIOLATION`          | varies | Agent `/chat` and `/invoke` traffic                             | Listed as a reserved code in the error-codes catalog; no public endpoint throws it today                    | Triage only, do not code a fix — see [Guardrail violation reserved code](#guardrail-violation-reserved-code) |
| `VOICE_CLONE_CONSENT_REQUIRED` | 422    | `POST /api/v1/voice/clones`, `POST /api/v1/voice/clones/upload` | The consent attestation your request carried failed the biometric-voice gate before any DB or provider work | Complete or re-file the attestation — see [Voice clone consent required](#voice-clone-consent-required)      |

## Outbound calling disabled

`POST /api/v1/agents/:id/calls` is the agent-originating outbound-call
endpoint. It walks a short chain of guards before it originates anything:
the agent must exist (`AGENT_NOT_FOUND` 404), must not be archived
(`AGENT_ARCHIVED` 400), and must have outbound calling switched on. The
`OUTBOUND_CALLING_DISABLED` 409 fires on the last check — the toggle is a
per-agent setting operators flip deliberately, and placing a call spends
balance, so the route refuses to originate for a disabled agent instead of
defaulting open.

Symptoms:

* The error message names one fix: enable the toggle.
* Your integration is fine; the failure is repeatable until the toggle
  flips, so a retry loop returns the same 409 every time.
* No call record, no billing event, no origination — the guard runs before
  any of those are touched.

Fix — enable the toggle, then re-send the call request:

```http theme={null}
PATCH /api/v1/agents/:id/outbound-calling
{
  "enabled": true
}
```

The same endpoint reads the current state with `GET`, and carries the
agent's default caller ID alongside the toggle — set it with a
`caller_id` field on the same PATCH body (send `caller_id: null` to clear
and fall back to the tenant default). Verify the agent id from
`GET /api/v1/agents` first; a bad id returns `AGENT_NOT_FOUND`, not this
code.

When to escalate instead: never for the toggle itself — it is a deliberate
per-agent control, tenant-owned end to end. Escalate only if the PATCH
route itself errors (a 4xx validation refusal, or a 5xx) or the toggle
reads back `true` from the GET while `POST .../calls` still returns the
409 — that mismatch narrows the window to the update you made, so capture
the PATCH response and one failing 409 envelope with its request id and
timestamps.

What NOT to try:

* **Do not** treat the 409 as a rate limit or a carrier block and back off
  exponentially — it fires identically until the config changes.
* **Do not** escalate a downstream guard (TCPA dialing window, balance,
  destination block) under this page — those have their own runbooks; this
  one owns only the pre-origination agent toggle.

## Guardrail violation reserved code

`GUARDRAIL_VIOLATION` appears in the
[error codes catalog](/reference/error-codes) with the status `varies`,
as a *reserved* AI-guardrail code. Reservation means the code is held in
the platform's error-code enum for SDK stability and forward
compatibility — no public endpoint throws it today, and guardrail
failures still surface through other codes.

Confirmed facts:

* No public endpoint (`/chat`, `/invoke`, graph test-run, voice-agent turn)
  throws it. Internal comments reference the stream path, but the code
  itself is unthrown — treat this page as triage.
* Guardrail failures surface today as `AI_PARSE_FAILED` (422) or
  `VALIDATION_ERROR` (422) on the `/chat` / `/invoke` routes — parse or
  schema mismatches in the agent's output, not residual guardrail verdicts
  on the envelope.
* The reserved code's HTTP status varies — expected `422` on `/chat`
  run-and-validate, `502` when the provider loop degrades.

If a customer's API capture shows a literal `GUARDRAIL_VIOLATION` response:

1. Capture the exact HTTP status, the `message` and `details` fields, and
   the request id off the envelope.
2. Check whether the response came through an SDK or a wrapper that
   remaps the model's structured output — the raw envelope matters more
   than the mapped shape.
3. Escalate with the raw envelope and the two request ids bracketing the
   change to support — this code is not supposed to surface on end-user
   calls today, so a 422 with it is a platform signal, not a tenant
   config issue.

What NOT to try:

* **Do not** write a fix branch that "handles" `GUARDRAIL_VIOLATION` on
  your /chat /invoke integration — the code is reserved, not thrown; the
  false guard branch is dead code.
* **Do not** assume your agent is blocked by a guardrail because the code
  appears in the catalog — the catalog holds the reservation, not the live
  behavior.

## Voice clone consent required

Every voice-clone call (`POST /api/v1/voice/clones` for call-sourced
cloning, `POST
/api/v1/voice/clones/upload` for a sample upload, and any design or design-
upload flow that lands on the same gate) runs a consent gate first — the
attestation you send is validated *before* the route touches the database,
a provider, or any credit. The gate throws 422 with
`VOICE_CLONE_CONSENT_REQUIRED` when the attestation is missing or
incomplete, and that is a deliberate fail-fast, not a transient condition.

Attestation fields and the gate order:

* `biometric_consent_acknowledged` must be `true` — the acknowledgement
  that your application carries biometric-privacy obligations (BIPA /
  CUBI / EU AI Act Art 50) for a cloned voice. Missing it throws with
  `missing_field: "biometric_consent_acknowledged"`.
* `voice_owner_relationship` must be a non-empty classify string — the
  route accepts the `self | employee | actor_with_release |
  customer_with_written_consent | other` vocabulary; any other input
  throws with `missing_field: "voice_owner_relationship"`.
* One of `voice_owner_consent_evidence_url` (an HTTPS URL to the written
  evidence — ≥50 characters for the text variant) or
  `voice_owner_consent_text` (a free-form attestation statement, ≥ 50
  characters on a text-only attestation) must be present. Missing both
  throws with
  `missing_field: "voice_owner_consent_evidence_url |
  voice_owner_consent_text"`; a text that is too short or too long throws
  with `field: "voice_owner_consent_text"` plus the cap bound.

Symptoms:

* The error is deterministic — missing attestation fields return it
  identically every time you retry.
* The gate passes *before* any clone row is created, so a correct retry
  is a genuine first attempt, not a duplicate; you are never charged for
  a blocked request.
* The route rejects *both* evidence text and evidence URL being absent —
  one of the two is required, and the attestation text cap is applied on
  both the length bounds.

Fix — fill the attestation fields on the retry. The attestation shape is
the same compact body the route's validation schema accepts; on the
call-sourced path it travels with the `source_call_id` and on the upload
path with the sample. Resubmit with every required field populated and a
consent text at or above the length floor, or a HTTPS evidence URL that
points at the signed consent. The error's `details.missing_field` (or
`details.field` on a length violation) names exactly which gate failed, so
there is one retry per field — not several blind ones.

When to escalate instead: never because of the gate itself — it is a
tenant-owned consent control, and the customer fixes it in the request.
Escalate if the API refuses every attestation shape you send, if the
`details` names a field the schema does not validate, or if a 5xx replaces
the 422 after a complete attestation — all of those narrow the fix to
the route layer, not to your compliance posture.

## Triage table — fix or escalate

| Error code                     | Fix vs escalate                         | Tenant-owned surface                              | When to escalate                                                                        |
| ------------------------------ | --------------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `OUTBOUND_CALLING_DISABLED`    | Fix — flip the toggle                   | `PATCH /api/v1/agents/:id/outbound-calling`       | The PATCH errors, or the GET shows enabled while place-call still returns 409           |
| `GUARDRAIL_VIOLATION`          | Escalate — reserved, not tenant-visible | The API response envelope itself                  | A literal `GUARDRAIL_VIOLATION` on a captured envelope — that is a platform signal      |
| `VOICE_CLONE_CONSENT_REQUIRED` | Fix — complete the attestation          | The consent attestation body on the clone request | The gate refuses every attestation shape, or the `details` field contradicts the schema |

The first two codes are deliberate, tenant-facing gates — flipping the
right surface permanently retires them. The third is a reserved code that
maps no runnable path today.

## What NOT to try

* **Do not retry in a loop on the toggle code** — `OUTBOUND_CALLING_DISABLED`
  fires identically on every request until the config changes; spend the
  backoff on the PATCH instead.
* **Do not write a fix branch for `GUARDRAIL_VIOLATION`** — reserved
  codes are placeholders, not endpoints; the false branch is dead code.
* **Do not shorten the attestation text below the floor to beat the
  length cap** — that field names its bound; the gate validates exactly
  one thing at a time, and the retry must carry all the required fields.

## See also

* [Error codes reference](/reference/error-codes) — the catalog these
  codes live in; `GUARDRAIL_VIOLATION` is recorded as reserved there.
* [Voice biometrics failures](/troubleshooting/voice-biometrics-failures)
  — the sidecar connect / auth / availability codes on enroll and
  verify this page does not own.
* The agent outbound-calling toggle on the dashboard — the same code the
  GET/PATCH route exposes: **Voice agents → Agent → Outbound calling**.
* [Voice destination blocks](/troubleshooting/voice-destination-blocks)
  — the post-toggle 4xx lane when the caller id or destination is what
  actually blocks the dial.
