> ## 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.

# Tools: conecta tu agente a tus sistemas

> Cómo dar de alta una tool (función personalizada) en el Constructor, qué petición HTTP recibe tu servidor y qué debe responder.

Una **tool** es una función que tu agente puede llamar en medio de la conversación para consultar o escribir en tus sistemas: buscar un pedido, cotizar, registrar un lead, confirmar disponibilidad. Tú expones un endpoint HTTPS; Ryvo lo llama con los datos que el modelo extrajo de la conversación y le devuelve la respuesta al agente para que la use en su siguiente frase.

Funciona igual en el probador de chat y en las llamadas de voz.

## Dar de alta una tool

En el Constructor, riel izquierdo, entra a **Tools** y haz clic en **+** (Nueva herramienta). El único tipo disponible hoy es **Solicitud API**.

<Frame caption="(1) Tools en el riel. (2) Nueva herramienta. A la derecha, el detalle de una tool: endpoint, autenticación, parámetros y tiempo límite.">
  <img src="https://mintcdn.com/ryvo-3dab4d1a/9EEXAZ5i3XN2oDZq/images/portal/tools-panel.png?fit=max&auto=format&n=9EEXAZ5i3XN2oDZq&q=85&s=2b4e1b8d3cc662298f0a90745489325a" alt="Panel de Tools del Constructor" width="1600" height="1000" data-path="images/portal/tools-panel.png" />
</Frame>

| Campo             | Qué poner                                               | Reglas                                                                                                                                                                                                              |
| ----------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Nombre**        | Un verbo claro: `buscar_pedido`, `agendar_visita`       | 1 a 60 caracteres. El modelo ve el nombre saneado: sin acentos y con `_` en lugar de espacios o símbolos. Si dos tools sanean igual, la segunda se vuelve `nombre_2`.                                               |
| **Método**        | `GET`, `POST`, `PUT`, `PATCH` o `DELETE`                |                                                                                                                                                                                                                     |
| **URL**           | El endpoint de tu servidor                              | HTTPS obligatorio, dominio público. Se rechazan IPs privadas, `localhost`, direcciones de metadata y credenciales dentro de la URL (`usuario:clave@`). Al guardar se resuelve el DNS: si no resuelve, no se guarda. |
| **Autenticación** | `Ninguna`, `Bearer` o `Cabecera`                        | Con Bearer mandamos `Authorization: Bearer <secreto>`. Con Cabecera eliges el nombre (por ejemplo `X-API-Key`) y un prefijo opcional.                                                                               |
| **Parámetros**    | Los datos que el modelo debe extraer de la conversación | Hasta 20. Nombre `[A-Za-z_][A-Za-z0-9_]*` (máx. 40), tipo `string`, `number`, `integer`, `boolean`, `array` u `object`, descripción de hasta 200 caracteres y si es obligatorio.                                    |

<Warning>
  El secreto de autenticación se cifra al guardar y **no se vuelve a mostrar**. Si lo pierdes, borra la tool y créala de nuevo. Las cabeceras `Content-Type`, `Content-Length` y `Host` no se pueden usar como cabecera de autenticación.
</Warning>

<Frame caption="El modal de alta: tipo, nombre, autenticación, endpoint y parámetros.">
  <img src="https://mintcdn.com/ryvo-3dab4d1a/9EEXAZ5i3XN2oDZq/images/portal/nueva-tool.png?fit=max&auto=format&n=9EEXAZ5i3XN2oDZq&q=85&s=76e5d67a07a6e9633f74f1c38678d540" alt="Modal Nueva tool" width="720" height="620" data-path="images/portal/nueva-tool.png" />
</Frame>

### La descripción de cada parámetro sí importa

El modelo recibe el nombre y la descripción de cada parámetro como parte del esquema de la función. Una descripción como «Número de pedido de 8 dígitos que el cliente dicta» produce mejores extracciones que dejarla vacía.

<Note>
  El campo «Cuándo debe usarla el agente» todavía **no se guarda**: el modelo decide cuándo llamar la tool conociendo únicamente su nombre y sus parámetros. Mientras tanto, explica en el **prompt del agente** cuándo y para qué usar cada tool, por su nombre exacto. Ejemplo: «Cuando el cliente pregunte por el estado de un pedido, pide el número y llama a `buscar_pedido`».
</Note>

## Publica para que el agente la vea

Crear la tool no la activa. Las tools se asignan a una **versión** del agente, así que tienes que **Publicar** después de crearla. El panel de Tools te enseña el estado de cada una:

| Estado              | Significado                                                      |
| ------------------- | ---------------------------------------------------------------- |
| **Activa**          | Está en la versión publicada y habilitada.                       |
| **Sin asignar**     | Existe, pero la versión publicada no la incluye. Publica.        |
| **Pausada**         | La deshabilitaste; el modelo no la ve.                           |
| **Mal configurada** | Falta la URL, el método o el secreto. Bórrala y créala de nuevo. |

Puedes probarla sin publicar: el probador de chat y la prueba de voz del Constructor usan el **borrador** (la versión que estás editando), no la publicada.

## La petición que recibe tu servidor

Cuando el modelo decide llamar la tool, Ryvo resuelve los parámetros y hace **una** petición a tu URL.

**`GET` y `DELETE`**: los parámetros viajan como query string, sin cuerpo.

```http theme={null}
GET /pedidos?numero=48213&telefono=%2B5218112345678 HTTP/1.1
Host: api.tunegocio.com
Authorization: Bearer ****
```

**`POST`, `PUT` y `PATCH`**: los parámetros viajan como JSON en el cuerpo.

```http theme={null}
POST /citas HTTP/1.1
Host: api.tunegocio.com
Content-Type: application/json
Authorization: Bearer ****

{ "nombre": "Mariana López", "fecha": "2026-10-02", "hora": "11:00" }
```

Lo que **sí** llega: los parámetros que declaraste, con los valores que el modelo extrajo (o el cuerpo tal cual lo armó el modelo si la tool no tiene parámetros). Lo que **no** llega hoy: identificador de la llamada, del agente ni teléfono del llamante, ni firma HMAC. Si necesitas correlacionar con la conversación, pide al modelo que capture ese dato como parámetro.

### Lo que Ryvo hace por su cuenta

* **Timeout de 8 segundos** y **un reintento** (500 ms después) sólo si tu servidor respondió `5xx`, hubo error de red o venció el timeout. Un `4xx` no se reintenta.
* **Idempotencia**: cada llamada del modelo lleva un identificador único. Si el mismo turno se repite (por ejemplo, tras un corte del audio), tu endpoint **no** se vuelve a ejecutar; el agente recibe el resultado registrado la primera vez.
* **Redirecciones**: máximo 3, sólo al mismo origen y siempre HTTPS. Una redirección a otro dominio se corta para no llevarse tu secreto.
* **Tope de llamadas por turno** según tu plan (4 en Pago por uso, 6 en Starter, 10 en Pro, 12 en Scale). Si el modelo intenta más, recibe `tool_call_budget_exhausted`.

## Lo que debe responder tu servidor

Cualquier código **2xx**. El cuerpo se entrega al modelo:

* Si es JSON válido, como JSON.
* Si no, como texto.

Responde **corto y estructurado**: el agente tiene que leerlo en voz alta o convertirlo en una frase. `{"estado":"en camino","entrega":"jueves 2 de octubre"}` funciona mejor que una página de datos.

Hay un tope de bytes por respuesta según tu plan: **16 KB** en Pago por uso, **32 KB** en Starter, **64 KB** en Pro y **128 KB** en Scale y Enterprise. Si tu respuesta lo excede, el agente recibe el fragmento leído marcado como truncado:

```json theme={null}
{ "truncated": true, "max_bytes": 16384, "bytes_read": 16384, "content": "..." }
```

Un `4xx` o `5xx` llega al modelo como error con el código HTTP y el cuerpo que enviaste. Si mandas un mensaje legible en el cuerpo (`{"error":"No encontramos ese pedido"}`), el agente puede decírselo al cliente.

## Errores que puede ver el agente

| Código                               | Causa                                                                         | Qué hacer                                        |
| ------------------------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------ |
| `upstream_error`                     | Tu servidor respondió `4xx` o `5xx`. Va acompañado del `status` y del cuerpo. | Revisa el log de tu endpoint.                    |
| `timeout`                            | No respondió en 8 s (tras el reintento).                                      | Responde rápido; encola el trabajo pesado.       |
| `network_error`                      | DNS, TLS o conexión rechazada.                                                | Verifica certificado y disponibilidad pública.   |
| `missing_required_param:<nombre>`    | El modelo no extrajo un parámetro obligatorio.                                | Mejora la descripción del parámetro o el prompt. |
| `credentials_unavailable`            | No se pudo descifrar el secreto.                                              | Borra y vuelve a crear la tool.                  |
| `tool_disabled` / `tool_not_allowed` | La tool está pausada o no está en la versión que atiende.                     | Actívala y publica.                              |
| `tool_call_budget_exhausted`         | Se alcanzó el tope de llamadas del turno.                                     | Consolida tools o sube de plan.                  |

## Diferencias entre chat y voz

* En voz, la ejecución corre en un hilo aparte para no trabar el audio, pero el agente no tiene nada que decir hasta que llega tu respuesta. Mantén tus tools por debajo de 2 o 3 segundos; el silencio se nota.
* Los valores de **variables dinámicas** (por ejemplo, el teléfono del llamante) no se inyectan en tools durante llamadas de voz por ahora.

## Tools nativas

Además de las tuyas, el agente puede traer una tool que Ryvo opera:

* **`search_kb`**: busca en tu base de conocimiento. Aparece sola cuando el agente tiene documentos en modo «Cuando haga falta». [Más en Base de conocimiento](/guias/agentes/base-de-conocimiento).

Para agendar citas usa una integración de calendario (Google Calendar, Calendly u Outlook) y dale al agente la acción de crear el evento; ver la sección siguiente.

## Integraciones

Desde el plan **Pro**, el agente puede usar acciones de apps que ya usas (Google Calendar, Gmail, Outlook, Google Sheets, HubSpot, Salesforce, Pipedrive, Notion, Airtable, Slack y Calendly) sin que tengas que escribir un webhook. Ryvo las conecta por Composio, que guarda y renueva el acceso por ti.

1. En **Configuración → Integraciones** pulsa **Conectar** en la app. Se abre la pantalla de autorización de esa app; al terminar vuelves a Ryvo con la tarjeta en **Conectada**.
2. En el constructor, **Nueva tool → Integración**: elige la app conectada y marca las acciones que quieres darle al agente (las recomendadas van primero y hay buscador). Cada acción se crea como una tool con sus parámetros ya definidos por la app; no se editan, sólo se borran.
3. **Publica**. Igual que cualquier tool, el agente las ve cuando la versión publicada las declara.

Límites: hasta **10 acciones de integración por agente** sumando todas las apps, y cada acción expone al modelo como mucho 24 parámetros (las requeridas siempre entran). Funciona igual en chat y en voz; en voz cuenta el tiempo de respuesta de la app, así que prefiere acciones concretas (crear un evento, buscar un contacto) a listados largos.

Si desconectas una app, sus tools siguen en el agente pero fallan con `integration_disconnected` hasta que la vuelvas a conectar.

## Lo que todavía no está

En la pantalla verás rotulado **Próximamente**: probar una tool suelta, editarla sin borrarla, el mensaje de espera («Mientras se ejecuta»), tools de tipo **Webhook** (aviso al terminar la llamada). Hoy la única forma de cambiar una tool es borrarla y crearla de nuevo, y hay que volver a pegar el secreto.
