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.
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.
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).
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.
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.
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, programmatic —
POST /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
| 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.