Herramientas
Una herramienta es una acción nombrada que la IA puede invocar, con entradas tipadas — p. ej.send_email(to, subject, body). Las herramientas se declaran en el archivo tools.ts de una skill y, para herramientas que tu app sirve, están respaldadas por una ruta HTTP en uno de tus componentes. Esta página es la fuente de verdad para el contrato de herramientas; Skills cubre dónde vive tools.ts.
Declarar una herramienta
Cada entrada entools.ts tiene un name seguro para proveedores, un displayName amigable, una description, un esquema Zod input, y un target que indica qué invoca Kazzle.
Destinos
target es la dirección reutilizable para una herramienta o botón de acción requerida. Una llamada directa de herramienta de IA y un clic de botón pueden usar el mismo objeto target, por lo que ambos ejecutan el mismo código.
Los destinos HTTP usan los mismos campos de solicitud:
body: '${input}'.
Referencias
Kazzle resuelve referencias en los camposquery, headers, body y url del destino HTTP antes del envío:
${input}— toda la entrada de herramienta, o toda la entrada de botón.${input.path}— un valor anidado de la entrada.${env.NAME}— una variable de entorno nombrada de laenv.collectiondeclarada del componente de app propietario +env.environment.
$${input.name} cuando necesites texto literal ${input.name}.
Solicitud del manejador
Para un destinoapp, añade la ruta coincidente en el componente destino. Con body: '${input}', Kazzle envía la entrada tipada como cuerpo JSON:
app también reciben:
Los destinos de app no pueden establecer
Authorization a través de headers; Kazzle es propietario de ese encabezado. Lee el contexto con toolContext(req) desde @kazzle/app/tools cuando el manejador debe ramificarse entre thread y Tools API.
Una herramienta declarada sin una ruta coincidente no hace nada útil — añade ambas juntas. tools.json no es compatible; el compilador de app falla si encuentra uno.
Respuesta del manejador
Devuelve texto sin formato, o JSON con hasta tres canales:content— el resultado sin formato que la IA lee (alimentado al modelo). Requerido.markdown— opcional. Un resumen de texto enriquecido corto renderizado en la tarjeta de herramienta (react-markdown; el HTML sin procesar se escapa). Bueno para una oración, una lista pequeña, un enlace en línea. Una ruta relativa sin procesar se renderiza como texto preformateado muerto — los enlaces deben ser absolutos.embedUrl— opcional. Una URL absoluta que tu app sirve; la tarjeta la renderiza en un iframe aislado. Así es como muestras una interfaz real y de ancho completo — una pantalla de conexión, un panel, un gráfico. Tu app aloja y es propietaria de la página, por lo que puede ser completamente interactiva contra tu propio backend, cookies y OAuth. Nada se escribe en el drive.
embedUrl prevalece sobre markdown cuando ambos están establecidos. Siempre mantén un content significativo — eso es lo que la IA lee.
Acción requerida
Una herramienta de app puede pausar el thread cuando necesita una acción del usuario (o dispositivo). Devuelvetype: 'action_required' con un título de tarjeta y botones. Solo válido cuando toolContext(req).source === 'thread' — sobre la Tools API (source: 'api'), devuelve un error de dominio normal en su lugar.
/chat/resume después de que se presiona un botón. Los clientes coincidentes ven los botones del autor; los clientes no coincidentes aún ven Omitir/Cancelar más “Continuar en ”. Un botón sin target envía su input como resultado de herramienta. Un botón con un destino ejecuta ese destino primero, luego usa el resultado del destino como resultado de herramienta.
Interfaz enriquecida — incrustar una página alojada en app
Cuando el resultado de una herramienta es visual o interactivo (una pantalla de conexión, un gráfico, un panel de resumen), sirve la página desde uno de tus componentes y devuelve su URL absoluta comoembedUrl. Construye la URL a partir de la URL del componente inyectada — nunca una ruta relativa.
embedUrl sobre emitir cadenas HTML: tu app ya sirve páginas, la interfaz permanece interactiva y versionada con tu código, y ningún artefacto por llamada se escribe en ningún lugar.