Cargando

Implementando múltiples turnos

Lección 2815 min

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 solicita 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:

python
if response.stop_reason != "tool_use":
    break  # Claude is done, no more tools needed

El bucle de conversación

La función principal de conversación sigue un patrón simple:

python
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 messages

Este 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 herramienta y procesando cada uno:

python
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:
        # Process each tool request...

Bloques de resultado de herramienta

Para cada bloque de uso de herramienta, necesitamos crear un bloque de resultado de herramienta correspondiente. Estos bloques tienen campos específicos requeridos:

El bloque de resultado de herramienta debe incluir el mismo ID que el bloque de uso de herramienta original, pero en el campo tool_use_id:

python
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 devolver un bloque de resultado de herramienta, pero con información de error:

python
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 separada en lugar de codificar los nombres de las herramientas directamente:

python
def run_tool(tool_name, tool_input):
    if tool_name == "get_current_datetime":
        return get_current_datetime(**tool_input)
    elif tool_name == "other_tool":
        return other_tool_function(**tool_input)
    # Agrega más herramientas según sea necesario

Este enfoque facilita agregar nuevas herramientas sin modificar la lógica central de 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 bloques de uso de herramienta
  • Ejecutar las herramientas solicitadas y crear bloques de resultado de herramienta
  • Enviar los resultados de las herramientas de vuelta a Claude como un mensaje de usuario
  • Repetir hasta que Claude proporcione una respuesta final sin solicitudes de herramientas

Esto crea una experiencia fluida donde Claude puede realizar múltiples llamadas a herramientas a lo largo de varios turnos de conversación para recopilar toda la información necesaria antes de proporcionar una respuesta final completa al usuario.