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

> ## Agent Instructions
> Use the public API base URL: https://api.teamfollowup.ai/api.
> Authenticate public API requests with Authorization: Bearer YOUR_API_KEY.
> Use product-owned terms: agents, campaigns, projects (GoHighLevel sub-accounts), contacts, calls, outcomes, skills, cadences, phone numbers.
> Scope requests by locationId rather than projectName.
> Read the guide linked from each API reference group before recommending an endpoint.

# Campaign workflows

> After every call, the outcome picks a branch and the workflow does the CRM work: tag, move stage, note, text, book. One graph per campaign, one branch per outcome.

The call ends. Now what? The lead booked, or asked for a callback, or said
never again. Each of those should do something different in the CRM. A
**campaign workflow** is that mapping: for each outcome, a list of actions the
platform runs the moment the call is over.

You do not have to build one. A campaign works without a workflow and still
applies the [automatic tags](/campaigns/after-the-call). Build one when "tag
it" is not enough.

## Outcomes are the entry points

The workflow is a graph with one root per outcome. The keys under
`dispositionEntries` are the outcome constants:

| Key                                      | The call ended with                          |
| ---------------------------------------- | -------------------------------------------- |
| `SUCCESS` (alias `BOOKED`)               | An appointment booked.                       |
| `CONFIRMED`                              | An appointment confirmed.                    |
| `RESCHEDULE`                             | An appointment moved.                        |
| `TRANSFER`                               | A live transfer that connected.              |
| `FAILED_TRANSFER`                        | A live transfer that did not connect.        |
| `TAG_APPLIED`                            | The agent applying a tag as the main result. |
| `CALLBACK`                               | A callback request.                          |
| `INFO_ONLY` (alias `FOLLOWUP_REQUESTED`) | A lead who wanted information.               |
| `HUMAN_NEEDED`                           | Something the agent could not handle.        |
| `KILL_SWITCH`                            | An opt-out.                                  |
| `VOICEMAIL` (alias `NO_ACTION`)          | No conversation.                             |

An outcome with no entry does nothing beyond the automatic tag. The outcomes a
campaign can actually produce depend on its capabilities. See
[What your agent records](/agents/outcomes).

## Nodes and edges

`nodes` is an object keyed by node id. Each node has a `type` and its own
settings. `edges[]` connect them with `source`, `target` and, on branching
nodes, a `sourceHandle` naming which exit the edge leaves from.

| Node `type`              | Does                                                             |
| ------------------------ | ---------------------------------------------------------------- |
| `add-tag`, `remove-tag`  | Change tags on the contact.                                      |
| `set-field`              | Write a custom field, for example the budget the agent captured. |
| `move-stage`             | Move the contact to a pipeline stage.                            |
| `add-note`               | Write a note on the contact.                                     |
| `send-sms`, `send-email` | Message the lead.                                                |
| `book-appointment`       | Create the appointment in a calendar.                            |
| `trigger`                | Fire a GoHighLevel workflow.                                     |
| `if`                     | Branch on one condition. Exits are `then` and `else`.            |
| `switch`                 | Branch on several cases. Exits are the case ids and `default`.   |

Conditions on `if` and `switch` compare an [AI-generated field](/agents/outcomes)
or a contact field with an operator: `is_true`, `is_false`, `is_set`,
`is_empty`, `equals`, `not_equals`, `contains`, `starts_with`, `in`, `gt`,
`gte`, `lt`, `lte`.

## Campaign-wide settings

`campaignConfig` on the same document holds settings that shape every branch:

* `callbackMode`: `ai` lets the agent place callbacks, `human` routes them to
  your team, with `humanCallbackCalendarId` naming where to book them.
* `aiNotes` and `noteLanguage`: whether the agent writes a call note and in
  which language.
* `convertedTag`: the tag that marks a lead as converted.

## Saving without breaking a live campaign

The workflow runs on real calls while you edit it, so the write endpoints are
built to fail loudly rather than lose a branch.

* Every read returns `version`. Send it back as `expectedVersion` on a write.
  If someone saved in between, you get `409` and reload.
* The **replace** endpoint swaps the whole graph. If the new graph drops nodes,
  you must send `allowRemovals: true`, and a `400` lists what would go.
* The **update** endpoint merges. It changes settings and the contents of
  nodes that already exist. It never creates a node.
* The **add actions** endpoint appends nodes to one outcome's branch in a
  single step, so a partially applied chain cannot exist.
* The **remove node** endpoint deletes one node and its edges.

## Advisories

Reads return `advisories[]`, checks that do not block saving but tell you
where the graph is weak:

| Advisory          | Means                                                                                     |
| ----------------- | ----------------------------------------------------------------------------------------- |
| `node_incomplete` | A node is missing a required setting, such as a tag name.                                 |
| `unreachable`     | No edge leads to this node.                                                               |
| `unsafe_context`  | An action that assumes data the outcome does not carry, such as booking on a `VOICEMAIL`. |
| `unknown_outcome` | An entry keyed by an outcome this campaign cannot produce.                                |

The [digest](/api-reference/campaign-workflows/get-a-per-outcome-workflow-digest)
endpoint gives the same graph as one line per outcome, which is the easiest
way to review what a campaign will do.

## Boundaries

* One workflow per campaign. Campaigns on the same agent share the agent but
  not the graph.
* Branches run after the call. They cannot change what the agent says.
* Automatic tags are applied whether or not a workflow exists.
* A `409` means reload, do not retry blindly.

## In the API

* [Get the campaign workflow](/api-reference/campaign-workflows/get-the-campaign-workflow)
* [Replace the entire workflow](/api-reference/campaign-workflows/replace-the-entire-workflow) and
  [Update settings or node contents](/api-reference/campaign-workflows/update-settings-or-node-contents)
* [Add actions to an outcome](/api-reference/campaign-workflows/add-actions-to-an-outcome) and
  [Remove a workflow node](/api-reference/campaign-workflows/remove-a-workflow-node)
* [Get a per-outcome workflow digest](/api-reference/campaign-workflows/get-a-per-outcome-workflow-digest)
* Every field above is defined in the [Glossary](/glossary#campaign-workflows)

## Related

* [What your agent records](/agents/outcomes) defines the outcomes and fields
  the conditions read.
* [GoHighLevel resources](/ghl/overview) is where you look up the tag,
  calendar, field and stage ids these nodes need.
