Skip to main content
The {{variables}} of your agent have a default value you set in the Builder. On a call you can replace them with that call’s values: the customer’s name, their CRM contact ID, the branch they called. The agent hears them in its prompt, says them in its first message and passes them to its tools.

Where the values come from

When the same name has several values, this order wins: system variables (system__*, filled by Ryvo), then the call’s value, then the agent’s default. A variable with no value at all stays with its braces, so you can spot it in the transcript.

What they reach

  • The prompt, including every stage of a flow.
  • The first message and the voicemail message, which the agent says out loud.
  • The description of End call.
  • Tool parameters whose value comes from a dynamic variable. The name does not have to appear in the prompt: a tool can use tenant_slug even if the prompt never mentions it.
On calls you also get {{system__call_id}}: the call’s ID in Ryvo, the same one your webhooks receive, handy to log the call in your CRM from a tool.

Limits and how values are cleaned

  • Names: letters, digits and underscore, up to 64 characters, never starting with system__. In POST /v1/calls, keys with other names (for example deal-id) stay as opaque metadata: they travel in the conversation.started webhook but never reach the agent.
  • Up to 50 variables per call (more is a 400 invalid_body in the API), up to 2000 characters per value and 8 KB in total.
  • Numbers and booleans become text ("42", "true"). null keeps the default.
  • Control characters are removed, and {{ or }} inside a value become a single brace, so a value can never create a new variable.
These values go into the prompt as written. Treat them as data from your end customer: if a value comes from a public form, someone can try to give the agent instructions through it.

The call initiation webhook

For inbound phone calls. Before answering, Ryvo sends your server who is calling and uses the variables you return. Meanwhile, the caller hears the phone ringing.
1

Create an endpoint

In Settings › Webhooks (or from the Builder), create an endpoint with your server’s HTTPS URL. Its signing secret is the one that signs these requests too.
2

Turn it on in the agent

In the Builder, open Call settings › Call initiation webhook, turn on Ask my server when a call comes in and pick the endpoint.
3

Adjust the wait

Maximum wait time goes from 0.5 to 4 seconds (2 by default). Turn on Let it change the first message if your response may bring the agent’s first message.
4

Publish

Inbound calls use the published version.

The request

A POST with JSON, signed with X-Ryvo-Signature exactly like the events (see Verify signatures), plus X-Ryvo-Event: conversation.initiation and X-Ryvo-Event-Id. The endpoint receives it whatever events it is subscribed to.
caller_id and called_number keep the names ElevenLabs uses. There is no session ID yet; the stable key is call_sid, and the same call_sid can arrive more than once if Twilio retries.

The response

Answer with a 2xx and this JSON (the same shape ElevenLabs accepts):
  • dynamic_variables follows the limits above.
  • first_message is used only if Let it change the first message is on, the agent has no flow and it already speaks first. Up to 1000 characters, and it can use variables too.
  • Any other override (prompt, language, voice) is ignored.
  • A body over 8 KB, invalid JSON or a different type counts as a failure.

When it fails

If your server does not answer in time, answers something other than 2xx, or the response is invalid, the call is answered anyway with the default values. The result (ok, timeout, error or invalid, with the HTTP status and the latency, never the body) is stored with the call. You can turn the webhook off at any time from the same section.