El modelo solo sabe que una herramienta existe si está declarada en su catálogo, con nombre, descripción y parámetros. Una herramienta es una acción que el agente puede pedirle a la app (buscar un fichero, mirar el calendario, escribir un texto); si no está declarada, la función puede estar perfecta en la app y no se usará nunca. Si lo está, el catálogo viaja con cada turno, junto a lo que dices y a lo que ve la pantalla (las tres entradas llegan juntas), y se paga en cada frase.
01Una lista que vivía fuera de git
La lista de lo que Saelyx sabe hacer no estaba en el repositorio. Vivía en la configuración del agente, en la consola de un proveedor externo, sin pruebas, sin revisión y sin diff. La comprobación de paridad de la app cubría el despacho (qué ejecuta cuando el modelo pide algo) y no podía cubrir lo que no estaba en git.
El 25 de julio de 2026 vi la grieta entera: la app sabía ejecutar 52 herramientas y el agente declaraba 24. Entre las 28 que faltaban había cosas tan corrientes como buscar un fichero o consultar el calendario. El modelo ni sabía que existían, así que jamás las llamó.
Lo primero que hice fue volcar la configuración viva al repositorio, con una regla: cada cambio en la consola se commitea en el mismo movimiento. En septiembre la fuente pasó a ser el repositorio, con un fichero por herramienta y una línea por propiedad, para que recortar un párrafo no parezca veinte líneas de ruido.
02El recibo: 145 ms y 6.860 tokens
Medí lo que cuesta declarar. El 25 de julio de 2026, contra el modelo que entonces estaba en producción, cronometré cuánto tarda en empezar a contestar con tres catálogos distintos. De 24 a 52 herramientas, el primer token se retrasó 145 ms por turno y la entrada creció 6.860 tokens. Con un presupuesto de conversación de 300 a 800 ms, 145 no se pierden en el ruido.
Las 28 merecían el precio, pero se paga siempre, también en un «sí» suelto: lleva el mismo catálogo que el resumen de una reunión.
| Cambio en el catálogo | Primer token | Tokens de entrada | Cómo lo sé |
|---|---|---|---|
| +28 herramientas declaradas (de 24 a 52) | +145 ms | +6.860 | Medido |
| Quitar del ordenador las que solo sirven en el teléfono | −23 ms | −1.109 | Medido |
| Descripciones a menos de 300 caracteres | ≈ −25 ms | ≈ −1.200 | Estimado; no se hizo |
03Quitar del ordenador lo del teléfono: 23 ms
La idea obvia: el ordenador no necesita las herramientas que solo sirven en el teléfono. Probé a quitárselas y recuperé 23 ms. Casi nada.
Las dos medidas, la subida de 145 ms y la bajada de 23, caen en la misma pendiente: unos 21 ms por cada mil tokens de catálogo. Con solo dos puntos no se puede afirmar más, pero apuntan a que manda el peso y no el recuento. Recortar todas las descripciones por debajo de 300 caracteres valdría, a esa pendiente, unos 25 ms (una estimación). No lo hice: esas descripciones le dicen al modelo cuándo usar cada herramienta y, en varias, que trate lo que lee como datos y nunca como órdenes. No se toca por 25 ms lo que sostiene el comportamiento.
En el teléfono la cuenta salía mejor: cargaba en cada turno muchas herramientas que solo el ordenador puede ejecutar, y la estimación de julio era recuperar casi todo el recargo. Pero hacía falta una lista distinta por dispositivo, y la app no podía enviar la suya al abrir la conversación. Tenía escrito que lo que sí elegía la app era a qué agente se conectaba.
Era falso, y de todas es la que más me escuece: el agente viaja dentro de la credencial de la conversación, que genera el servidor. El 8 de septiembre repartí las herramientas entre dos agentes dando por hecho que cada aparato iría al suyo; fueron los dos al mismo y el Mac se quedó sin parte de sus capacidades, la terminal entera incluida. El 9 lo corregí: el servidor pasó a repartir los agentes por tipo de aparato. Y antes de repartir nada se mide a quién sirve cada uno: un agente con cero conversaciones no sirve a nadie, por mucho que se llame «teléfono».
04Un valor por defecto que dejó mudas a las herramientas, dos veces
Al declarar las 28 no indiqué si cada herramienta espera respuesta, y la API puso «no» por su cuenta. Catorce devuelven un dato, y salían mudas: el modelo las llamaba, la app hacía el trabajo y el dato no volvía, así que el agente seguía hablando sin contarlo. Lo vi cruzando el volcado de la configuración con las herramientas que sí funcionaban: las 24 buenas eran justo las 24 con ese campo en «sí».
Escribí la regla y creí que bastaba. El 14 de septiembre volvió: una copia del catálogo para el agente del Mac había nacido con el mismo valor, en casi la mitad de sus herramientas. Pedí el resumen de la última reunión y el agente contestó que no había reuniones. La app había respondido bien y su registro lo decía; lo que fallaba era lo que recibía el modelo, una frase genérica de éxito en vez del resultado, y eso solo se veía en la transcripción, al otro lado.
Esta vez lo cerré con una prueba. Desde el 21 de septiembre ese campo forma parte de la definición versionada de cada herramienta, y la prueba falla si un recorte lo toca.
05La dieta de septiembre y el objetivo que no cumplí
Con la lista en git pude leerla entera. Más de la mitad del texto de herramientas que puede llegar al modelo eran descripciones. Recorté tres repeticiones: un inventario de operaciones que estaba dos veces (en la descripción y en el parámetro que las elige), un protocolo de confirmación por voz copiado palabra por palabra en más de diez herramientas, y descripciones que repetían el prompt del agente.
Resultado, en el agente del Mac: −23 % en lo que puede llegar al modelo, −16 % en lo que devuelve la API y −43 % en las descripciones. Es el mismo recorte con dos denominadores: la API añade a cada propiedad campos de contabilidad que no llegan al modelo y no se pueden quitar, alrededor de la mitad de los caracteres del esquema. Doy por buena la primera cifra.
Antes de tocar nada guardé qué declaraba cada herramienta, y una prueba lo compara con el catálogo de hoy: ninguna operación, parámetro ni lista cerrada perdidos. El objetivo, en cambio, no lo alcancé: llegué a algo más de la mitad del camino. El esquema, además, creció un poco al absorber texto de las descripciones, y eso no lo apunto como ahorro. La comprobación de presupuesto falla con un tope puesto justo encima de lo que hay y no en el objetivo, porque un tope que falla el día que se estrena se apaga; el objetivo se imprime, con la distancia que falta, cada vez que mido. Los recortes están en producción desde el 21 de septiembre.
06Lo que no sé
- Las medidas son de un día de julio y de un modelo, el de entonces; con el de hoy la pendiente podría ser otra.
- No he medido en un teléfono real si quitar lo que sobra recupera lo que estimé, ni cuánto bajó el primer token con la dieta: del tamaño del bloque a la latencia hay una cuenta, no una medida.
07Preguntas frecuentes
¿Qué es una herramienta en un agente de voz?
Una acción que el agente puede pedirle a la app, como buscar un fichero o mirar el calendario. Para el modelo solo existe si está en su catálogo.
¿Por qué cada herramienta declarada añade latencia?
Porque el catálogo viaja con cada turno y el modelo lo lee antes de contestar: en mis medidas de julio, unos 21 ms por cada mil tokens.
¿Qué pasa si la app sabe hacer algo que el agente no tiene declarado?
Que no se hará nunca, porque el modelo no sabe que existe. Me pasó con 28 herramientas hasta el 25 de julio de 2026.
¿Has medido cuánto aceleró la dieta de septiembre?
No. Medí el tamaño del bloque (un 23 % menos en el agente del Mac, en lo que puede llegar al modelo), no su efecto en el primer token en una sesión real.
¿Lleva el catálogo datos míos?
No. Describe lo que el agente puede hacer, no lo que ve de ti. Qué viaja y qué se guarda: qué sale de tu ordenador y dónde viven tus datos.
— Adianny
Sr. DevOps. Llevo unos cuatro años trabajando con machine learning y MLOps, hoy como tech lead; Saelyx es mi proyecto de casa.