Herramientas
Una herramienta (tool) amplía las capacidades del modelo usando herramientas integradas y servidores MCP remotos (Model Context Protocol), además de conectores como búsqueda web, lectura de archivos, APIs de terceros o tus propias funciones.
En esta página aprenderás qué son las tools, cómo declararlas, cómo se invocan, y mejores prácticas para diseñarlas de forma segura y confiable.
🚀 ¿Qué es una tool?
Una tool es una capacidad externa que el modelo puede invocar para:
Buscar en la web o en tus datos.
Llamar funciones propias (APIs internas).
Acceder a servicios de terceros (pagos, clima, CRM, etc.).
Coordinarse con MCP servers que exponen comandos remotos.
El modelo decide cuándo y con qué argumentos llamar una tool, según tu prompt y el esquema que declares.
🧩 Tipos de herramientas
function
Llamada a función con JSON Schema.
Clima, CFDI, CURP, consultas a DB, integraciones internas.
Web / Búsqueda
Conectores para resultados recientes.
Noticias, documentación pública, verificación.
Archivos
Recuperación y lectura de documentos.
PDFs, CSV, bases de conocimiento.
MCP Server
Comandos remotos vía Model Context Protocol.
Herramientas distribuidas/aisladas, plugins de equipo.
🏗️ Declarar una tool (function
)
function
)Para realizar un llamado a tools en nuestra API, sigue estos pasos:
Define un nombre, descripción y un schema de parámetros (
JSON Schema
).Marca los campos requeridos.
Evita
additionalProperties
si quieres máxima validación.
Ejemplo :
{
"model": "Saptiva Legacy",
"messages": [
{ "role": "user", "content": "Cuál es el clima en Ciudad de México hoy?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "obtener_clima",
"description": "Obtener la temperatura actual de una ubicación determinada.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "Ciudad y país, p. ej. Bogotá, Colombia"
}
},
"required": ["location"],
"additionalProperties": false
}
}
}
]
}
🔁 Ciclo de llamada a tool (overview)
El usuario pregunta → el modelo detecta que necesita datos externos.
El modelo propone una llamada a la función (con
name
+arguments
en JSON).Tu runtime ejecuta la función real (API/DB) usando esos argumentos.
Devuelves el resultado como mensaje de
tool
(string JSON o texto).El modelo continúa la conversación usando ese resultado.
Importante: valida en tu servidor los
arguments
antes de ejecutar la acción.
📦 Formato de la respuesta de la tool
El contenido debe ser serializable (JSON o texto claro).
Incluye campos estables y mensajes de error con códigos reutilizables.
Respuesta sugerida (éxito)
{
"ok": true,
"data": {
"location": "Ciudad de México, MX",
"temperature_c": 21.4,
"condition": "Parcialmente nublado",
"observed_at": "2025-10-14T14:05:00Z",
"source": "meteo_api_v2"
}
}
Respuesta sugerida (error)
{
"ok": false,
"error": {
"code": "LOCATION_NOT_FOUND",
"message": "No se pudo resolver la ubicación solicitada.",
"hint": "Prueba con: 'Ciudad, País', e.g. 'Bogotá, Colombia'."
}
}
🛡️ Seguridad y buenas prácticas
Validación estricta de entrada (respeta el
JSON Schema
).Idempotencia para operaciones que puedan reintentarse.
Tiempos de espera razonables (timeouts) y reintentos con exponential backoff.
Registro (logging) sin PII sensible. Enmascara datos cuando corresponda.
Rate limits: si tu tool llama APIs externas, implementa control local y respeta encabezados como
retry-after
.Versionado: versiona tus funciones (
obtener_clima_v2
) para cambios incompatibles.
🧪 Pruebas: patrones recomendados
Unit tests para:
Conversión de argumentos del modelo → función.
Validaciones y manejo de errores.
Formato de la respuesta de tool.
Tests de contrato entre tool y el modelo (entradas/salidas esperadas).
Mocks para servicios externos.
🔧 Manejo de errores y retry-after
retry-after
Si una API externa devuelve HTTP 429 con encabezado retry-after
, respeta el tiempo indicado antes de reintentar. Esto evita bloqueos y mantiene saludable tu integración.
# Pseudocódigo
if resp.status_code == 429:
wait = int(resp.headers.get("retry-after", "1"))
sleep(wait)
retry()
📚 Plantilla mínima de una tool (servidor)
type Args = { location: string };
export async function obtener_clima(args: Args) {
if (!args?.location || typeof args.location !== "string") {
return { ok: false, error: { code: "BAD_REQUEST", message: "location es requerido" } };
}
try {
const data = await meteoClient.current(args.location); // tu SDK o fetch
return {
ok: true,
data: {
location: data.city,
temperature_c: data.temp_c,
condition: data.condition,
observed_at: data.observed_at,
source: "meteo_api_v2"
}
};
} catch (e: any) {
if (e.status === 429) {
return {
ok: false,
error: { code: "UPSTREAM_RATE_LIMIT", message: "Proveedor saturado" },
meta: { retry_after: e.headers?.["retry-after"] ?? 1 }
};
}
return { ok: false, error: { code: "UPSTREAM_ERROR", message: "Fallo del proveedor" } };
}
}
🧭 Consejos de diseño
Un propósito claro por tool: evita funciones “multiuso” demasiado generales.
Descripciones ricas: ayuda al modelo a saber cuándo llamar la tool.
Ejemplos en el prompt del sistema: fomentan el uso correcto.
Campos canónicos:
ok
,data
,error.code
,error.message
,hint
,meta
.Observabilidad: registra latencia, tasas de acierto y errores por tool.
✅ Checklist de publicación
Última actualización