Todos los recursos

Cuando un agente llama a la herramienta equivocada, el bug casi siempre está en la descripción de la herramienta, no en el system prompt. El modelo lee esas descripciones como si fueran documentación de API y enruta con ellas, así que escríbelas igual que documentación de API. Esta guía recorre toda la superficie: schemas, condiciones de disparo, el system prompt corto que amarra todo y un loop de eval para que un cambio de una sola palabra no te dañe el ruteo sin que te enteres.

Ingeniería de prompts para agentes que usan herramientas

En resumen

  • La descripción de la herramienta es donde viven las decisiones de ruteo: pesa más que el system prompt para decidir qué herramienta se llama.
  • Di cuándo llamar una herramienta, no solo qué hace. Los modelos Opus recientes recurren a las herramientas con cautela, así que una condición de disparo explícita sube de forma medible la tasa de llamada correcta.
  • Mantén el set chico y sin solapes. Diez herramientas afiladas le ganan a treinta difusas; el solape obliga al modelo a adivinar.
  • Los verbos específicos enrutan; los vagos traban al modelo. «fetch», «cancel», «refund» le ganan a «process» y «handle».
  • Marca los efectos secundarios (READ-ONLY vs WRITE) y valida cada input: un schema restringe la forma, nunca la corrección del negocio.

Un agente que elige la herramienta equivocada parece un problema del modelo. Casi nunca lo es. El modelo lee tus definiciones de herramientas igual que un ingeniero nuevo lee la documentación de una API: enruta por el nombre, la descripción y la lista de parámetros, en ese orden. Y cuando se equivoca, el arreglo está en esos tres lugares, no en un system prompt que grite más fuerte. Al final de esta guía vas a tener una superficie de herramientas que enruta limpio: descripciones prescriptivas, schemas ajustados, un system prompt corto que no estorba y un ciclo de eval que atrapa las regresiones de ruteo antes que tus usuarios.

01 · Requisitos previos y el modelo mental

Dos cosas claras antes de tocar una descripción.

Importante

Necesitas una API key de Anthropic en tu entorno como ANTHROPIC_API_KEY y el SDK instalado con npm install @anthropic-ai/sdk. Las herramientas son una función del único endpoint /v1/messages: tú las describes, Claude las pide, tu código las corre. Nunca mandes la key al navegador; pon un servidor delgado (un route handler de Next.js, una Edge Function de Supabase) entre el frontend y Anthropic y deja la key ahí.

El modelo mental: Claude decide, tu harness ejecuta. La definición de una herramienta son tres campos: un name, una description que Claude lee para decidir cuándo llamarla, y un JSON Schema para el input. Claude nunca ve tu código, tu base de datos ni tu frontera de seguridad. Ve esos tres campos y la conversación, y con eso elige una herramienta y arma los argumentos. Así que todo lo que quieras que acierte en el ruteo tiene que estar metido en lo que realmente puede leer.

Esto pesa más hoy que antes. Los modelos Opus recientes (4.7, 4.8) recurren a las herramientas con más cautela que los anteriores: razonan primero y llaman a una herramienta solo cuando están razonablemente seguros de que hace falta. Por lo general eso es una mejora, pero significa que una herramienta cuya descripción solo dice qué hace termina sin llamarse. La ganancia viene de decirle cuándo. Esos mismos modelos también siguen las instrucciones de forma más literal, así que la vieja maña de tapar una mala descripción con "CRITICAL: TIENES QUE USAR ESTA HERRAMIENTA" ahora dispara de más en lugar de ayudar. Arregla la descripción, no el volumen.

02 · Escribe la descripción como documentación de API

Una descripción de herramienta es documentación para un lector que va a actuar sobre ella de inmediato y al pie de la letra. Dale a cada herramienta:

  • Una línea de qué hace y cuándo usarla y, donde importe, cuándo no usarla. La condición de disparo es la frase de mayor peso de toda la definición.
  • Una marca de efecto secundario. Di READ-ONLY o WRITE de forma explícita. El modelo trata muy distinto una consulta y una mutación en cuanto le dices cuál es cuál, y te conviene que sea cauteloso con la destructiva.
  • Una razón para existir al lado de sus vecinas. Si dos herramientas pudieran atender la misma petición, la descripción tiene que trazar el límite; si no, el modelo va a adivinar.
import Anthropic from "@anthropic-ai/sdk"

const tools: Anthropic.Tool[] = [
  {
    name: "search_orders",
    description:
      "Busca pedidos por email del cliente. READ-ONLY. " +
      "Llama a esta herramienta antes de emitir un reembolso para confirmar que el pedido existe y es reembolsable. " +
      "No la uses para crear ni modificar pedidos: para eso usa create_order o cancel_order.",
    input_schema: {
      type: "object",
      properties: {
        email: { type: "string", description: "Email del cliente, ej. ana@example.com" },
        status: { type: "string", enum: ["paid", "shipped", "refunded"] },
      },
      required: ["email"],
    },
  },
]

Fíjate en lo que el schema hace y en lo que no hace. Cada propiedad tiene un tipo y un valor de ejemplo concreto, no solo un nombre: "ej. ana@example.com" le comunica la forma al modelo mucho mejor que la palabra "email" sola. El enum fija status a tres valores válidos para que el modelo no invente un cuarto. Mantén el schema plano: los campos muy anidados o de nombre ambiguo suben la tasa de error, y un objeto plano es más fácil de llenar bien en una sola pasada.

Consejo

La condición de disparo va en la propia description de la herramienta, no solo en el system prompt. En los Opus recientes, un "Llama a esto cuando…" prescriptivo dentro de la descripción da una mejora medible en la tasa de llamada correcta frente a una descripción que solo dice qué hace. La descripción viaja con la herramienta; las reglas de ruteo en el system prompt se desincronizan apenas agregas una herramienta y se te olvida actualizarlas.

03 · Los verbos enrutan; mantén el set chico

Dos cambios baratos arreglan la mayoría de los problemas de ruteo.

Usa verbos específicos

Los verbos vagos hacen dudar al modelo o reparten una petición entre las herramientas equivocadas. "Procesar el pedido", "gestionar la solicitud": ¿procesar cómo?, ¿gestionar hacia qué? Los verbos específicos cargan la señal de ruteo: fetch, create, cancel, refund, search. Ponle también el verbo al nombre de la herramienta (cancel_order, no order_manager) y la decisión de cuándo llamarla se afila notablemente, porque el nombre por sí solo ya recorta a las candidatas.

Mantén el set chico y sin solapes

Diez herramientas bien nombradas le ganan a treinta que se solapan. El solape es el asesino silencioso: cuando existen update_order y modify_order a la vez, el modelo tiene que adivinar a cuál te referías, y adivinar es justo donde viven los errores de ruteo. Antes de agregar una herramienta, pregúntate si una que ya tienes cubre el caso con un schema más amplio. Para el modelo es más fácil razonar sobre un puñado de herramientas afiladas y distintas que sobre un menú enorme de casi-duplicados.

Si de verdad tienes una librería grande donde solo unas pocas herramientas aplican por petición, no metas todos los schemas al contexto: usa la capacidad de tool search, que deja que el modelo descubra y cargue solo las definiciones relevantes en vez de enrutar entre cientos a la vez. Para el caso común de una docena o dos de herramientas, basta con mantener el set ajustado.

04 · El system prompt: objetivo y límites, y luego no estorbes

Con el ruteo a cargo de las definiciones de herramientas, el system prompt tiene una tarea más chica de lo que la gente cree: di el objetivo, di los límites y para. No vuelvas a documentar cada herramienta ahí: vas a escribir una segunda copia desincronizada de las descripciones y las dos van a terminar contradiciéndose. Cuando no coinciden, creaste justo la ambigüedad que querías eliminar.

Dos notas específicas del modelo que conviene atender en Opus 4.7/4.8:

  • No grites. "CRITICAL: SIEMPRE usa la herramienta de búsqueda" dispara de más en estos modelos porque siguen las instrucciones al pie de la letra. Escribe "Usa la herramienta de búsqueda cuando la respuesta dependa de datos actuales del pedido": una condición, no una orden.
  • Da autonomía en las llamadas chicas. Estos modelos son más deliberados y se detienen a preguntar por decisiones menores (cuál de dos herramientas equivalentes, un valor por defecto). Si esa manía de preguntar molesta a tus usuarios, dilo explícito: que elija una opción razonable en las decisiones menores y pregunte primero en lo destructivo.
const system = [
  "Eres un agente de soporte de una tienda en línea.",
  "Objetivo: resolver el problema del pedido del cliente con las herramientas dadas.",
  "Usa search_orders para buscar un pedido antes de cualquier reembolso o cancelación.",
  "En decisiones menores (qué campo de búsqueda, un filtro de status por defecto), elige una opción razonable y déjala anotada.",
  "En acciones destructivas (reembolso, cancelación), confirma primero con el usuario.",
  "No le pidas al usuario datos que puedas obtener con una herramienta.",
].join("\n")

Ese es el contrato completo: un objetivo, la única regla de ruteo que las descripciones no pueden expresar solas (buscar-antes-de-mutar es una secuencia, y eso vive mejor aquí) y el límite de autonomía. Todo lo demás está en las herramientas.

05 · Ejemplo trabajado y errores comunes

Sigamos un turno. Un usuario escribe "reembólsame mi último pedido, ana@example.com". Claude lee el objetivo, ve la regla de buscar-antes-de-reembolsar y, porque search_orders dice READ-ONLY y "llama antes de emitir un reembolso", la llama primero con { email: "ana@example.com" }. Tu harness la corre, devuelve el pedido como tool_result y, en el siguiente turno, Claude ya tiene lo que necesita para confirmar y llamar a la herramienta de reembolso. El ruteo lo decidieron por completo la descripción y la única regla de secuencia del system prompt; no forzaste nada.

Los errores que de verdad duelen:

  • Un verbo vago en el nombre o la descripción. "manage_order" o "procesar la solicitud" dejan al modelo adivinando la intención. Renómbralo a la acción específica y la tasa de llamada correcta sube.
  • Herramientas que se solapan. Dos herramientas que podrían atender la misma petición. Fusiónalas o afila las descripciones hasta que el límite sea inequívoco; no dejes que el modelo lo eche a la suerte.
  • Re-documentar las herramientas en el system prompt. Las descripciones y el prompt se desincronizan y luego se contradicen. Deja el detalle de ruteo en las descripciones; deja las secuencias y los límites en el prompt.
  • Confiar en el input. Un schema restringe la forma de los argumentos, no su corrección de negocio. Valida cada input en tu handler antes de actuar: trata lo que manda Claude como datos sin tipar que tú revisas, no como verdad revelada.
  • Gritarles a los modelos recientes. El lenguaje "CRITICAL: TIENES QUE" dispara de más en Opus 4.7/4.8. Bájalo a una condición de disparo normal.

Atención

No dejes que un juez LLM califique el ruteo de herramientas con el mismo modelo que produjo la respuesta: es demasiado indulgente con su propio trabajo. Usa otro modelo o una verificación programática estricta (¿llamó a la herramienta esperada, en el orden esperado, con argumentos válidos?) y tendrás una señal honesta.

Móntale un eval chiquito a todo el flujo. Define de diez a veinte peticiones representativas con la herramienta que esperas que llame cada una, córrelas en cada cambio de prompt o de descripción e imprime una tasa de aciertos. Una caída de 90% a 74% te avisa al instante que tu "ajuste pequeño" no era tan pequeño.

const cases = [
  { input: "reembólsame mi último pedido, ana@example.com", expect: "search_orders" },
  { input: "¿dónde está mi paquete?", expect: "search_orders" },
  { input: "cancela el pedido 1182", expect: "cancel_order" },
]

// Por cada caso: corre el turno, lee el primer bloque tool_use, compara con expect.
// Pasa = se llamó la herramienta esperada primero con args válidos. Imprime passed / cases.length.

Acierta con las descripciones, mantén el set chico y afilado, deja que el system prompt diga solo lo que las herramientas no pueden y pon una compuerta de tasa de aciertos delante de cada cambio. Así el ruteo de herramientas deja de sentirse como un misterio del modelo y pasa a ser algo que puedes depurar, medir y mejorar a propósito.

Puntos clave

  • El ruteo vive en la descripción de la herramienta, no en el system prompt. Arregla ahí primero el bug de la herramienta equivocada.
  • Di cuándo llamar a cada herramienta, en su propia descripción y con un verbo específico: es la palanca más grande sobre la tasa de llamada correcta.
  • Mantén el set chico y sin solapes, y valida cada input; el schema restringe la forma, nunca la corrección de negocio.
  • Deja que el system prompt diga solo lo que las herramientas no pueden (objetivo, secuencias entre herramientas, límites de autonomía) y para.
  • Ponle una compuerta de eval con tasa de aciertos a cada cambio de prompt o descripción, calificada de forma programática o por otro modelo.

Preguntas frecuentes

¿Las reglas de ruteo van en el system prompt o en las descripciones de las herramientas?

El ruteo de cada herramienta, o sea cuándo llamar a esa herramienta en concreto, va en su description, porque viaja con la herramienta y no se desincroniza. Las secuencias entre herramientas (haz A antes de B) y los límites generales van en el system prompt. El error es re-documentar cada herramienta en el prompt; terminas con dos copias que tarde o temprano se contradicen.

Mi agente llama de menos a una herramienta que claramente debería usar. ¿Cómo lo arreglo?

Los Opus recientes recurren a las herramientas con cautela, así que una descripción que solo dice qué hace termina sin llamarse. Agrega a la propia descripción una condición de disparo explícita: "Llama a esto cuando la respuesta dependa de datos actuales del pedido". No recurras al lenguaje "CRITICAL: TIENES QUE"; en estos modelos dispara de más y sigue al pie de la letra, lo que causa el problema opuesto.

¿Cuántas herramientas son demasiadas?

No hay un tope fijo, pero el solape importa más que la cantidad. Diez herramientas distintas y de nombre afilado enrutan mejor que treinta que se difuminan entre sí. Si dos herramientas pudieran atender la misma petición, eso ya es un riesgo de ruteo sin importar el total. Para librerías de verdad grandes donde solo unas pocas aplican por petición, usa la capacidad de tool search para que el modelo cargue solo los schemas relevantes en vez de enrutar entre todos.

¿Sigo necesitando validar los inputs si uso un JSON schema estricto?

Sí. Un schema restringe la forma (tipos, enums, campos requeridos) pero nunca la corrección de negocio. El schema no tiene forma de saber que el pedido 1182 es de otro cliente, o que esta cuenta no tiene permiso para emitir reembolsos. Trata el input que manda Claude como datos sin tipar que validas en tu handler antes de actuar, sobre todo en cualquier escritura o acción destructiva.

¿Cómo mido si un cambio de prompt mejoró o empeoró el ruteo?

Mantén un set de eval chico: de diez a veinte peticiones representativas, cada una etiquetada con la herramienta que esperas que llame primero. Córrelo en cada cambio de una descripción o del system prompt e imprime una tasa de aciertos. Califica de forma programática (¿se llamó la herramienta esperada primero, con args válidos?) en vez de con un juez LLM, y nunca juzgues con el mismo modelo que produjo la respuesta: es demasiado indulgente con su propio trabajo.

¿Debería usar tool_choice para forzar la herramienta correcta?

Deja tool_choice en su valor por defecto ("auto") para que el modelo también pueda responder sin más cuando no hace falta ninguna herramienta. Forzar una herramienta específica con { type: "tool", name } es para casos puntuales como garantizar una extracción estructurada, no un sustituto de una descripción clara. Si estás forzando una herramienta para arreglar el ruteo, el bug real está en la descripción, y forzarla solo esconde el problema en los casos en que el modelo no debería haber llamado a la herramienta.

¿Prefieres que lo hagamos por ti?

Esto mismo lo construimos para negocios como el tuyo. La primera conversación es gratis y sin compromiso.

Escríbenos por WhatsApp

Escríbenos por WhatsApp

Escanéalo con tu teléfono para escribirnos por WhatsApp.

Escanéalo con tu teléfono para escribirnos por WhatsApp.

¿Estás desde el teléfono y no puedes escanear? Escríbenos a info@ilustrari.com

Primera conversación gratis. Te responde el fundador.

Recursos relacionados

GuíaTypeScript

Hacer streaming de llamadas a herramientas de la API de Claude dentro de un bucle

Hacer streaming con herramientas es un bucle agéntico, no una sola llamada: vas emitiendo tokens para que la respuesta se sienta ágil, pausas cuando Claude pide una herramienta, la ejecutas, le devuelves el resultado y sigues con el streaming hasta que el turno se cierra. Esta guía recorre el bucle completo en TypeScript con eventos reales del SDK, las reglas de forma del mensaje que la API exige y los fallos que más duelen en producción.

8 may 202611 min de lectura
GuíaTypeScript

Arma evals para tus agentes antes de confiar en ellos

Cada cambio de prompt en un agente que no puedes medir es una apuesta a ciegas. Una eval no es más que un test para sistemas no deterministas: un dataset pequeño y honesto, graders que corren en cada cambio y un pass rate que te dice al instante si tu "ajustito" rompió algo que ya funcionaba.

28 abr 202612 min de lectura
GuíaMCP

Diseñar un servidor MCP que los agentes de verdad sepan usar bien

El Model Context Protocol es lo fácil; el diseño es lo que separa un servidor que el agente usa con fluidez de uno con el que pierde el tiempo dando palos de ciego. Esta guía te lleva paso a paso: modelar las herramientas pensando en tareas y no en tablas, darle forma a lo que devuelves para que no te tape la ventana de contexto, escribir errores que le enseñen al modelo a recuperarse y blindar las rutas de escritura peligrosas con scopes e idempotencia.

25 abr 202612 min de lectura