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

# Testing Inbound Agents

> Test agents that receive calls. Cekura acts as the caller, dials your agent's configured number, and runs your evaluators end-to-end — no scripts required.

export const CopyPageButton = () => {
  if (typeof window !== 'undefined') {
    setTimeout(function () {
      if (document.getElementById('ck-tools')) return;
      var anchor = document.getElementById('content-area') || document.querySelector('.mdx-content');
      if (!anchor) return;
      if (!document.getElementById('ck-style')) {
        var s = document.createElement('style');
        s.id = 'ck-style';
        s.textContent = '#ck-tools{position:absolute;top:6px;right:0;z-index:100;font-family:inherit;}' + '.ck-row{display:inline-flex;align-items:stretch;border:1px solid rgba(0,0,0,0.15);border-radius:8px;overflow:hidden;background:#fff;}' + ':root.dark .ck-row{background:rgba(255,255,255,0.06);border-color:rgba(255,255,255,0.12);}' + '.ck-btn{padding:5px 12px;border:none;background:none;cursor:pointer;font-size:13px;font-weight:500;font-family:inherit;color:#374151;}' + ':root.dark .ck-btn{color:#d1d5db;}' + '.ck-btn:hover{background:rgba(0,0,0,0.04);}' + ':root.dark .ck-btn:hover{background:rgba(255,255,255,0.06);}' + '.ck-chevron{padding:5px 8px;border:none;background:none;cursor:pointer;font-size:14px;font-family:inherit;color:#374151;}' + ':root.dark .ck-chevron{color:#d1d5db;}' + '.ck-chevron:hover{background:rgba(0,0,0,0.04);}' + ':root.dark .ck-chevron:hover{background:rgba(255,255,255,0.06);}' + '.ck-divider{width:1px;background:rgba(0,0,0,0.12);flex-shrink:0;}' + ':root.dark .ck-divider{background:rgba(255,255,255,0.12);}' + '.ck-dd{position:absolute;top:calc(100% + 4px);right:0;min-width:180px;background:#fff;border:1px solid rgba(0,0,0,0.12);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.1);padding:4px;display:none;z-index:200;}' + ':root.dark .ck-dd{background:#1f2937;border-color:rgba(255,255,255,0.1);box-shadow:0 4px 16px rgba(0,0,0,0.35);}' + '.ck-item{display:block;width:100%;padding:7px 12px;border:none;background:none;border-radius:6px;cursor:pointer;font-size:13px;font-family:inherit;text-align:left;color:#374151;}' + ':root.dark .ck-item{color:#d1d5db;}' + '.ck-item:hover{background:rgba(0,0,0,0.05);}' + ':root.dark .ck-item:hover{background:rgba(255,255,255,0.07);}';
        document.head.appendChild(s);
      }
      var wrap = document.createElement('div');
      wrap.id = 'ck-tools';
      var row = document.createElement('div');
      row.className = 'ck-row';
      var mainBtn = document.createElement('button');
      mainBtn.className = 'ck-btn';
      mainBtn.textContent = 'Copy page';
      var divider = document.createElement('span');
      divider.className = 'ck-divider';
      var chevron = document.createElement('button');
      chevron.className = 'ck-chevron';
      chevron.textContent = '▾';
      var dd = document.createElement('div');
      dd.className = 'ck-dd';
      function closeDD() {
        dd.style.display = 'none';
      }
      function openDD() {
        dd.style.display = 'block';
      }
      chevron.onclick = function (e) {
        e.stopPropagation();
        if (dd.style.display === 'block') {
          closeDD();
        } else {
          openDD();
        }
      };
      document.addEventListener('click', function (e) {
        if (!e.target.closest('#ck-tools')) {
          closeDD();
        }
      });
      document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape') {
          closeDD();
        }
      });
      function makeItem(label, fn) {
        var b = document.createElement('button');
        b.className = 'ck-item';
        b.textContent = label;
        b.onclick = function () {
          fn();
          closeDD();
        };
        return b;
      }
      function getMarkdown() {
        var walk = function (node) {
          if (!node) return '';
          if (node.nodeType === 3) return node.textContent || '';
          if (node.nodeType !== 1) return '';
          var tag = node.tagName.toLowerCase();
          var skip = ['script', 'style', 'svg', 'noscript', 'button', 'iframe'];
          if (skip.indexOf(tag) !== -1) return '';
          if (node.id === 'ck-tools') return '';
          var ch = Array.from(node.childNodes).map(walk).join('');
          if (tag === 'h1') return '\n# ' + ch.trim() + '\n\n';
          if (tag === 'h2') return '\n## ' + ch.trim() + '\n\n';
          if (tag === 'h3') return '\n### ' + ch.trim() + '\n\n';
          if (tag === 'p') return '\n' + ch.trim() + '\n\n';
          if (tag === 'pre') return '\n```\n' + node.textContent.trim() + '\n```\n\n';
          if (tag === 'li') return '- ' + ch.trim() + '\n';
          if (tag === 'code') return '`' + ch.trim() + '`';
          return ch;
        };
        var content = document.querySelector('.mdx-content') || document.getElementById('content-area') || document.body;
        return walk(content).replace(/\n\n\n+/g, '\n\n').trim();
      }
      function copyMd() {
        var md = getMarkdown();
        navigator.clipboard.writeText(md).then(function () {
          mainBtn.textContent = 'Copied!';
          setTimeout(function () {
            mainBtn.textContent = 'Copy page';
          }, 2000);
        });
      }
      function viewMd() {
        var md = getMarkdown();
        var safe = md.split('&').join('&amp;').split('<').join('&lt;').split('>').join('&gt;');
        var html = '<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{font-family:monospace;max-width:860px;margin:40px auto;padding:0 24px;line-height:1.7;white-space:pre-wrap;word-wrap:break-word}</style></head><body>' + safe + '</body></html>';
        window.open(URL.createObjectURL(new Blob([html], {
          type: 'text/html'
        })), '_blank');
      }
      function openClaude() {
        var prompt = 'Can you read this Cekura docs page ' + window.location.href + ' so I can ask you questions?';
        window.open('https://claude.ai/new?q=' + encodeURIComponent(prompt), '_blank');
      }
      mainBtn.onclick = copyMd;
      dd.appendChild(makeItem('Copy page', copyMd));
      dd.appendChild(makeItem('View as Markdown', viewMd));
      dd.appendChild(makeItem('Open in Claude', openClaude));
      row.appendChild(mainBtn);
      row.appendChild(divider);
      row.appendChild(chevron);
      wrap.appendChild(row);
      wrap.appendChild(dd);
      anchor.style.position = 'relative';
      anchor.insertBefore(wrap, anchor.firstChild);
    }, 50);
  }
  return null;
};

<CopyPageButton />

## What is Inbound Testing?

If your agent is built to **receive** calls (a support line, a booking line, an IVR), Cekura tests it by placing the call itself. You select evaluators, hit run, and Cekura dials your agent's configured number as the simulated caller. Transcripts, metrics, and results land in your dashboard exactly the same way outbound runs do.

If instead your agent is built to **make** calls, see [Auto Outbound Calls](/documentation/guides/testing-agents/outbound-auto-call) — the direction of the call decides which guide applies, not the testing framework you use.

## How It Works

<Steps>
  <Step title="Set Inbound on the Agent">
    In agent settings, set the **Inbound** flag to **ON** (`inbound: true`).
  </Step>

  <Step title="Configure the Phone Number">
    Add the phone number Cekura should dial in Agent Settings. This is the number that reaches your agent. You can override it per run when needed.
  </Step>

  <Step title="Run Evaluators">
    Trigger scenarios from the UI, the API, or your CI pipeline. Cekura places the call to your agent's configured number and runs the scenario.
  </Step>

  <Step title="Review Results">
    Check transcripts, metric evaluations, and pass/fail status in your dashboard once the run completes.
  </Step>
</Steps>

## Prerequisites

* **Inbound mode enabled**: Agent's `inbound` must be set to `true`
* **Reachable phone number**: A number on your stack that routes to the agent under test (your provider's number, a Twilio BYO number, or a Cekura-issued number)
* **Evaluators ready**: Scenarios that define what the simulated caller should say and what the metrics should grade

<Note>
  Inbound testing does **not** require voice-provider API keys on Cekura's side — Cekura is the caller, not the agent. Your agent answers the call using its own stack as it would in production.
</Note>

## Triggering a Run

Once the agent is configured, any of the standard run-trigger surfaces will place a call:

* **Dashboard** — open the scenario(s) and click Run.
* **API** — call the standard scenario-run endpoint with the scenario IDs you want to execute.
* **CI/CD** — use the [GitHub Actions integration](/documentation/guides/github-actions-ci-cd) to run on push, pull request, or schedule. The action is direction-agnostic; the agent's `inbound` flag is what controls who places the call.

The trigger surface only decides **when** the run fires. The call direction is always determined by the agent's `inbound` flag.

## Overriding the Number Per Run

You can override the destination number on a per-scenario basis without changing the agent's default. This is useful when the same agent is deployed to multiple numbers (staging vs. production, region-specific lines).

1. Edit the scenario.
2. Open the **Configuration** section.
3. Set the phone number you want Cekura to dial for this scenario.

Bring-your-own-number setups are documented in [Twilio phone numbers](/documentation/key-concepts/phone-numbers/twilio) and [Plivo phone numbers](/documentation/key-concepts/phone-numbers/plivo).

## Inbound vs. Outbound

| Agent role                                        | Direction of test call           | Guide                                                                          |
| ------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------ |
| Receives calls (support, IVR, booking line)       | **Cekura → your agent**          | This page                                                                      |
| Makes calls (lead follow-up, reminders, outreach) | **Your agent → Cekura's number** | [Auto Outbound Calls](/documentation/guides/testing-agents/outbound-auto-call) |

The role Cekura plays in testing mirrors the role the caller plays in production: whoever picks up the phone is the agent.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Call Never Reaches the Agent">
    Verify the phone number on the agent (or scenario override) routes to your agent in production. Place a manual call to the same number — if it doesn't reach the agent, the issue is upstream of Cekura.
  </Accordion>

  <Accordion title="Cekura Says the Agent Didn't Answer">
    Check that the agent's transport (SIP trunk, Twilio number, provider webhook) is reachable from the public internet and is configured to answer the test number. Provider-side rate limits and number-blocking rules can silently drop test calls.
  </Accordion>

  <Accordion title="Run Triggers But Direction Looks Wrong">
    The most common cause is `inbound: false` on the agent. Confirm the flag in Agent Settings. The same agent cannot be tested in both directions in a single run — duplicate the agent if you need both flows.
  </Accordion>
</AccordionGroup>

## Next Steps

* Set up [GitHub Actions CI/CD](/documentation/guides/github-actions-ci-cd) to run inbound scenarios on every push
* Run the [Infrastructure Suite](/documentation/guides/testing-agents/infrastructure-suite) against your inbound number to validate latency and stability
* Add [custom metrics](/documentation/key-concepts/metrics/custom-metrics) tailored to your agent's job
