# SDK usage examples

Runnable-style snippets for `@voctiv/agent-sdk`. Copy into your script project or use as reference.

Each file exports one `defineScript` handler. The host **always** invokes that single export — unlike logic-executor Python, it does **not** call separate functions by `entry_point` name.

| File | Topic |
|------|--------|
| [outbound-on-answer.ts](./outbound-on-answer.ts) | Campaign outbound on `200 OK` (`outboundCallMode: 'on_answer'`, the default) |
| [outbound-from-invite.ts](./outbound-from-invite.ts) | Campaign outbound from INVITE (`outboundCallMode: 'from_invite'`) |
| [outbound-script-dial.ts](./outbound-script-dial.ts) | Script dials the campaign leg (`outboundCallMode: 'script_dial'`) |
| [outbound-with-recall.ts](./outbound-with-recall.ts) | Outbound with `recallCount` / `recallDelay` |
| [recall-routing-by-attempt.ts](./recall-routing-by-attempt.ts) | Branch on `context.attempt` during online recall legs |
| [schedule-call-with-defaults.ts](./schedule-call-with-defaults.ts) | `platform.call()` using CMS defaults from `context` |
| [after-call-continuation.ts](./after-call-continuation.ts) | `onSuccessCall` / `onFailedCall` + `getScriptPhase()` |
| [read-recall-from-params.ts](./read-recall-from-params.ts) | `parseRecallDelaySeconds()` / `parseRecallCount()` |
| [custom-media-providers.ts](./custom-media-providers.ts) | Host-only `mediaProviders` (`implements ScriptAsrConnector` / `ScriptTtsConnector`) |
| [custom-media-providers-script.ts](./custom-media-providers-script.ts) | Sandboxed `defineScript` using custom vendors (no `ws` / no `process.env`) |

## Recall flow

1. Script calls `platform.call(msisdn, { recallCount, recallDelay })`.
2. Host stores params on the `call` row.
3. On failed outbound, host schedules a new `call` with `date_added = now + recallDelay`.
4. Dialer runs the **same script** again; `context.attempt` is incremented.
5. Branch inside `defineScript` with `context.attempt`, not with a separate entry function.

Do **not** combine step 1 with `onFailedCall` on the same `platform.call()` — use one strategy per
scheduled outbound leg. See [after-call-continuation.ts](./after-call-continuation.ts) for the
script-driven failure path (`after_call_failed`).

## Failed outbound: pick one strategy

| Need | Use | Avoid on the same `platform.call()` |
|------|-----|--------------------------------------|
| CMS-style automatic redials | `recallCount` + `recallDelay` (or omit both and let host default from `context` when no `onFailedCall`) | `onFailedCall` |
| Diagram / custom logic after failure | `onFailedCall` (+ branch on `getScriptPhase` → `after_call_failed`) | `recallCount` + `recallDelay` |

When `onFailedCall` is passed **explicitly** in `platform.call()` options, the host does
**not** auto-apply CMS `context.recallCount` / `context.recallDelay` to the new `call` row.
`on_failed_call` in dialog/Omni defaults is ignored for scheduling. If the script passes both
strategies in options, the host **drops recall** and keeps `onFailedCall`.

## `entryPoint` vs logic-executor

In LE Python, `entry_point='main'` selects which script function runs.

In this host, `platform.call({ entryPoint })` only writes `entry_point` to DB params and sets `context.entryPoint` so **your** `defineScript` can branch (e.g. `getScriptPhase(context)` for headless after-call). Omit it when recall/online logic uses `context.attempt` only.
