Un agente de soporte buscó el pedido de un cliente, encontró el número de seguimiento correcto y citó con confianza una política de devoluciones que había sido actualizada dos meses antes. La herramienta funcionó. La API devolvió datos. El cliente escuchó una respuesta clara, específica e incorrecta, y presentó un contracargo al día siguiente.
Esto es lo importante sobre las herramientas para agentes de IA: no son funcionalidades opcionales. Son la diferencia entre un chatbot que habla sobre hacer cosas y un agente que realmente las hace. Un agente sin herramientas puede empatizar con tu retraso en el envío. Un agente con herramientas puede buscar tu número de seguimiento, consultar la API de estado del transportista y reprogramar la entrega, todo en la misma conversación.
Pero un mal sistema de herramientas es peor que no tener herramientas. Un chatbot que dice "No tengo acceso a esa información" es molesto. Un agente que actúa con confianza sobre datos obsoletos, o llama a la API equivocada, o se queda colgado ocho segundos esperando un timeout, eso es un cliente que acabas de perder.
Este artículo te enseña a construir un sistema de herramientas desde cero. Escribirás TypeScript real y ejecutable. Al final, entenderás exactamente cómo funcionan los registros de herramientas, los bucles de ejecución, la gestión de credenciales y el monitoreo. Luego lo romperemos, intencionalmente, al ver qué pasa cuando tu prototipo de tres herramientas se encuentra con 200 clientes concurrentes en producción.
Requisitos previos y configuración
Necesitarás Node.js 18+, una API key de Anthropic para Claude y una terminal. Todo el código es TypeScript. Instala el SDK y estarás listo:
npm install @anthropic-ai/sdkCrea un archivo .env:
ANTHROPIC_API_KEY=sk-ant-...Usaremos la API tool_use de Claude para el bucle de ejecución. Si eres nuevo en cómo los LLMs seleccionan y llaman herramientas, la guía profunda sobre function calling cubre la mecánica en detalle.
¿Qué es un sistema de herramientas?
Un sistema de herramientas es la infraestructura que permite a un agente de IA realizar acciones en el mundo real, no solo generar texto sobre ellas. Tiene cuatro capas: un registro de herramientas disponibles, un motor de ejecución que las llama, una capa de autenticación que gestiona credenciales, y monitoreo que rastrea qué sucedió.
Para agentes orientados al cliente, lo que está en juego en cada capa es más alto que para herramientas internas. Cuando tu bot interno de Slack no logra obtener un ticket de Jira, un desarrollador se encoge de hombros y reintenta. Cuando tu agente de soporte no puede buscar un pedido mientras un cliente frustrado está al teléfono, ese cliente lo cuenta en Twitter.
Así se ve una llamada de herramienta de principio a fin:
Tres cosas suceden que no obtienes gratis: el agente descubre qué herramientas existen (registro), la llamada a la herramienta llega a una API real con credenciales reales (ejecución + autenticación), y alguien sabe que sucedió (monitoreo). Cada uno de esos es un sistema que necesitas construir.
Constrúyelo: Un registro mínimo de herramientas
El registro de herramientas es la base: es donde tu agente aprende qué puede hacer. Cada herramienta necesita un nombre, una descripción que el LLM pueda leer, un esquema que define qué argumentos acepta, y una función que realmente la ejecuta.
Comencemos con la interfaz:
interface ToolResult {
success: boolean;
data?: unknown;
error?: string;
}
interface Tool {
name: string;
description: string;
parameters: {
type: "object";
properties: Record<string, {
type: string;
description: string;
enum?: string[];
}>;
required: string[];
};
execute: (params: Record<string, unknown>) => Promise<ToolResult>;
}El campo description está haciendo más trabajo del que parece. El LLM lo lee para decidir si llama a la herramienta. Si la descripción es vaga, el agente elige la herramienta equivocada. Si es demasiado específica, el agente nunca la elige cuando debería. Este es el mismo principio de claridad de la ingeniería de prompts: la precisión en la instrucción determina la precisión en el resultado.
Ahora definamos tres herramientas que un agente real orientado al cliente usaría:
const lookupOrder: Tool = {
name: "lookup_order",
description:
"Retrieves the current status, tracking number, carrier, and estimated " +
"delivery date for a customer order given its order ID. Use this when a " +
"customer asks about shipping, delivery, or order status.",
parameters: {
type: "object",
properties: {
orderId: {
type: "string",
description: "The order ID (format: ORD-XXXXX)",
},
},
required: ["orderId"],
},
execute: async (params) => {
const orderId = params.orderId as string;
// In production: call your order management API
const response = await fetch(
`https://api.example.com/orders/${orderId}/status`,
{ headers: { Authorization: `Bearer ${process.env.ORDER_API_KEY}` } }
);
if (!response.ok) {
return { success: false, error: `Order ${orderId} not found` };
}
const data = await response.json();
return { success: true, data };
},
};
const checkInventory: Tool = {
name: "check_inventory",
description:
"Checks real-time inventory availability for a product by SKU. Returns " +
"current stock count and whether the item is available for immediate " +
"shipping. Use when a customer asks if something is in stock.",
parameters: {
type: "object",
properties: {
sku: {
type: "string",
description: "Product SKU identifier",
},
},
required: ["sku"],
},
execute: async (params) => {
const sku = params.sku as string;
const response = await fetch(
`https://api.example.com/inventory/${sku}`,
{ headers: { Authorization: `Bearer ${process.env.INVENTORY_API_KEY}` } }
);
if (!response.ok) {
return { success: false, error: `SKU ${sku} not found` };
}
const data = await response.json();
return { success: true, data };
},
};
const scheduleCallback: Tool = {
name: "schedule_callback",
description:
"Schedules a callback from a human support agent at a specific date and " +
"time. Use when the customer's issue requires human assistance or when " +
"the customer explicitly asks to speak with a person.",
parameters: {
type: "object",
properties: {
customerPhone: {
type: "string",
description: "Customer phone number in E.164 format",
},
preferredTime: {
type: "string",
description: "Preferred callback time in ISO 8601 format",
},
reason: {
type: "string",
description: "Brief summary of why the callback is needed",
},
},
required: ["customerPhone", "preferredTime", "reason"],
},
execute: async (params) => {
const response = await fetch("https://api.example.com/callbacks", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.CALLBACK_API_KEY}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
return { success: false, error: "Failed to schedule callback" };
}
const data = await response.json();
return { success: true, data };
},
};Ahora, el registro en sí, solo un Map con registro y búsqueda:
class ToolRegistry {
private tools = new Map<string, Tool>();
register(tool: Tool): void {
this.tools.set(tool.name, tool);
}
get(name: string): Tool | undefined {
return this.tools.get(name);
}
listForLLM(): Array<{
name: string;
description: string;
input_schema: Tool["parameters"];
}> {
return Array.from(this.tools.values()).map((tool) => ({
name: tool.name,
description: tool.description,
input_schema: tool.parameters,
}));
}
}
const registry = new ToolRegistry();
registry.register(lookupOrder);
registry.register(checkInventory);
registry.register(scheduleCallback);El método listForLLM() genera las definiciones de herramientas en el formato que espera la API de Anthropic. Ahora conectémoslo con Claude y construyamos el bucle de ejecución, el ciclo de Razonar, Seleccionar, Ejecutar y Observar:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
async function handleCustomerMessage(
userMessage: string
): Promise<string> {
const tools = registry.listForLLM();
const messages: Anthropic.MessageParam[] = [
{ role: "user", content: userMessage },
];
// Keep looping until the agent produces a final text response
while (true) {
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
system:
"You are a customer support agent. Use the available tools to " +
"look up real data before answering. Never guess — if you can't " +
"find the information, say so honestly.",
tools,
messages,
});
// If the model wants to call tools, execute them and feed results back
if (response.stop_reason === "tool_use") {
// Add the assistant's response (includes tool_use blocks)
messages.push({ role: "assistant", content: response.content });
const toolResults: Anthropic.ToolResultBlockParam[] = [];
for (const block of response.content) {
if (block.type === "tool_use") {
const tool = registry.get(block.name);
if (!tool) {
toolResults.push({
type: "tool_result",
tool_use_id: block.id,
content: `Tool "${block.name}" not found`,
is_error: true,
});
continue;
}
const result = await tool.execute(
block.input as Record<string, unknown>
);
toolResults.push({
type: "tool_result",
tool_use_id: block.id,
content: JSON.stringify(result),
is_error: !result.success,
});
}
}
messages.push({ role: "user", content: toolResults });
continue;
}
// Model is done — extract the text response
const textBlock = response.content.find(
(block) => block.type === "text"
);
return textBlock?.text ?? "I wasn't able to process that request.";
}
}
// Try it
const answer = await handleCustomerMessage(
"Where's my order ORD-48291?"
);
console.log(answer);Eso es un sistema de herramientas funcional. El agente recibe un mensaje del cliente, examina las herramientas disponibles, decide cuál llamar, la ejecuta, lee el resultado y formula una respuesta. Si la herramienta falla, el error se pasa de vuelta al agente como una observación, y puede decidir cómo manejarlo: reintentar, probar una herramienta diferente, o explicar la situación al cliente.
Constrúyelo: Autenticación y secretos
El código anterior tiene un problema que quizás notaste: las API keys están codificadas en referencias a process.env dispersas en las definiciones de herramientas. Eso funciona para un demo. En producción con agentes orientados al cliente, necesitas credenciales que estén gestionadas centralmente, que se puedan rotar sin re-desplegar, y que estén delimitadas para que la herramienta de Shopify no pueda acceder accidentalmente a tus claves de Stripe.
Aquí hay un almacén de credenciales que separa los secretos de las definiciones de herramientas:
interface Credential {
id: string;
name: string;
headers: Record<string, string>; // e.g., { Authorization: "Bearer sk-..." }
expiresAt?: Date;
}
class CredentialStore {
private credentials = new Map<string, Credential>();
add(credential: Credential): void {
this.credentials.set(credential.id, credential);
}
get(id: string): Credential | undefined {
const cred = this.credentials.get(id);
if (!cred) return undefined;
// Check expiration
if (cred.expiresAt && cred.expiresAt < new Date()) {
console.warn(
`Credential "${cred.name}" expired at ${cred.expiresAt.toISOString()}`
);
return undefined;
}
return cred;
}
rotate(id: string, newHeaders: Record<string, string>): void {
const existing = this.credentials.get(id);
if (!existing) throw new Error(`Credential ${id} not found`);
this.credentials.set(id, { ...existing, headers: newHeaders });
}
}Ahora las herramientas referencian IDs de credenciales en lugar de secretos directos:
interface SecureTool extends Tool {
credentialId: string; // Reference to credential store, not a raw key
}
async function executeSecureTool(
tool: SecureTool,
params: Record<string, unknown>,
credentialStore: CredentialStore
): Promise<ToolResult> {
const credential = credentialStore.get(tool.credentialId);
if (!credential) {
return {
success: false,
error: `Authentication unavailable for tool "${tool.name}"`,
};
}
// Inject credential headers into the execution context
const originalFetch = globalThis.fetch;
globalThis.fetch = async (input, init) => {
const headers = new Headers(init?.headers);
for (const [key, value] of Object.entries(credential.headers)) {
headers.set(key, value);
}
return originalFetch(input, { ...init, headers });
};
try {
return await tool.execute(params);
} finally {
// Restore original fetch
globalThis.fetch = originalFetch;
}
}Esto te da tres beneficios. Primero, la rotación de claves es una sola línea, credentialStore.rotate("shopify-prod", newHeaders), y cada herramienta que usa esa credencial toma el cambio inmediatamente. Segundo, obtienes verificación de expiración, así que una clave expirada devuelve un error limpio en lugar de un misterioso 401 de una API downstream. Tercero, las herramientas y credenciales están desacopladas, lo que significa que la misma definición de herramienta puede usar diferentes credenciales por workspace o por cliente.
En producción, este almacén estaría respaldado por un vault encriptado: AWS Secrets Manager, HashiCorp Vault, o una base de datos con encriptación en reposo. El patrón es el mismo independientemente del backend: las herramientas referencian IDs de credenciales, y los headers de autenticación se resuelven en tiempo de ejecución. Si estás ejecutando agentes multi-tenant donde diferentes clientes necesitan diferentes API keys, agregarías resolución basada en alcance: intenta la credencial específica del cliente primero, recurre al valor predeterminado del workspace. Este es exactamente el patrón de gestión de secretos que implementan las plataformas de agentes en producción.
Constrúyelo: Seguimiento de ejecución
Cuando un agente orientado al cliente llama a una herramienta durante una conversación en vivo, necesitas saber qué pasó. No eventualmente, no en un archivo de logs que alguien revisa la próxima semana, sino ahora mismo, en un dashboard que puedas filtrar por herramienta, por rango de tiempo, por tasa de éxito.
Aquí está el wrapper mínimo de seguimiento:
interface ExecutionRecord {
id: string;
toolName: string;
params: Record<string, unknown>;
result: ToolResult;
latencyMs: number;
timestamp: Date;
}
const executions: ExecutionRecord[] = [];
async function executeWithTracking(
tool: Tool,
params: Record<string, unknown>
): Promise<ToolResult> {
const start = Date.now();
const id = crypto.randomUUID();
try {
const result = await tool.execute(params);
const record: ExecutionRecord = {
id,
toolName: tool.name,
params,
result,
latencyMs: Date.now() - start,
timestamp: new Date(),
};
executions.push(record);
return result;
} catch (error) {
const errorResult: ToolResult = {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
executions.push({
id,
toolName: tool.name,
params,
result: errorResult,
latencyMs: Date.now() - start,
timestamp: new Date(),
});
return errorResult;
}
}Ahora agreguemos eso en algo útil:
interface ToolStats {
toolName: string;
totalCalls: number;
successfulCalls: number;
failedCalls: number;
successRate: number;
averageLatencyMs: number;
p95LatencyMs: number;
lastCalledAt: Date | null;
}
function getToolStats(toolName: string): ToolStats {
const records = executions.filter(
(e) => e.toolName === toolName
);
const successful = records.filter((e) => e.result.success);
const latencies = records.map((e) => e.latencyMs).sort(
(a, b) => a - b
);
return {
toolName,
totalCalls: records.length,
successfulCalls: successful.length,
failedCalls: records.length - successful.length,
successRate:
records.length > 0
? successful.length / records.length
: 0,
averageLatencyMs:
latencies.length > 0
? latencies.reduce((a, b) => a + b, 0) / latencies.length
: 0,
p95LatencyMs:
latencies.length > 0
? latencies[Math.floor(latencies.length * 0.95)]
: 0,
lastCalledAt:
records.length > 0
? records[records.length - 1].timestamp
: null,
};
}Con el seguimiento implementado, puedes responder preguntas que importan: "¿La herramienta de búsqueda de pedidos está más lenta hoy que ayer?" "¿Qué porcentaje de verificaciones de inventario están fallando?" "¿Qué herramienta no ha sido llamada en 30 días?" Estas son las métricas que los dashboards de monitoreo en producción muestran. Estamos construyendo la plomería que los alimenta.
La idea clave es que cada registro de ejecución se vincula a una conversación. En un sistema real, también incluirías campos de conversationId y agentId, para que cuando un cliente se queje de información incorrecta, puedas rastrear exactamente qué llamada de herramienta devolvió qué datos, cuánto tardó y si el resultado estaba obsoleto.
Mira cómo se rompe: Modos de falla en producción
Todo lo que has construido hasta ahora funciona. Tres herramientas, un registro, gestión de credenciales, seguimiento de ejecución. Si estás ejecutando un solo agente con un puñado de clientes, esto se sostiene bien.
Luego creces.
Aquí hay cinco formas en que este sistema falla cuando se encuentra con tráfico real de producción. Cada una es un problema que los equipos descubren después de haber lanzado, generalmente en el peor momento posible.
Problema 1: Proliferación de herramientas
Empiezas con 3 herramientas. Producto quiere que el agente maneje devoluciones, así que agregas initiate_return y get_return_status. Marketing quiere que responda preguntas sobre precios, así que agregas get_pricing y check_promotions. El equipo de envíos agrega track_package, estimate_delivery y change_delivery_address. Seis meses después, tienes 47 herramientas en el registro.
El LLM ahora lee 47 descripciones antes de cada decisión. La precisión en la selección de herramientas cae. Un cliente pregunta "¿Puedo devolver esto?" y el agente llama a check_inventory en lugar de initiate_return porque las descripciones son lo suficientemente similares como para confundir al modelo. Otro cliente pregunta sobre una promoción y el agente llama a get_pricing cuando debería haber llamado a check_promotions.
La solución son los toolsets: grupos curados de herramientas relacionadas asignados a contextos específicos. Tu agente de soporte obtiene el toolset de Soporte (búsqueda de pedidos, devoluciones, callbacks). Tu agente de ventas obtiene el toolset de Ventas (precios, promociones, inventario). Cada agente ve 8-12 herramientas en lugar de 47, y la precisión de selección vuelve a subir.
Este es el mismo principio que la jerarquía de instrucciones en ingeniería de prompts: menos ruido significa mejores decisiones. La investigación muestra que la precisión en la selección de herramientas se degrada por encima de 15-20 herramientas en un solo contexto. Los toolsets te mantienen bajo ese umbral sin sacrificar capacidad.
Problema 2: Infierno de versionamiento
Actualizas lookup_order para agregar un campo returnEligible a la respuesta. La API comienza a devolver el nuevo esquema. Pero los agentes que están a mitad de conversación ya vieron la definición anterior de la herramienta. No saben que returnEligible existe, así que no lo mencionan. O peor: cambias los parámetros requeridos, y un agente a mitad de conversación envía el formato de parámetros antiguo a la API nueva. El cliente recibe un error críptico o una respuesta parcial.
En el sistema DIY que construimos, no existe el concepto de versiones de herramientas. Cuando actualizas una herramienta, el cambio está en vivo al instante para todos, incluyendo agentes que iniciaron su conversación con la versión anterior.
Los sistemas en producción manejan esto con versionamiento de herramientas y deprecación gradual. Una actualización de herramienta crea una nueva versión. Las conversaciones existentes siguen usando la versión con la que comenzaron. Las nuevas conversaciones obtienen la última. Las versiones antiguas se deprecan con una fecha de fin de vida, no se eliminan sin aviso.
Problema 3: Rotación de autenticación
Tu API key de Shopify expira. En el almacén de credenciales que construimos, credentialStore.get("shopify-prod") devuelve undefined porque la verificación de expiración lo detecta. Bien. Obtienes un error limpio en lugar de un misterioso 401.
Pero error limpio o no, cada herramienta que usa Shopify se rompió simultáneamente. Si tienes 200 clientes a mitad de conversación y cuatro de tus herramientas dependen de Shopify, son potencialmente 200 personas escuchando "Lo siento, estoy teniendo problemas para buscar eso en este momento."
La solución es multicapa: alertas de rotación automatizadas antes de que las claves expiren (no después), credenciales de respaldo que se activan ante fallas primarias, y circuit breakers que detectan fallas de autenticación generalizadas y cambian a degradación elegante ("Permíteme conectarte con un agente humano que pueda buscar eso") en lugar de intentos fallidos repetidos.
Problema 4: Cascada de latencia
Una herramienta tarda 8 segundos porque la API upstream está lenta. En una interfaz de chat, 8 segundos es molesto. En una llamada de voz, 8 segundos es una eternidad de silencio. El cliente dice "¿Hola? ¿Sigues ahí?" El agente, todavía esperando la API, no dice nada. El cliente cuelga.
El wrapper executeWithTracking que construimos mide la latencia, pero no la limita. No hay timeout. No hay respaldo. No hay forma de decirle al cliente "Estoy buscando eso para ti, un momento" mientras la herramienta se ejecuta.
Los sistemas en producción necesitan presupuestos de latencia: esta herramienta debe responder en menos de 3 segundos para voz, menos de 5 segundos para chat. Si no cumple el presupuesto, devuelve un resultado parcial o una respuesta de respaldo. Para agentes de voz especialmente, las respuestas de relleno ("Déjame verificar eso para ti...") necesitan dispararse mientras la herramienta aún se está ejecutando, lo que significa que la ejecución de la herramienta tiene que ser no-bloqueante. La relación entre latencia y satisfacción del cliente no es lineal, es un precipicio. La investigación muestra consistentemente que los tiempos de respuesta superiores a 5 segundos en interacciones de voz causan caídas dramáticas en las tasas de completación.
Problema 5: La brecha de monitoreo
Una herramienta devuelve datos obsoletos silenciosamente durante tres días. La API que llama está activa, devolviendo 200 OK, pero los datos detrás no se han actualizado desde una migración que rompió el trabajo de sincronización. Tu seguimiento de ejecución muestra 100% de tasa de éxito y latencia normal. Todo se ve verde.
Entonces un cliente tuitea: "Tu IA me dijo que un producto estaba en stock y manejé 45 minutos hasta la tienda. No ha estado en stock en una semana."
La tasa de éxito y la latencia no son suficientes. Necesitas validación de resultados: verificaciones de cordura sobre lo que devuelven las herramientas, no solo si devuelven algo. ¿La marca de tiempo lastUpdated es reciente? ¿El conteo de inventario cae en un rango razonable? ¿Los precios son no-negativos? Estas son verificaciones específicas del dominio que tu wrapper genérico de seguimiento no maneja, y son la diferencia entre un monitoreo que detecta caídas y un monitoreo que detecta respuestas incorrectas.
Aquí es donde la evaluación de agentes se encuentra con el monitoreo de herramientas. No puedes evaluar si un agente dio la respuesta correcta sin saber si sus herramientas le dieron los datos correctos.
Cómo se ve la producción en realidad
Has construido los fundamentos. Entiendes cómo funcionan los registros de herramientas, cómo los bucles de ejecución encadenan llamadas de herramientas en conversaciones, cómo necesitan gestionarse las credenciales, y qué sale mal a escala. Ahora veamos qué proporciona un sistema de producción por encima de esos fundamentos.
El SDK y CLI de Chanl envuelven los mismos conceptos que construiste: registro, ejecución, autenticación, monitoreo, en infraestructura que maneja los problemas de escalabilidad que acabamos de describir.
Gestión de herramientas vía CLI:
# List all tools in your workspace
chanl tools list
# Create a tool from a JSON definition
chanl tools create -f lookup-order.json
# Group tools into a toolset for your support agent
chanl toolsets create -n "Support Tools" --tools tool_abc,tool_def,tool_ghi
# Assign the toolset to an agent
chanl agents update agent_123 --toolsets ts_456
# Test a tool with sample input before going live
chanl tools execute tool_abc --input '{"orderId": "ORD-48291"}'Integración con SDK para acceso programático:
import { PlatformClient } from "@chanl-ai/platform-sdk";
const client = new PlatformClient({
apiKey: process.env.CHANL_API_KEY,
});
// List tools — filtered by type, status
const tools = await client.tools.list({
type: "http",
isEnabled: true,
});
// Create a tool from code
await client.tools.create({
name: "lookup_order",
description: "Retrieves order status by order ID",
type: "http",
inputSchema: {
type: "object",
properties: {
orderId: { type: "string", description: "Order ID" },
},
required: ["orderId"],
},
configuration: {
http: {
method: "GET",
url: "https://api.example.com/orders/{{orderId}}/status",
headers: {
Authorization: "Bearer {{ORDER_API_KEY}}",
},
},
},
});
// Group tools into a toolset
await client.toolsets.create({
name: "Support Tools",
description: "Tools for customer support agents",
toolIds: ["tool_abc", "tool_def", "tool_ghi"],
});Lo que obtienes y que no construiste:
Almacén centralizado de credenciales con rotación. Los secretos están encriptados en reposo y se resuelven en tiempo de ejecución. Cuando una clave rota, cada herramienta que usa esa credencial toma el cambio, sin re-despliegue, sin interrupción de conversaciones.
Agrupación por toolsets. Asigna diferentes paquetes de herramientas a diferentes agentes. Tu agente de soporte ve herramientas de soporte. Tu agente de ventas ve herramientas de ventas. El LLM nunca tiene que elegir entre 47 opciones. Cubrimos la arquitectura completa de toolsets en Herramientas para Agentes de IA: MCP, OpenAPI y Gestión de Herramientas.
Seguimiento de ejecución integrado con métricas de latencia. Cada llamada a herramienta se registra con tiempos, éxito/falla, entrada y salida. Agregado en dashboards con tendencias de tasa de éxito, percentiles de latencia y detección de anomalías.
Importación de OpenAPI. Apunta a una especificación OpenAPI y obtén herramientas auto-generadas: una herramienta por operación, con esquemas, descripciones y configuración de autenticación derivados de la especificación. Sin necesidad de escribir JSON manualmente para APIs existentes.
Integración MCP. Las herramientas se exponen a través del Model Context Protocol, para que cualquier cliente compatible con MCP (Claude, ChatGPT, VS Code, tu agente personalizado) pueda descubrirlas y llamarlas sin integración personalizada. Si eres nuevo en MCP, el tutorial MCP Explicado te guía paso a paso para construir un servidor MCP desde cero.
Habilitar/deshabilitar sin eliminar. Desactiva una herramienta y desaparece inmediatamente de las conversaciones del agente. Reactívala y se restaura con toda su configuración intacta. Rollback instantáneo cuando algo sale mal.
Memoria persistente entre conversaciones. Las herramientas pueden leer y escribir en la memoria del agente, para que tu agente de soporte recuerde que este cliente llamó por el mismo problema ayer y ya intentó la solución sugerida.
El enfoque aquí no es "tira lo que construiste." Es: ahora entiendes cada pieza. El registro, el bucle de ejecución, el patrón de credenciales, la capa de monitoreo. Cuando usas una plataforma que maneja esto a escala, sabes qué está haciendo internamente, y puedes detectar cuando lo está haciendo mal.
Cuándo construir vs. comprar
Constrúyelo tú mismo cuando estés aprendiendo cómo funcionan los sistemas de herramientas (lo cual acabas de hacer), cuando estés prototipando con menos de 5 herramientas, cuando tengas un solo agente, o cuando el agente sea solo interno y el costo de falla sea bajo.
Usa una plataforma cuando tu agente sea de cara al cliente, cuando estés gestionando más de 10 herramientas en múltiples agentes, cuando necesites gestión centralizada de autenticación y rotación de claves, cuando necesites monitoreo con alertas, o cuando necesites versionamiento para que las actualizaciones de herramientas no rompan sesiones a mitad de conversación.
La verdad honesta: la mayoría de los equipos comienzan construyendo. Es más rápido para un prototipo, y aprendes cosas sobre tu dominio que ninguna documentación de plataforma enseña. La transición ocurre cuando te das cuenta de que estás gastando más tiempo manteniendo infraestructura de herramientas que construyendo capacidades de agentes. Eso generalmente sucede alrededor de la marca de 10 herramientas y 3 agentes, cuando estás depurando por qué la API de inventario falló a las 2am en lugar de mejorar cómo tu agente maneja conversaciones sobre reembolsos.
Construir te enseña qué importa. La plataforma maneja lo que escala.
Hacia dónde ir desde aquí
Las herramientas son lo que separa a un chatbot de un agente. Sin ellas, una IA solo puede hablar sobre el mundo. Con ellas, puede actuar en él: buscar pedidos, verificar disponibilidad, programar callbacks, iniciar devoluciones. La infraestructura debajo (registro, ejecución, autenticación, monitoreo) determina si esas acciones son lo suficientemente confiables para enfrentar clientes reales.
Has construido cada capa desde cero. Entiendes la selección de herramientas, la inyección de credenciales, el seguimiento de ejecución y los cinco modos de falla que aparecen cuando escalas. Ya sea que sigas construyendo tu propio sistema o uses infraestructura de producción, ese entendimiento te hace un mejor constructor. Escribirás mejores descripciones de herramientas porque sabes cómo el LLM selecciona entre ellas. Diseñarás mejor manejo de errores porque has visto lo que la cascada de latencia le hace a una llamada de voz. Harás las preguntas correctas sobre autenticación y monitoreo porque has construido las versiones ingenuas y las viste fallar.
Si continúas en la serie Learning AI, RAG desde Cero cubre la capa de recuperación de conocimiento que complementa las herramientas, dando a los agentes acceso a tus documentos, no solo a tus APIs. Y Evaluaciones de Agentes de IA muestra cómo medir si tu agente equipado con herramientas realmente da respuestas correctas.
Construye agentes que realmente hacen cosas
Chanl maneja la gestión de herramientas, almacenamiento de credenciales, hosting MCP y monitoreo de ejecución, para que te enfoques en construir capacidades de agentes, no infraestructura.
Explorar Chanl Tools- Anthropic Tool Use Documentation — Claude API Reference
- OpenAI Function Calling Guide — GPT API Documentation
- Model Context Protocol Specification — MCP Documentation
- MCP Adoption Statistics — MCP Manager (2025-2026 data)
- A Year of MCP: 97M+ Monthly Downloads — Pento (2025 Review)
- Gartner: >40% of Agentic AI Projects Will Be Canceled by 2027
- OWASP Top 10 for Agentic Applications (2026)
- State of MCP Server Security 2025 — Astrix
- JSON Schema Specification — json-schema.org
- Latency and Customer Satisfaction in Voice AI — Sub-300ms Standard
Co-founder
Building the platform for AI agents at Chanl — tools, testing, and observability for customer experience.
Aprende IA Agéntica
Una lección por semana: técnicas prácticas para construir, probar y lanzar agentes IA. Desde ingeniería de prompts hasta monitoreo en producción. Aprende haciendo.



