Construir un sistema de conversación con herramientas requiere implementar un bucle que siga llamando a Claude hasta que deje de solicitar el uso de herramientas. Cuando Claude ya no pide herramientas, eso indica que tiene una respuesta final lista para el usuario.
Detectando solicitudes de herramientas
La clave para saber si Claude quiere usar una herramienta está en el campo stop_reason del mensaje de respuesta. Cuando Claude decide que necesita llamar a una herramienta, este campo se establece en "tool_use". Esto nos da una forma clara de verificar si necesitamos continuar el bucle de conversación:
if response.stop_reason != "tool_use":
break # Claude is done, no more tools neededEl bucle de conversación
La función principal de conversación sigue un patrón simple:
def run_conversation(messages):
while True:
response = chat(messages, tools=[get_current_datetime_schema])
add_assistant_message(messages, response)
print(text_from_message(response))
if response.stop_reason != "tool_use":
break
tool_results = run_tools(response)
add_user_message(messages, tool_results)
return messagesEste bucle continúa hasta que Claude proporciona una respuesta final sin solicitar ninguna herramienta.
Manejo de múltiples llamadas a herramientas
Claude puede solicitar múltiples herramientas en una sola respuesta. El contenido del mensaje contiene una lista de bloques, y necesitamos procesar cada bloque de uso de herramienta por separado:

La función run_tools maneja esto filtrando los bloques de uso de herramientas y procesando cada uno:
def run_tools(message):
tool_requests = [
block for block in message.content if block.type == "tool_use"
]
tool_result_blocks = []
for tool_request in tool_requests:
# Procesar cada solicitud de herramienta...Bloques de resultado de herramienta
Cada bloque de uso de herramienta debe responderse con un bloque de resultado de herramienta correspondiente. La conexión entre ellos se mantiene mediante IDs coincidentes:

La estructura del bloque de resultado de herramienta incluye:
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_request.id,
"content": json.dumps(tool_output),
"is_error": False
}Manejo de errores
La ejecución robusta de herramientas requiere manejar posibles errores. Cuando una herramienta falla, aún necesitamos proporcionar un bloque de resultado a Claude:
try:
tool_output = run_tool(tool_request.name, tool_request.input)
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_request.id,
"content": json.dumps(tool_output),
"is_error": False
}
except Exception as e:
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_request.id,
"content": f"Error: {e}",
"is_error": True
}Enrutamiento escalable de herramientas
Para admitir múltiples herramientas, crea una función de enrutamiento que asigne los nombres de las herramientas a sus implementaciones:
def run_tool(tool_name, tool_input):
if tool_name == "get_current_datetime":
return get_current_datetime(**tool_input)
elif tool_name == "another_tool":
return another_tool(**tool_input)
# Agrega más herramientas según sea necesarioEste enfoque facilita agregar nuevas herramientas sin modificar la lógica central de la conversación.
Flujo de trabajo completo
La conversación completa de múltiples turnos funciona así:
- Enviar el mensaje del usuario a Claude con las herramientas disponibles
- Claude responde con texto y/o solicitudes de herramientas
- Ejecutar todas las herramientas solicitadas y crear bloques de resultado
- Enviar los resultados de las herramientas de vuelta como un mensaje del usuario
- Repetir hasta que Claude proporcione una respuesta final
Esto crea una experiencia fluida en la que Claude puede usar múltiples herramientas a lo largo de varios turnos para responder completamente a solicitudes complejas del usuario. El historial de la conversación mantiene el contexto completo, lo que permite a Claude basarse en resultados de herramientas anteriores para proporcionar respuestas integrales.