Skip to main content
Yappr supports two agent types:

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

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: 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 and DELETE /integrations/:id 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. Use this for audit trails, A/B comparison, and rollback.

Testing

Two test surfaces:
  • Hermetic, programmaticPOST /agents/:id/flow/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

type is immutable post-create.