Conceptos básicos de uso de herramientas
10 ejemplos para empezar con el uso de herramientas y la llamada a funciones: 7 básicos y 3 intermedios.
Prerrequisitos
- Instala el SDK:
pip install anthropic. - Establece
ANTHROPIC_API_KEYen tu entorno; el cliente lo lee automáticamente. from anthropic import Anthropic; client = Anthropic()es toda la configuración que estos ejemplos necesitan.
Ejemplos básicos
1. Definición de un esquema de herramienta
Describe una herramienta con un nombre, una descripción y un esquema JSON para su entrada.
weather_tool = {
"name": "get_weather",
"description": "Obtiene el clima actual de una ubicación. Llama a esta herramienta cuando el usuario pregunte sobre las condiciones actuales.",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "Ciudad y estado, por ejemplo, San Francisco, CA",
}
},
"required": ["location"],
},
}namees el identificador que Claude usa para solicitar la herramienta y que tú comparas en tu propio código.descriptiones la señal principal que Claude usa para decidir cuándo llamar a la herramienta; escríbela como documentación para un compañero de equipo, no como una etiqueta.input_schemaes el esquema JSON estándar; los valoresrequiredy ladescriptionpor campo mejoran la fiabilidad con la que Claude rellena los argumentos.- La definición de una herramienta es un diccionario Python simple; no se requiere una clase SDK especial para declararla.
Relacionado: Definición de esquemas de herramientas con nombre, descripción y esquema de entrada - la referencia completa del esquema
2. Envío de un mensaje con herramientas
Pasa tu lista de herramientas a messages.create junto con la conversación.
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[weather_tool],
messages=[
{"role": "user", "content": "¿Qué tiempo hace en San Francisco, CA?"}
],
)- El parámetro
toolsacepta una lista, por lo que puedes ofrecer varias herramientas a Claude en la misma llamada. - Claude solo usa una herramienta cuando la conversación lo requiere; pasar
toolsno fuerza una llamada. max_tokensalrededor de 1024 es suficiente para un turno de llamada a herramienta; auméntalo si la respuesta final será larga.model="claude-sonnet-5"es el modelo predeterminado para el uso general de herramientas en esta pila.
3. Detección de una razón de parada tool_use
Comprueba stop_reason antes de asumir que tienes una respuesta de texto plano.
if response.stop_reason == "tool_use":
print("Claude quiere llamar a una herramienta")
else:
print(response.content[0].text)stop_reason == "tool_use"es cómo el SDK te dice que Claude se detuvo para solicitar una llamada a herramienta en lugar de terminar su respuesta.- Siempre bifurca según
stop_reasonen lugar de adivinar a partir de la forma del contenido; es la señal documentada para este estado. - Si Claude no necesitó una herramienta,
response.contentcontiene bloques de texto ordinarios que puedes leer directamente. - Omitir esta comprobación es la causa más común de fallos cuando una llamada a herramienta es opcional.
Relacionado: Cómo decide Claude cuándo llamar a una herramienta - por qué algunos turnos omiten el uso de herramientas por completo
4. Extracción de la entrada de la herramienta
Encuentra el bloque de contenido tool_use y lee sus argumentos generados.
tool_use_block = next(
block for block in response.content if block.type == "tool_use"
)
tool_name = tool_use_block.name
tool_input = tool_use_block.input
tool_id = tool_use_block.id
print(tool_name, tool_input, tool_id)response.contentes una lista de bloques de contenido; un turnotool_usepuede mezclar un bloquetextcon uno o más bloquestool_use.block.inputya es un diccionario Python analizado que coincide con tuinput_schema; no se necesita decodificación JSON.block.ides el valor que debes devolver más tarde en eltool_resultcorrespondiente, así que captúralo ahora.block.namete dice qué herramienta ejecutar cuando tienes más de una definida.
5. Ejecución de tu función de herramienta
Ejecuta tu propio código con los argumentos que Claude generó.
def get_weather(location: str) -> str:
# Reemplaza esto con una llamada real a una API meteorológica.
return f"72F y soleado en {location}"
if tool_name == "get_weather":
result = get_weather(**tool_input)- Claude nunca ejecuta código por sí mismo; solo produce el nombre y la entrada de la herramienta; ejecutar la herramienta es enteramente tu responsabilidad.
- Desempaquetar
tool_inputcon**funciona limpiamente cuando los nombres de los parámetros de tu función coinciden con las claves depropertiesdel esquema. - Trata
tool_inputcomo cualquier otra entrada externa; valídala antes de usarla en rutas de archivos, consultas o comandos de shell. - Mantén el valor de retorno de la función como una cadena simple o una estructura serializable en JSON para que sea fácil de devolver como
tool_result.
6. Devolución de un bloque tool_result
Envía la salida de la herramienta de vuelta a Claude como un nuevo mensaje de usuario.
messages = [
{"role": "user", "content": "¿Qué tiempo hace en San Francisco, CA?"},
{"role": "assistant", "content": response.content},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_id,
"content": result,
}
],
},
]
final_response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[weather_tool],
messages=messages,
)
print(final_response.content[0].text)- El turno del asistente que añades debe ser
response.contentverbatim; preserva el bloquetool_useexacto que Claude generó, incluido suid. tool_use_iddebe coincidir con eliddel bloquetool_useal que responde, para que Claude pueda emparejar la solicitud con su resultado.- El bloque
tool_resultsiempre va en un mensaje con el roluser, aunque en realidad sea una respuesta de máquina, no algo que el humano escribió. - La segunda llamada a
messages.createes una nueva solicitud con todo el historial adjunto; Claude solo ve los turnos anteriores que incluyes explícitamente.
Relacionado: Manejo de solicitudes de uso de herramientas y devolución de bloques
tool_result- la referencia completa del ciclo de ida y vuelta
7. Manejo de errores de ejecución de herramientas
Informa a Claude de que una llamada a herramienta falló en lugar de omitirla silenciosamente.
try:
result = get_weather(**tool_input)
tool_result_content = result
is_error = False
except Exception as exc:
tool_result_content = f"La ejecución de la herramienta falló: {exc}"
is_error = True
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_id,
"content": tool_result_content,
"is_error": is_error,
}- Establece
"is_error": trueen el bloquetool_resultcuando tu función genere una excepción o falle la llamada a la API subyacente. - Una cadena de error informativa permite a Claude decidir qué hacer a continuación: reintentar, pedir aclaraciones al usuario o explicar el fallo.
- Nunca omitas el
tool_resultpara un bloquetool_use, ni siquiera en caso de fallo; la conversación está mal formada si una llamada a herramienta queda sin respuesta. - Envolver la ejecución de la herramienta en
try/exceptevita que una sola llamada a API fallida bloquee todo tu manejador de solicitudes.
Ejemplos intermedios
8. Ciclo completo de ida y vuelta: de la pregunta del usuario a la respuesta final
Encadena todos los pasos anteriores en un bucle funcional.
from anthropic import Anthropic
client = Anthropic()
weather_tool = {
"name": "get_weather",
"description": "Obtiene el clima actual de una ubicación. Llama a esta herramienta cuando el usuario pregunte sobre las condiciones actuales.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "Ciudad y estado, por ejemplo, San Francisco, CA"}
},
"required": ["location"],
},
}
def get_weather(location: str) -> str:
return f"72F y soleado en {location}"
messages = [{"role": "user", "content": "¿Debería llevar paraguas en Austin, TX hoy?"}]
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[weather_tool],
messages=messages,
)
if response.stop_reason == "tool_use":
tool_use_block = next(b for b in response.content if b.type == "tool_use")
result = get_weather(**tool_use_block.input)
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": tool_use_block.id, "content": result}
],
})
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[weather_tool],
messages=messages,
)
print(response.content[0].text)- Este es el mismo ciclo de cinco pasos: crear, detectar
tool_use, ejecutar, añadirtool_result, crear de nuevo, escrito como un solo script. - Reutilizar la lista
messagescon.append()mantiene intacto todo el historial de la conversación para la segunda llamada. - La segunda llamada a
messages.createtodavía pasatools=[weather_tool], ya que Claude puede necesitar legítimamente llamar a la herramienta de nuevo. - En producción, esta lógica suele envolverse en un bucle
while response.stop_reason == "tool_use":para manejar cualquier número de llamadas a herramientas.
Relacionado: Construcción de un bucle de uso de herramientas de varios turnos - generalización de esto en un bucle reutilizable
9. Manejo de múltiples bloques tool_use en un solo turno
Itera sobre cada bloque tool_use, ya que Claude puede solicitar varias herramientas en un solo turno.
tool_result_blocks = []
for block in response.content:
if block.type != "tool_use":
continue
if block.name == "get_weather":
output = get_weather(**block.input)
else:
output = f"Herramienta desconocida: {block.name}"
tool_result_blocks.append(
{"type": "tool_result", "tool_use_id": block.id, "content": output}
)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_result_blocks})- Un solo turno del asistente puede contener más de un bloque
tool_use; filtraresponse.contentportype == "tool_use"en lugar de asumir exactamente uno. - Cada bloque
tool_usenecesita su propio bloquetool_resultcorrespondiente en el mensaje de usuario de seguimiento, cada uno con su propiotool_use_id. - Todos los bloques
tool_resultde un turno van juntos en la listacontentde un único mensaje de usuario, no como mensajes separados. - La bifurcación por
block.namees cómo se dirige a la función Python correcta cuando se definen varias herramientas.
Relacionado: Ejecución de llamadas a herramientas en paralelo en un solo turno - más sobre el procesamiento por lotes de resultados de herramientas
10. Elección entre herramientas con tool_choice
Usa tool_choice para forzar, restringir o dejar abierta la elección de la herramienta que Claude selecciona.
calculate_tool = {
"name": "calculate",
"description": "Evalúa una expresión aritmética básica. Llama a esta herramienta para cualquier pregunta de matemáticas.",
"input_schema": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "por ejemplo, 12 * (4 + 1)"}
},
"required": ["expression"],
},
}
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[weather_tool, calculate_tool],
tool_choice={"type": "tool", "name": "calculate"},
messages=[{"role": "user", "content": "¿Cuánto es 12 por 5?"}],
)tool_choice={"type": "tool", "name": "calculate"}fuerza a Claude a llamar a esa herramienta específica en lugar de elegir por sí mismo.- Dejar
tool_choicesin establecer es equivalente a{"type": "auto"}; Claude decide si usar una herramienta y cuál, basándose en las descripciones. {"type": "any"}requiere alguna llamada a herramienta pero permite a Claude elegir cuál;{"type": "none"}deshabilita las llamadas a herramientas para ese turno.- Forzar una herramienta es útil para probar el esquema de una sola herramienta de forma aislada, sin depender de la propia decisión de enrutamiento de Claude.
Relacionado: Referencia de opciones de elección de herramientas - todos los modos de
tool_choiceen detalle
Versiones de la pila: Escrito contra la línea de modelos de Claude actual a partir de ~junio de 2026: Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (el predeterminado) y Claude Haiku 4.5, y el SDK oficial de Python
anthropic(última versión 0.x). Los nombres de los modelos, las versiones del SDK y los precios cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.