# Herramientas propias

> Conecta tus agentes con tus sistemas: código JavaScript que corre aislado y revisa eltick, o una llamada HTTP a tu API sin escribir código.

Una **herramienta propia** le da al agente acceso a tus sistemas: consultar una deuda, verificar la cobertura de una dirección, diagnosticar un servicio, reiniciar un equipo, crear un pedido. El agente decide cuándo usarla según lo que dice su descripción y tu prompt.

Las herramientas son de tu negocio, no de un agente: las creas una vez en **Agentes IA › Herramientas** y las sumas a los agentes que quieras desde su pestaña **Herramientas**.

## Dos tipos

<CardGroup cols={2}>
  <Card title="Código (JavaScript)" icon="code">
    Para lógica propia: varias llamadas, cálculos, combinar respuestas, guardar datos en el contacto. Corre aislado y **la revisa el equipo de eltick** antes de que tus agentes puedan usarla. Mira el [SDK](/avanzados/sdk).
  </Card>
  <Card title="Llamada HTTP" icon="globe">
    Una llamada `GET`, `POST`, `PUT`, `PATCH` o `DELETE` a tu API, sin escribir código. Eliges dónde va cada entrada, armas el cuerpo JSON, qué parte de la respuesta ve el agente y qué se guarda. Se usa sin revisión.
  </Card>
</CardGroup>

## Crear una herramienta

<Steps>
  <Step title="Tipo, nombre y cuándo usarla">
    En **Agentes IA › Herramientas**, toca **Nueva herramienta**. Elige el tipo y escribe:

    - **Nombre**, para tu equipo: *SIACoop · Consultar deuda*.
    - **Nombre para la IA**: minúsculas y guión bajo, como la ve el agente: `siacoop_consultar_deuda`.
    - **Cuándo usarla**: lo que lee el agente para decidir. Sé concreto: *Consulta la deuda de un cliente con su número de usuario: devuelve el total, las facturas y el link de pago.*
  </Step>
  <Step title="Código o URL">
    En una herramienta de código escribes la función en la pestaña **Código**. A la izquierda tienes el SDK para insertar llamadas, y a la derecha declaras los **permisos** y los **dominios** a los que llama.

    ```js
    export default async function run(input, eltick) {
      const res = await eltick.fetch(`https://api.siacoop.com.ar/v2/clientes/${input.numero_usuario}/deuda`, {
        auth: input.credenciales,
      })
      if (res.status === 404) return { encontrado: false }
      const data = await res.json()
      await eltick.contact.setField("numero_usuario", input.numero_usuario)
      return { encontrado: true, total: data.importe_total, link_pago: data.url_pronto_pago }
    }
    ```

    En una herramienta HTTP completas la pestaña **Llamada**: el método, la URL (por ejemplo `https://api.tuempresa.com/pedidos/{numero}`), el cuerpo y qué hacer con la respuesta. Mira [Herramientas HTTP](#herramientas-http).
  </Step>
  <Step title="Entradas">
    Qué recibe la herramienta y de dónde sale cada dato: fijo, una variable del contacto o de una credencial, o lo completa el agente. Mira [Entradas](/avanzados/entradas).
  </Step>
  <Step title="Ajustes">
    Confirmación del cliente, tope de usos por conversación, qué hacer si falla y cómo leer la respuesta. Están explicados abajo.
  </Step>
  <Step title="Probar">
    En **Probar** la ejecutas de verdad contra tu sistema, con una conversación real para las variables del contacto (nada se le manda al cliente). Ves el resultado, las llamadas, los logs y los cambios que pide sobre el contacto. En una herramienta HTTP ves también lo que ve el agente, la respuesta completa y lo que se guardaría en variables y campos.
  </Step>
  <Step title="Enviar a revisión (solo código)">
    Toca **Enviar a revisión**. Te avisamos por WhatsApp y por email cuando la aprobemos o si hay algo para cambiar. Mira [Revisión del código](/avanzados/revision).
  </Step>
</Steps>

Después, en el agente, activa la herramienta en **Herramientas › Herramientas propias** y nómbrala en el prompt donde corresponda.

<Tip>
  En la misma pestaña están **Escuchar notas de voz** y **Mirar las fotos que mandan**. En el historial que recibe el modelo, un audio transcripto aparece como `[nota de voz] <lo que dijo>` y una foto vieja como `[imagen]`. Ver [Audios y fotos](/guias/agentes/herramientas#audios-y-fotos).
</Tip>

## Herramientas HTTP

Con una herramienta HTTP integras la mayoría de las APIs sin escribir código. Todo se configura en la pestaña **Llamada** y en **Entradas**.

### Método y URL

Elige `GET`, `POST`, `PUT`, `PATCH` o `DELETE`. En la URL, `{entrada}` se reemplaza por el valor de esa entrada (codificado para URL):

```
https://api.tuempresa.com/clientes/{numero_cliente}/pedidos/{numero_pedido}
```

Cada `{nombre}` de la URL tiene que ser una entrada. Si no, el editor te avisa antes de guardar.

### Dónde va cada entrada

En **Entradas**, cada entrada de una herramienta HTTP tiene **Dónde va**:

| Ubicación | Cómo sale | Ejemplo |
| --- | --- | --- |
| **Parámetro de la URL** | `?clave=valor` | `?estado=pendiente` |
| **En la ruta** | Reemplaza `{clave}` en la URL | `/pedidos/1042` |
| **En el cuerpo** | Una propiedad del JSON | `{ "cantidad": 3 }` |
| **Header** | Un header del pedido | `X-Sucursal: 12` |

Si la dejas en **Automático**: va en la ruta si la URL la nombra; si no, como parámetro en `GET` y `DELETE`, y en el cuerpo en `POST`, `PUT` y `PATCH`. Una credencial en automático va como autenticación, según su tipo. Si le eliges una ubicación, el valor de la credencial se pone ahí (por ejemplo, un header propio).

Con **Nombre en el pedido** mandas la entrada con otro nombre, por ejemplo la entrada `token` como el header `X-Api-Key`, o `pagina` como el parámetro `page[number]`.

### Cuerpo

Para `POST`, `PUT`, `PATCH` y `DELETE` puedes escribir el cuerpo como una plantilla JSON. Usa `{entrada}`, `{var.clave}` (variables de la conversación) y los datos del contacto, la conversación y la cuenta (`{contacto.nombre}`, `{contacto.campo.clave}`, `{conversacion.id}`, `{cuenta.nombre}`…):

```json
{
  "cliente": { "nombre": "{contacto.nombre}", "telefono": "{contacto.telefono}" },
  "items": [{ "sku": "{sku}", "cantidad": {cantidad} }],
  "nota": "Pedido desde WhatsApp: {nota}"
}
```

- **Entre comillas**, el valor va como texto y se escapa: aunque el cliente escriba comillas o saltos de línea, el JSON no se rompe.
- **Sin comillas**, va tal cual como JSON: números, `true`/`false`, `null` u objetos (`{cantidad}` → `3`).

Si dejas el cuerpo vacío, se manda un JSON con las entradas que van en el cuerpo.

### Respuesta

- **Qué ve el agente**: rutas dentro de la respuesta, como `data.items[0].precio` o `pedido.estado` (hasta 20). Si pones alguna, el agente ve solo esas; si no, ve la respuesta entera. Así el agente no se confunde con datos que no necesita.
- **Guardar de la respuesta** (hasta 10): toma un valor de la respuesta y lo guarda en:
  - una **variable de la conversación**: queda como `{var.clave}` para el prompt, para otras herramientas (también en la misma respuesta del agente) y para los pasos siguientes de la automatización;
  - un **campo del contacto**: se guarda al terminar la respuesta del agente, como cualquier dato del contacto.

Las reglas de **Cómo leer la respuesta** miran la respuesta entera, aunque el agente vea solo una parte.

### Tiempo máximo de espera

De 1 a 30 segundos (10 por defecto). Si tu API no responde a tiempo, la herramienta devuelve un error y el agente sigue lo que dice **Si falla**.

## Ajustes

### Pedir confirmación del cliente

Para las herramientas que **hacen cambios** (reiniciar un equipo, dar de baja, crear un pedido). El agente solo puede usarla si el cliente ya dijo que sí de forma explícita en la conversación; si no, la herramienta le responde que pida la confirmación primero.

En el chat de prueba y en los casos de prueba, las herramientas con confirmación y las HTTP que no son `GET` (`POST`, `PUT`, `PATCH` y `DELETE`) **no se ejecutan**: se simulan como si hubieran funcionado.

### Máximo por conversación

Cuántas veces se puede usar en una misma conversación, por ejemplo *1 vez* para una verificación de cobertura. Cuando llega al tope, el agente recibe un aviso y no la vuelve a usar.

### Si falla

Qué hace el agente cuando la herramienta devuelve un error: *Decir que no pudo consultarlo y ofrecer la guardia técnica.*

### Cómo leer la respuesta

Reglas que convierten el resultado en una indicación concreta para el agente. Se evalúan de arriba abajo y la primera que se cumple se suma al resultado como `indicacion`:

| Si el campo | Condición | Entonces el agente… |
| --- | --- | --- |
| `bloqueado` | es verdadero | Dice que el servicio está bloqueado por falta de pago y manda la deuda. No diagnostica ni reinicia. |
| `conectado` | es verdadero | Pregunta si quiere reiniciar la conexión. |
| `conectado` | es falso | Corre el diagnóstico y explica la causa sin jerga. |
| *(vacío)* | está vacío | No inventa un estado: avisa que no ubicó el servicio. |

Las condiciones posibles son *es igual a*, *no es igual a*, *es verdadero*, *es falso*, *está vacío*, *tiene valor* y *contiene*. Para campos anidados usa puntos: `plan.estado`. Así las decisiones importantes no dependen de que el modelo interprete bien un JSON.

## Qué recibe el agente

Cuando el agente usa una herramienta, recibe un JSON con:

```json
{
  "ok": true,
  "resultado": { "encontrado": true, "total": 38420.5 },
  "indicacion": "Mandá el total y el link de pago, una URL por línea."
}
```

Si falló, recibe `ok: false`, el `error` y, si lo configuraste, `que_hacer`. El resultado se corta a 8.000 caracteres: devuelve solo lo que el agente necesita.

## Dónde se ven

- En el **Registro** del agente, cada respuesta muestra qué herramientas usó, con qué datos y qué devolvieron.
- En **Agentes IA › Herramientas**, cada herramienta muestra qué agentes la usan y su estado: *Aprobada · v3*, *En revisión* o *Sin enviar a revisión*.
