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

# Flow Agents

> When to use flow agents instead of prompt agents — node catalog, decision tree, common patterns.

Yappr supports two agent types:

| Type                       | Drives the call                                                                                                                                 | Best for                                                                                                                                             |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prompt` (default, legacy) | A single `system_prompt` string. The LLM decides what to say and when to call attached tools.                                                   | Open-ended, consultative use cases — sales discovery, support triage, advisory conversations.                                                        |
| `flow`                     | A graph of nodes (`flow_config`). The flow runtime guarantees step order, enforces slot collection, and routes deterministically through tools. | Procedural use cases where steps must run in order and you want measurable funnel drop-off — booking, intake, RSVP, qualification, multi-step forms. |

## When to pick `flow`

Pick `flow` when **any** of these is true:

* The conversation has **required steps** that cannot be skipped (e.g. collect name → collect date → check availability → confirm → book).
* The conversation has **branching logic** that depends on a tool's result (e.g. "if `check_availability` returns `no_availability`, offer alternative slots").
* You need to **measure funnel drop-off** by step (where do callers hang up? at "asking for date"? at "confirming"?).
* A single prompt has been getting unreliable — the model "forgets" to ask a required question, or short-circuits to the booking tool too early.

## When to pick `prompt`

Pick `prompt` when:

* The conversation is open-ended and the LLM should improvise.
* You're not measuring per-step funnel — the call is one outcome (booked / not booked / no answer).
* The agent's tools are best chosen by the LLM mid-conversation, not gated to specific points.

## Node catalog

| Node           | Speaks?                                              | Action                                                               | Transitions                                                                    |
| -------------- | ---------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `start`        | conditional (greeting if `agent_speaks_first: true`) | entry; sets the "who speaks first" decision for the call             | single auto-advance                                                            |
| `conversation` | yes (Gemini Live)                                    | talks to the user using global `system_prompt` + node `instructions` | N user-defined transitions; eval LLM picks one or "stay" each turn             |
| `tool_call`    | optional pre-announcement                            | deterministically run a tool, inject result as a system message      | fixed `success` / `error`, optional custom branches keyed by JSONPath equality |
| `transfer`     | yes (transfer message)                               | SIP transfer to another phone                                        | terminal                                                                       |
| `end`          | yes (farewell)                                       | hang up                                                              | terminal                                                                       |

For per-call extraction or webhook delivery, use the agent-level `extraction_parameters` and `webhook_url` / `webhook_events` fields. They apply uniformly to both prompt and flow agents — the flow does not have a separate post-end pipeline.

## Transfer / end — node vs system tool

Both flow agents and prompt agents can transfer or end calls. The runtime mechanism is shared (same SIP transfer handler, same `EndTaskFrame` push). The configuration entry differs because the trigger model differs:

|               | Prompt agent                                                                | Flow agent                     |
| ------------- | --------------------------------------------------------------------------- | ------------------------------ |
| Trigger       | LLM **decides** to call the system tool                                     | Flow **routes** to the node    |
| Configure via | `tools` table (system tool with `handler: "transfer_call"` or `"end_call"`) | The Transfer / End node itself |
| Same runtime? | Yes — both call into `SYSTEM_TOOL_HANDLERS` in the bot                      | Yes                            |

The flow node and the system tool are not interchangeable. Prompt agents cannot reach an End node (no flow); flow agents cannot have the LLM call a system tool mid-conversation (conversation nodes have no LLM-callable tool surface — the eval LLM picks only from declared transitions).

## Who speaks first

Configured on the **Start node** for flow agents (overrides agent-level `agent.agent_speaks_first` and `agent.greeting_message`):

* `agent_speaks_first: true` (default) — bot speaks the `greeting` on connect, then auto-advances to the next conversation node.
* `agent_speaks_first: false` — bot waits silently for the user. The flow auto-advances silently to the next conversation node so the bot is "in" the right step when the user does speak (`agent.silence_timeout_secs` still applies — the call hangs up if dead air persists).

## Deciding between a transition and a tool-call node

If the bot needs to do anything **deterministic** (call an API, look up a calendar slot, transfer to another number), put it in a `tool_call` node — never let the conversation node's LLM decide. A `tool_call` node has predictable cost, predictable latency, and a measurable success/error split.

Conversation nodes only **talk**. The eval LLM chooses among the human-defined transitions baked into the node — it never invents new branches.

## Tools and `config_override`

A flow tool-call node references an existing row in the `tools` table (company-scoped) by `tool_id`. The same tool can be reused across many flows and across both prompt-mode and flow-mode agents — editing the tool's config propagates everywhere.

When you need per-flow customization (different webhook URL, different payload field, etc.), use `config_override`. It shallow-merges over the source tool's `config`, with array fields replaced (not concatenated). Keep overrides small — drift between the source tool and an override is the most common cause of subtle flow bugs.

In the dashboard, select a tool-call node to inspect its **Base tool configuration**, **Node overrides**, and **Effective configuration** together in the node editor. Enable only the fields that should differ for that node. The payload configuration is one top-level field, so overriding it replaces the complete payload section, including standard metadata, static parameters, and extracted parameters. Clearing the node overrides restores inheritance from the shared tool. Switching the linked tool requires confirmation and clears the old tool's overrides so an incompatible payload cannot carry over silently.

## Integrations as tools

OAuth-backed third-party integrations (v1: Google Calendar, Gmail) are surfaced as `integration_call` nodes. Once the credential is connected from the dashboard's Integrations page, the dashboard exposes the integration's typed actions (`create_event`, `list_events`, `check_availability`, `cancel_event` for Calendar; `send_email` for Gmail) as the `action` enum on an `integration_call` node. The public API exposes [`GET /integrations`](/api-reference/integrations/list) and [`DELETE /integrations/:id`](/api-reference/integrations/disconnect) for listing and revoking; the OAuth handshake itself is dashboard-only.

The bot resolves the encrypted access token at call-time via a SECURITY DEFINER RPC; tokens are never exposed to the API or to the bot process directly.

## Versioning

Every save writes a row to `flow_versions`, deduped by content hash. Browse history via [`GET /agents/:id/flow/versions`](/api-reference/flows/list-versions). Use this for audit trails, A/B comparison, and rollback.

## Testing

Two test surfaces:

* **Hermetic, programmatic** — [`POST /agents/:id/flow/test`](/api-reference/flows/test). Walks the graph against a synthetic transcript with mocked tool results. No real call placed, no `call_logs` row written. Use in CI.
* **Live WebRTC** — the in-app **Test** tab on the agent editor. Opens a real bot call against the saved (or unsaved) flow. Use for prompt-quality and eval-LLM behavior validation.

## API surface

| Method & path                                        | Scope           | Purpose                                                |
| ---------------------------------------------------- | --------------- | ------------------------------------------------------ |
| `POST /agents` (with `type: "flow"` + `flow_config`) | `agents:create` | Create a flow agent                                    |
| `PATCH /agents/:id` (with `flow_config`)             | `agents:update` | Update the graph; auto-snapshots a `flow_versions` row |
| `GET /agents/:id/flow/versions`                      | `flows:read`    | List version history                                   |
| `POST /agents/:id/flow/test`                         | `flows:test`    | Hermetic simulator                                     |

`type` is **immutable** post-create.
