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

# Orby campaign diagnostics

> Ask Orby whether a campaign is ready to send, why it failed or paused on its own, and which governance rules apply to it: three read-only diagnostics answered from your live campaign data.

# Orby campaign diagnostics

Three questions come up about campaigns more than any others: *can this send?*, *why did it fail?*, and *what rules apply to it?* Orby answers all three from your live workspace data with three read-only diagnostic tools: `campaign_check_readiness`, `campaign_failure_reason`, and `campaign_governance_summary`.

All three are read-only. They inspect a campaign and report; they never send, never enqueue, and never change data, so they answer immediately without the proposal-and-approval step that data-changing tools require. The same is not true of the campaigns family's action tools, `pause_campaign` and `resume_campaign`: those propose a change and wait for your explicit approval, exactly as described in [Tool actions: proposal and approval](https://docs.orbit.devotel.io/guides/orby-in-dashboard.md#tool-actions-proposal-and-approval). This guide covers the read-only half: what each diagnostic reports and how to read its answer.

As with every Orby tool, the diagnostics run under your signed-in operator session and role. They read only what your role can already read (`campaigns:read`), scoped to your organization.

## `campaign_check_readiness` — can this send?

Ask in plain language:

> "Is the Spring Promo campaign ready to send?"

Orby resolves the campaign (using `campaign_search` first if it needs the id) and runs the same pre-launch dry run the dashboard's launch banner reads. The dry run sends nothing, bills nothing, and enqueues nothing, so it is safe to ask as often as you like while you tune a campaign.

The answer is grounded in `ready_to_launch`, which is true only when all five of these hold:

1. **No blocking warnings.** `warnings` is empty: nothing flagged about the audience, the cost estimate, quiet hours, personalization tags, or the journey configuration.
2. **A deliverable audience.** `audience.deliverable` is greater than zero after suppressed, opted-out, missing-address, and hold-out recipients are netted out.
3. **Sufficient balance.** `cost.sufficient` is true: your wallet balance covers the estimated cost.
4. **A reachable primary provider.** `channel_waterfall.primary_provider_available` is true for the campaign's channel.
5. **Provider checks that actually passed.** `provider_readiness.status` is `pass`. A status of `unverified`, meaning the connection state could not be confirmed, is not a pass and keeps `ready_to_launch` false.

A representative answer when one check fails:

```json theme={null}
{
  "channel": "sms",
  "ready_to_launch": false,
  "audience": {
    "total_in_audience": 12480,
    "deliverable": 11905,
    "suppressed": 214,
    "opted_out": 96,
    "unreachable": 265,
    "held_out": 0
  },
  "cost": {
    "formatted_total_usd": "$95.24 USD",
    "formatted_balance_usd": "$41.10 USD",
    "sufficient": false
  },
  "channel_waterfall": {
    "primary": "sms",
    "primary_provider_available": true,
    "primary_channel_connected": true
  },
  "provider_readiness": { "status": "pass" },
  "warnings": [
    "Insufficient credits to launch. Estimated cost $95.24 USD exceeds wallet balance $41.10 USD."
  ]
}
```

When `ready_to_launch` is false, the `warnings` array names the specific failing checks, and Orby quotes those rather than guessing at a cause. When it is true, the same payload gives you the projected scale: deliverable recipients, estimated cost against balance, and any quiet-hours deferral to expect.

## `campaign_failure_reason` — why did it fail?

> "Why did the Spring Promo campaign fail?"

Orby reads the cause the platform recorded on the campaign: `failureReason`, with its machine-readable `failureCode`, the longer `failureDetail`, and the `failedAt` timestamp, plus `autoPausedReason` when the platform paused the campaign itself on a circuit-break. The sent, delivered, and failed counters come along so the cause reads with its scale.

A campaign the platform auto-paused mid-send reads like this:

```json theme={null}
{
  "campaignId": "cmp_8f21c04a6b",
  "status": "paused",
  "hasFailure": true,
  "failureReason": null,
  "failureCode": null,
  "failureDetail": null,
  "failedAt": null,
  "autoPausedReason": "Auto-paused after the delivery failure rate crossed the circuit-break threshold.",
  "sent": 4210,
  "delivered": 3122,
  "failed": 986
}
```

`hasFailure` is true when either a failure reason or an auto-pause reason is recorded. From your side, "it failed" and "it stopped on its own" are the same question, and both are answered here. When `hasFailure` is false there is no recorded failure, and Orby says so plainly instead of inventing a cause. If the answer leads you to act, for example pausing a misbehaving campaign, that step is a data-changing tool and pauses on the normal approval card before anything runs.

## `campaign_governance_summary` — what rules apply?

> "What rules apply to the Spring Promo campaign?"

Orby returns the governance rules in force for that one campaign in a single read: the A/B experiment block, the control hold-out cohort, the quiet-hours window that actually applies (together with the setting it came from), and your organization's frequency-cap rules, each flagged with whether it bites on this campaign's channel.

```json theme={null}
{
  "experiment": {
    "ab_test_enabled": true,
    "variant_count": 2,
    "variants": [
      { "name": "Control copy", "sample_percent": 50 },
      { "name": "Short copy", "sample_percent": 50 }
    ],
    "holdout_percent": 5
  },
  "holdout": {
    "pct": 5,
    "treatment_count": 11310,
    "control_count": 595,
    "total_resolved": 11905
  },
  "quiet_hours": { "start_hour": 21, "end_hour": 8, "source": "org_default" },
  "frequency_caps": {
    "total_org_rules": 3,
    "applicable_rules": [
      { "channel": "sms", "scope": "channel", "window_seconds": 86400, "max_count": 3, "applies": true },
      { "channel": "*", "scope": "global", "window_seconds": 604800, "max_count": 7, "applies": true },
      { "channel": "email", "scope": "channel", "window_seconds": 86400, "max_count": 5, "applies": false }
    ]
  }
}
```

Read it as the answer to "why is this campaign throttled, delayed, or sending to fewer people than the audience size implies":

* **Quiet hours** resolve with precedence: a per-campaign override wins over your organization default, which wins over the platform default. `source` names the setting that is governing, so a surprising window traces straight back to where you change it.
* **Frequency caps** list every organization rule, but only rules whose `applies` flag is true are in force for this campaign's channel. The others are configured for your organization but do not bite on this send.
* **The hold-out** shows the control cohort carved out of the audience. This is also why `audience.deliverable` on the readiness check is smaller than the gross audience: held-out recipients are excluded from the send by design.
* **The experiment block** shows the committed variants, their traffic split, and the winner settings, so you can see whether a winner has been selected or an auto-promote rule is armed.

Every rule in this summary is a control you own: campaign and organization quiet hours, frequency-cap rules, hold-out percentages, and A/B settings are all configured in your workspace. The summary reports how they resolve for this one campaign.

## See also

* [Using Orby, the in-dashboard operator assistant](https://docs.orbit.devotel.io/guides/orby-in-dashboard.md) — the panel itself, and the proposal-and-approval gate on data-changing tools
* [Orby operator assistant concept](https://docs.orbit.devotel.io/concepts/orby-operator-assistant.md) — the tool registry and approval gate in detail
* [Orby API reference](https://docs.orbit.devotel.io/api-reference/orby.md) — the HTTP contract for turns, threads, and tool confirmations
* [Troubleshooting: Orby operator errors](https://docs.orbit.devotel.io/troubleshooting/orby-operator-errors.md) — session, authorization, and rate-limit errors and their fixes


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.