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

# Variables por llamada y webhook de inicio de llamada

> Dale a cada llamada sus propios valores: desde la API, desde Node, desde el probador o desde tu servidor cuando entra una llamada.

Las `{{variables}}` de tu agente tienen un **valor por omisión** que defines en el Constructor. En una llamada puedes reemplazarlas con los valores de esa llamada: el nombre del cliente, su ID de contacto en el CRM, la sucursal a la que llamó. El agente los ve en su prompt, los dice en su saludo y se los pasa a sus tools.

## De dónde salen los valores

| Llamada | Cómo mandas los valores |
| - | - |
| Saliente, por la API | El objeto `metadata` de [`POST /v1/calls`](https://docs.ryvo.so/es/api-reference/calls/trigger-an-outbound-call). La CLI lo manda con `--var nombre=valor` y el servidor MCP con `create_call`. |
| Saliente, desde Node | Pídele a Node que haga la llamada con los valores; viajan igual. |
| Pruebas en el Constructor | El botón `{}` del probador. Sus valores aplican a **Probar LLM**, **Probar audio** e **Iniciar llamada** (en Canales). Nunca se guardan en el agente. |
| Entrantes por teléfono | El **webhook de inicio de llamada**: antes de contestar, Ryvo le pregunta a tu servidor quién llama (ver abajo). |

Cuando un mismo nombre tiene varios valores, gana este orden: las variables de sistema (`system__*`, las llena Ryvo), luego el valor de la llamada, luego el valor por omisión del agente. Una variable sin ningún valor se queda con sus llaves, para que la notes en la transcripción.

## A dónde llegan

* El prompt, incluida cada etapa de un flujo.
* El saludo y el recado del buzón, que el agente dice en voz alta.
* La descripción de **Colgar la llamada**.
* Los parámetros de tools cuyo valor sale de una **variable dinámica**. El nombre no tiene que aparecer en el prompt: una tool puede usar `tenant_slug` aunque el prompt nunca lo mencione.

En llamadas tienes además `{{system__call_id}}`: el ID de la llamada en Ryvo, el mismo que llega en tus webhooks, útil para registrar la llamada en tu CRM desde una tool.

## Límites y cómo se limpian los valores

* Nombres: letras, dígitos y guion bajo, hasta 64 caracteres, nunca empezando por `system__`. En `POST /v1/calls`, las llaves con otro nombre (por ejemplo `deal-id`) se quedan como metadata opaca: viajan en el webhook `conversation.started` pero nunca llegan al agente.
* Hasta **50 variables** por llamada (más es un `400 invalid_body` en la API), hasta 2000 caracteres por valor y 8 KB en total.
* Números y booleanos se vuelven texto (`"42"`, `"true"`). `null` conserva el valor por omisión.
* Se quitan los caracteres de control, y `{{` o `}}` dentro de un valor se reducen a una sola llave, así que un valor nunca puede crear una variable nueva.

> [!WARNING]
>
> Estos valores entran al prompt tal cual. Trátalos como datos de tu cliente final: si un valor viene de un formulario público, alguien puede intentar darle instrucciones al agente a través de él.

## El webhook de inicio de llamada

Para **llamadas entrantes por teléfono**. Antes de contestar, Ryvo le manda a tu servidor quién llama y usa las variables que devuelvas. Mientras tanto, quien llama escucha el timbre.

**1. Crea un endpoint**

En **Configuración › Webhooks** (o desde el Constructor), crea un endpoint con la URL HTTPS de tu servidor. Su secreto de firma es el que firma también estas peticiones.

**2. Enciéndelo en el agente**

En el Constructor, abre **Ajustes de llamada › Webhook de inicio de llamada**, enciende **Consultar mi servidor al recibir una llamada** y elige el endpoint.

**3. Ajusta la espera**

**Tiempo máximo de espera** va de 0.5 a 4 segundos (2 por omisión). Enciende **Permitir que cambie el saludo** si tu respuesta puede traer el primer mensaje del agente.

**4. Publica**

Las entrantes usan la versión publicada.

## La petición

Un `POST` con JSON, firmado con `X-Ryvo-Signature` igual que los eventos (ver [Verificar firmas](https://docs.ryvo.so/es/webhooks/signature-verification.md)), más `X-Ryvo-Event: conversation.initiation` y `X-Ryvo-Event-Id`. El endpoint la recibe sin importar a qué eventos esté suscrito.

```json theme={null}
{
  "type": "conversation_initiation",
  "agent_id": "3c1f2a4e-5b6d-4c7e-8f90-a1b2c3d4e5f6",
  "agent_version": 7,
  "call_sid": "CA0123456789abcdef0123456789abcdef",
  "caller_id": "+525512345678",
  "called_number": "+528121885950",
  "phone_number_id": "9d2e4f60-1a3b-4c5d-8e7f-0a1b2c3d4e5f",
  "channel": "phone",
  "direction": "inbound",
  "timestamp": "2026-10-26T18:00:00Z"
}
```

`caller_id` y `called_number` conservan los nombres que usa ElevenLabs. Todavía no hay ID de sesión; la llave estable es `call_sid`, y el mismo `call_sid` puede llegar más de una vez si Twilio reintenta.

## La respuesta

Contesta con un `2xx` y este JSON (la misma forma que acepta ElevenLabs):

```json theme={null}
{
  "type": "conversation_initiation_client_data",
  "dynamic_variables": { "lead_name": "Ana", "is_inbound": "true" },
  "conversation_config_override": {
    "agent": { "first_message": "Hola Ana, soy Karen de Kolonus." }
  }
}
```

* `dynamic_variables` sigue los límites de arriba.
* `first_message` sólo se usa si **Permitir que cambie el saludo** está encendido, el agente no tiene flujo y ya habla primero. Hasta 1000 caracteres, y también puede usar variables.
* Cualquier otro override (prompt, idioma, voz) se ignora.
* Un cuerpo de más de 8 KB, un JSON inválido o un `type` distinto cuentan como fallo.

## Cuando falla

Si tu servidor no contesta a tiempo, contesta algo distinto de `2xx` o la respuesta no es válida, **la llamada se contesta igual** con los valores por omisión. El resultado (ok, tiempo agotado, error o inválido, con el estado HTTP y la latencia, nunca el cuerpo) queda guardado con la llamada. Puedes apagar el webhook cuando quieras desde la misma sección.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.