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

# Custom API Workflows

> Full reference for calling your API from an agent: variables, activation, credentials, and response mapping.

A Custom API Workflow is a saved HTTP request an agent runs at a defined point in the
conversation lifecycle. This page is the full reference. For where workflows fit alongside
knowledge bases and built-in tools, start with [Tools](/building-agents/tools).

<Note>
  This is your agent calling **your** API. To call **Vocily's** API from your own backend, see
  [API Reference](/developers/api-reference) instead.
</Note>

## The two phases

| Phase                        | Runs                                          | Trigger                                       | Typical use                                          |
| ---------------------------- | --------------------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
| **Before Call** (`pre_call`) | Automatically, before the conversation starts | None - runs on every call                     | Load customer details or prepare context             |
| **During Call** (`on_call`)  | Only when the agent decides to call it        | Referenced by name in your prompt (see below) | Look up an order, check eligibility, update a system |

A workflow's **name** is unique per agent, used as its identifier elsewhere (letters, digits, and
underscores; no dots).

<Note>
  **There is no after-call phase.** To send a transcript, analysis, or outcome to your system once
  the call is over, use **webhooks** (Agents → your agent → **Settings → Webhooks**) instead. A
  webhook is signed, retried on failure, and has a delivery log you can inspect - none of which a
  one-shot HTTP call at the end of a conversation can offer.
</Note>

## Activate an on-call workflow

Creating an on-call workflow does not make it callable by itself. The agent only sees it as a
tool it can invoke when the workflow's name appears in the prompt, greeting, or a system message,
written in angle brackets:

```text theme={"dark"}
When the caller asks about an order, look it up with <lookup_order>.
```

Referencing a name that doesn't exist yet, or that belongs to a Before Call workflow, is rejected
when you save the prompt - the error names the unknown reference so you can add the workflow
first or fix the typo.

<Warning>
  If you never write `<workflow_name>` anywhere in the prompt, the agent will never call an
  on-call workflow - silently. There's no error for this; it just never fires. If a workflow you
  built doesn't seem to run, check for its `<name>` in the prompt first.
</Warning>

Before Call workflows need no such reference - they run automatically on every call.

## Reference variables inside a workflow

Inside a workflow's own URL, headers, query parameters, or body, every variable reference needs
an explicit namespace prefix - there is no bare `{{name}}` shorthand here. This is different from
using a variable in the **prompt or greeting**, where a bare `{{name}}` is always your own custom
variable; see [Variables](/building-agents/variables) for that shorthand and the `<tool_name>`,
`||...||`, and `((...))` prompt syntax.

| Namespace                              | Example                        | Meaning                                                                                                                                                                  | Available in     |
| -------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- |
| `custom.*`                             | `{{custom.customer_id}}`       | An agent variable - one you defined in **Prompt Variables & Defaults**, or an ad hoc key                                                                                 | Both phases      |
| `pre.*`                                | `{{pre.lookup_customer.name}}` | A field an earlier **Before Call** workflow mapped from its response                                                                                                     | Both phases      |
| `agent.*`                              | `{{agent.agent_id}}`           | `agent.workspace_id`, `agent.agent_id`, `agent.execution_id`                                                                                                             | Before Call only |
| `call.*`                               | `{{call.from_number}}`         | `call.from_number`, `call.to_number`, `call.direction`, `call.call_sid`, `call.started_at`, `call.connected_at`, `call.ended_at`, `call.duration_seconds`, `call.status` | Before Call only |
| `api.*`                                | `{{api.lookup_order.status}}`  | A field an earlier **During Call** workflow mapped from its response, in the same call                                                                                   | During Call only |
| bare parameter name, or `parameters.*` | `{{order_id}}`                 | A value the agent fills in when it calls the workflow - see Dynamic fields below                                                                                         | During Call only |

`agent.*` and `call.*` are not available inside a During Call workflow - the agent already has
that context from the conversation itself. In the other direction, `api.*` and `parameters` don't
exist Before Call, because no conversation has started yet.

## Field value modes

Each header, query parameter, path parameter, or body field can use one of these modes:

| Mode           | What it does                                                                                                                                      | Available on     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| **Static**     | A literal value, sent as-is                                                                                                                       | All fields       |
| **Variable**   | A `{{namespace.key}}` reference, resolved right before the request is sent                                                                        | All fields       |
| **Dynamic**    | The agent decides the value while talking to the caller. The field becomes a parameter the agent fills in, described by the text you enter for it | During Call only |
| **Credential** | References a saved credential (see below) - the real value is resolved on Vocily's server and never appears in the workflow                       | Headers only     |

A field marked **Dynamic** is what makes an on-call workflow feel like a real tool call: the
agent extracts the value (an order number, a date, an email) from what the caller says, rather
than you supplying it.

### Required vs. optional fields

Every field is required by default (path parameters are always required). If a **required**
field's variable has no value when the workflow is about to run, the workflow does not send a
request at all - it fails immediately, naming the missing variable. If an **optional** field's
variable has no value, that one field is simply left out of the request; everything else is sent
normally.

## Authenticate with a credential

Use a credential instead of pasting a secret into a header, so the value is never stored on the
workflow and never shown again after you save it.

1. Go to **Settings → Credentials** (workspace scope) and add a credential: give it a name and
   the secret value (an API key or token).
2. In the workflow's **Headers**, add a row for the header your API expects (for example
   `X-Api-Key` or `Authorization`), set its mode to **Credential**, and select the credential.

The value is write-only: no page or response ever shows it again - including this workflow's own
editor, once saved. To rotate it, replace the value on the credential itself; every workflow
using it picks up the new value immediately, with nothing to update on the workflow. Deleting a
credential that's still selected in a workflow's header is blocked until you remove it there.

## Map a response for later use

A response mapping pulls one field out of an API's JSON response and gives it a name you can
reference elsewhere. Each mapping has a JSON path into the response (`$` for the whole body,
`$.customer.name` for a nested field, `$.items[0]` for an array element) and a target name.

The target must be written as `<namespace>.<this workflow's name>.<field>`, where the namespace
matches the workflow's own phase - `api.` for During Call, `pre.` for Before Call. For example, a
During Call workflow named `lookup_order` mapping `$.status` to `api.lookup_order.status` makes
that value available as:

* `{{api.lookup_order.status}}` inside another During Call workflow's fields, or
* `{{api.lookup_order.status}}` in the prompt - the same token either way. The whole response is
  `{{api.lookup_order}}`.

A Before Call workflow's mapped field reads the same, with its own namespace:
`{{pre.tool_name.field}}`. See [Variables](/building-agents/variables) for the complete
prompt-syntax list.

## Test a workflow

Use **Test API** in the workflow editor before enabling it. The test always completes and shows
you an outcome - it never shows a generic failure:

* If your API answers with an error status, the test shows that **real status code and body**,
  so you can see exactly what your API sent back.
* If the endpoint can't be reached at all (wrong host, timeout), the test shows a message
  explaining why, with no status code - nothing answered.

Supply values for any Dynamic fields and any Variable fields you want to try, so the test
reflects a real call as closely as possible.

## What happens when a workflow fails

Behavior differs by phase, and only one of them tells the caller anything:

| Phase           | On failure                                                                                                                                                                                                                 |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Before Call** | Skipped. The call starts anyway; any variables that workflow would have set stay empty. Write your prompt to handle a missing value gracefully.                                                                            |
| **During Call** | The agent is told the tool call failed and can respond to the caller in the moment - for example, offering to take a message instead. Give it explicit instructions for this in [Agent Core](/building-agents/agent-core). |

A Before Call failure is deliberately quiet - a workflow that can't be reached should never stop a
call from happening. That means a broken Before Call workflow looks like an agent that suddenly
doesn't know who it's talking to, rather than an error. If a prompt starts sounding generic, check
the workflow before you check the prompt.

## What's next

* Reference variables and the prompt-syntax shorthand in [Variables](/building-agents/variables).
* Give the agent instructions for using a workflow's result in [Agent Core](/building-agents/agent-core).
* Run a full pass in [Test](/test/overview) before enabling a workflow for real calls.
