Cargando

Conversaciones multi-turno con herramientas

Lección 279 min

Construir conversaciones multi-turno con uso de herramientas requiere manejar diferentes tipos de respuesta de Claude. Cuando Claude responde, puede que necesite usar una herramienta, o puede que proporcione una respuesta directa. Tu código necesita manejar ambos escenarios de manera adecuada.

El problema con la integración simple de herramientas

Si simplemente agregas resultados de herramientas a cada conversación, te encontrarás con problemas. Cuando Claude responde a una pregunta simple como "¿Cuánto es 1+1?", no necesita ninguna herramienta. Pero si tu código siempre intenta procesar resultados de herramientas, terminarás agregando mensajes vacíos a tu historial de conversación.

La solución es verificar el stop_reason que viene con cada respuesta de Claude. Esto te indica por qué Claude dejó de generar, ya sea porque terminó de forma natural o porque quiere usar una herramienta.

Razones de detención

Claude puede detenerse por varias razones:

  • "tool_use" - El modelo quiere llamar a una herramienta
  • "end_turn" - El modelo terminó de generar su respuesta
  • "max_tokens" - Se alcanzó el límite de salida
  • "stop_sequence" - Se encontró una secuencia de detención que proporcionaste

Mejorando la función de chat

Primero, actualiza tu función de chat para que devuelva más información. En lugar de simplemente devolver texto y partes por separado, devuelve un diccionario con todo lo que necesitas:

python
def chat(messages, tools=None, system=None, **kwargs):
    # ... código existente ...
    
    return {
        "parts": parts,
        "stop_reason": response["stopReason"],
        "text": "\n".join([p["text"] for p in parts if "text" in p])
    }

Este enfoque extrae todo el contenido de texto de las partes de la respuesta, lo cual es más robusto que asumir que la primera parte siempre es texto.

Construyendo un bucle de conversación

Crea una función que maneje el flujo completo de la conversación:

python
def run_conversation(messages):
    while True:
        result = chat(messages, tools=[get_current_datetime_schema])
        
        add_assistant_message(messages, result["parts"])
        print(result["text"])
        
        if result["stop_reason"] != "tool_use":
            break
            
        tool_result_parts = run_tools(result["parts"])
        add_user_message(messages, tool_result_parts)
    
    return messages

Este bucle continúa hasta que Claude se detiene por una razón distinta al uso de herramientas. Cada iteración:

  1. Envía los mensajes actuales a Claude
  2. Agrega la respuesta de Claude al historial de mensajes
  3. Verifica si Claude quiere usar una herramienta
  4. Si es así, ejecuta las herramientas y agrega los resultados de vuelta a la conversación
  5. Si no, sale del bucle

Probando la implementación

Este enfoque maneja tanto preguntas que requieren herramientas como preguntas simples:

python
# Pregunta que requiere una herramienta
messages = []
add_user_message(messages, "What time is it?")
run_conversation(messages)

# Pregunta simple  
messages = []
add_user_message(messages, "What is 1+1?")
run_conversation(messages)

Para preguntas sobre la hora, Claude usará la herramienta de fecha y hora. Para preguntas matemáticas, responde directamente sin ninguna llamada a herramientas. El bucle de conversación se adapta automáticamente según la razón de detención de Claude.

Este patrón escala bien cuando agregas más herramientas: el mismo bucle maneja cualquier combinación de uso de herramientas y respuestas directas, haciendo que tu IA conversacional sea más robusta y natural.