Quieres que un asistente de compras consulte el estado de un pedido en SAP y, si hace falta, prepare una reclamación al proveedor. Claude no puede entrar en tu sistema. Lo que sí puede es pedirte que ejecutes una función con unos argumentos concretos. Tu código decide si la ejecuta, con qué permisos y qué le devuelve.
Ese contrato es el tool use (o function calling), y es la pieza sobre la que se construye todo lo demás: agentes, MCP, Claude Code. En el examen aparece en el dominio 8 (herramientas y MCP, un 10,6 %), pero también en preguntas de agentes, seguridad y coste.
Quién ejecuta qué
La documentación clasifica las herramientas por dónde se ejecuta el código, y esa es la distinción que más se pregunta:
De cliente
Las ejecuta tu aplicación
- Las que defines tú, con tu `input_schema`: tu lógica de negocio, tus APIs internas
- Las de esquema de Anthropic: `memory`, `bash`, `text_editor`, computer use y browser use. El esquema está entrenado en el modelo, pero las ejecutas tú
- Claude responde con `stop_reason: tool_use` y tú devuelves un `tool_result`
- Tú controlas credenciales, permisos y aprobaciones
De servidor
Las ejecuta Anthropic
- `web_search`, `web_fetch`, `code_execution`, `tool_search` y el conector MCP
- Las activas en `tools` y el bucle corre dentro de la API: no construyes `tool_result`
- La respuesta trae bloques `server_tool_use` con lo que se ejecutó
- Si el bucle interno llega a su límite, vuelve con `stop_reason: pause_turn` y reenvías para continuar
Algunas herramientas de servidor cobran aparte: la búsqueda web cuesta 10 $ por cada 1.000 búsquedas, más los tokens.
Una regla práctica de la propia documentación: si estás escribiendo una expresión regular para sacar una decisión de un texto libre, esa decisión debería haber sido una llamada a herramienta.
El ciclo tool_use y tool_result
Recorre una vuelta completa con una herramienta de cliente:
La petición lleva el array tools con nombre, descripción e input_schema de cada herramienta, y la pregunta del usuario.
En código, el bucle manual cabe en pocas líneas:
import anthropic
client = anthropic.Anthropic()
tools = [{
"name": "sap_consultar_pedido_compra",
"description": (
"Devuelve el estado de un pedido de compra de SAP S/4HANA: proveedor, posiciones, "
"cantidades recibidas y fecha de entrega prevista. Úsala cuando el usuario pregunte por "
"un pedido concreto y dé su número. No sirve para buscar pedidos por proveedor ni por fecha. "
"Solo lee datos: no modifica nada."
),
"input_schema": {
"type": "object",
"properties": {
"numero_pedido": {"type": "string", "description": "Número de pedido de 10 dígitos, por ejemplo 4500012345"}
},
"required": ["numero_pedido"],
"additionalProperties": False,
},
"strict": True,
}]
messages = [{"role": "user", "content": "¿Ha llegado ya el material del pedido 4500012345?"}]
while True:
response = client.messages.create(
model="claude-opus-5-5", max_tokens=4096, tools=tools, messages=messages
)
messages.append({"role": "assistant", "content": response.content}) # tal cual, con thinking
if response.stop_reason != "tool_use":
break
resultados = []
for block in response.content:
if block.type != "tool_use":
continue
try:
salida = ejecutar_herramienta(block.name, block.input) # tu código, tus permisos
resultados.append({"type": "tool_result", "tool_use_id": block.id, "content": salida})
except PedidoNoEncontrado:
resultados.append({
"type": "tool_result", "tool_use_id": block.id, "is_error": True,
"content": "No existe ese pedido. Pide al usuario que confirme los 10 dígitos.",
})
messages.append({"role": "user", "content": resultados})
print("".join(b.text for b in response.content if b.type == "text"))
Tres reglas de formato que dan un 400 si las incumples: el tool_result va justo después del tool_use que responde, sin mensajes en medio; dentro del mensaje user, los tool_result van primero y cualquier texto después; y cada tool_use necesita su resultado.
Si no quieres escribir el bucle, los SDK de Python y TypeScript traen el Tool Runner (en beta): decoras una función con @beta_tool, el SDK deduce el esquema de los tipos y el docstring, y client.beta.messages.tool_runner(...) ejecuta las herramientas y reenvía los resultados por ti.
Herramientas que Claude elige bien
La documentación es tajante: la descripción es, con diferencia, el factor que más influye en el rendimiento de una herramienta. Compara:
name: get_data
description: Gets data from SAP.
input_schema: { id: string }Nombre genérico, una frase y un parámetro sin explicar. Claude no sabe qué datos devuelve, cuándo usarla ni qué formato tiene el id: adivinará.
Las buenas prácticas oficiales, resumidas:
- Descripciones largas y concretas: al menos tres o cuatro frases. Qué hace, cuándo usarla y cuándo no, qué significa cada parámetro, qué no devuelve.
input_examplespara herramientas con entradas complejas o formatos delicados. Cada ejemplo debe cumplir el esquema, o la API devuelve 400.- Menos herramientas y más capaces: mejor una herramienta con un parámetro
actionque tres casi iguales (create_pr,review_pr,merge_pr). Menos ambigüedad al elegir. - Espacios de nombres con prefijo de servicio (
sap_…,slack_…) cuando crece el catálogo. - Respuestas con señal: identificadores estables y solo los campos útiles. Un volcado de 300 columnas gasta contexto y confunde.
strict: truepara que los argumentos cumplan siempre el esquema. NecesitaadditionalProperties: falseen cada objeto.
Sobre tool_choice: tiene cuatro modos (auto, any, tool y none). Pero Opus 5.5, Sonnet 5.5 y Fable 5.1 no admiten forzar una herramienta: any y tool devuelven 400. La alternativa documentada es auto con strict: true y decir en el prompt cuándo usarla, o structured outputs si lo que quieres es una respuesta con forma fija. Para evitar llamadas en paralelo existe disable_parallel_tool_use: true.
Errores, aprobaciones y contenido no fiable
Errores. Si tu herramienta falla, devuelve el error en el tool_result con "is_error": true y un mensaje que sirva para recuperarse: no «failed», sino qué pasó y qué probar («límite de tasa, reintenta en 60 segundos»). Ante una llamada inválida, Claude suele corregir y reintentar un par de veces antes de rendirse. Con las herramientas de servidor no gestionas is_error: la API lo resuelve.
Aprobaciones. El examen habla de «patrones de aprobación». El más útil: separa las herramientas de lectura de las de escritura, y para las que tienen efectos irreversibles (crear un pedido, enviar un correo, borrar) pon una confirmación humana en tu código antes de ejecutar. Claude propone; tu aplicación enseña la propuesta y ejecuta solo si alguien la aprueba. Y el ejecutor usa credenciales con el mínimo privilegio necesario, no las de un administrador.
Contenido no fiable. Los resultados de herramientas traen texto que no controlas: páginas web, correos, campos libres de un ERP. La documentación recomienda mantenerlo dentro de los bloques tool_result y no copiarlo al system ni a texto del usuario, porque puede contener instrucciones inyectadas. Y, sobre todo, que una instrucción inyectada no pueda disparar una acción sensible sin pasar por tu control.
Un agente lee correos de proveedores y tiene dos herramientas: leer_correo y crear_pedido_compra. ¿Qué diseño reduce más el riesgo de que un correo malicioso provoque un pedido?
Herramienta integrada, propia, Skill o MCP
El subdominio de «agentic customization» (4,1 %) pregunta cuál elegir en cada caso. Esta tabla resume el criterio:
| Necesitas | Mejor opción | Por qué |
|---|---|---|
| Buscar en la web, ejecutar código en un sandbox | Herramienta integrada de servidor | Ya existe, la ejecuta Anthropic, sin mantenimiento |
| Llamar a tu lógica de negocio desde una aplicación | Herramienta propia (tool use) | Control total, cero infraestructura extra |
| La misma integración en varias aplicaciones o clientes | Servidor MCP | Se escribe una vez, se mantiene aparte y cualquier cliente MCP lo usa |
| Enseñar un procedimiento, una convención o un formato | Skill | Conocimiento e instrucciones que se cargan solo cuando hacen falta; no es una conexión |
Fíjate en la última fila: una Skill no da acceso a ningún sistema, da saber hacer. Y una trampa habitual es pensar que una herramienta integrada puede llegar a tu API interna: no puede. Para eso está la herramienta propia o el servidor MCP, que vemos en la siguiente lección.
Un detalle de coste: las herramientas no salen gratis. Sus definiciones cuentan como tokens de entrada en cada petición, y activar tools añade además un system prompt interno (en Opus 5.5, 286 tokens). Con catálogos grandes, la herramienta tool search carga las definiciones bajo demanda.
Para el examen
Dominio · D8 Tools and MCPs (Tool Implementation y Agentic Customization) · D7 Security
Lo que tienes que dominar
- Herramientas de cliente (tú ejecutas y devuelves
tool_result) frente a las de servidor (ejecuta Anthropic; ojo conpause_turn). - Bucle: mientras
stop_reasonseatool_use, ejecutar y devolver resultados;tool_resultprimero y todos los paralelos en un mismo mensaje. - La descripción es lo que más pesa: qué hace, cuándo sí y cuándo no, parámetros y lo que devuelve.
strict: truegarantiza argumentos válidos; en Opus 5.5, Sonnet 5.5 y Fable 5.1 no haytool_choiceforzado.- Errores con
is_errory mensajes accionables; acciones irreversibles con aprobación humana y mínimo privilegio.
Donde se suele fallar
- Creer que una herramienta integrada llega a una API interna.
- Confundir Skill (conocimiento) con MCP (conexión reutilizable).
- Poner texto antes de los
tool_resulto separar resultados paralelos en varios mensajes. - Confiar en el system prompt como única defensa ante contenido inyectado en resultados de herramientas.
Checklist para el examen
0 de 7 dominadosMarca lo que ya sabrías responder en el examen.
Ponte a prueba
Tipo test
6 preguntas sobre esta lección. Responde una a una; verás las soluciones al terminar.
Siguiente parada
Próxima lección: MCP para desarrolladores. Qué es un servidor MCP, sus primitivas, cómo construir uno en Python y conectarlo a Claude Code, al Agent SDK y a la API, sin filtrar credenciales.