# ReACT Agent Loop

Fuente conceptual: MiroFish `backend/app/services/report_agent.py` (AGPL-3.0)
Reimplementar desde cero. No copiar codigo.

## Funcion a implementar

### react_loop

- **Dominio:** core
- **Lang:** Python
- **Purity:** impure (llama LLM y tools)
- **Signature:**
  ```python
  def react_loop(
      llm_chat: Callable[[list[dict]], str],
      tools: dict[str, Callable[..., str]],
      system_prompt: str,
      user_prompt: str,
      max_iterations: int = 5,
      on_thought: Callable[[str], None] | None = None,
      on_action: Callable[[str, dict], None] | None = None,
      on_observation: Callable[[str], None] | None = None,
  ) -> str:
  ```
- **Descripcion:** Implementa el patron ReACT (Reasoning + Acting) para agentes LLM. El agente razona, decide usar herramientas, observa resultados, y repite hasta producir una respuesta final.
- **Algoritmo:**
  1. Construir mensajes iniciales: system + user prompt con descripcion de tools disponibles
  2. Loop (max_iterations):
     - Llamar `llm_chat(messages)` → response
     - Parsear response buscando patrones:
       - `Thought:` → razonamiento del agente
       - `Action:` → nombre de tool a llamar
       - `Action Input:` → parametros (JSON)
       - `Observation:` → (se llena con resultado del tool)
       - `Final Answer:` → respuesta final, salir del loop
     - Si hay Action:
       - Llamar `tools[action_name](**action_input)`
       - Anadir observacion a mensajes
       - Callbacks: on_thought, on_action, on_observation
     - Si hay Final Answer: retornar
  3. Si se agota max_iterations: retornar ultimo response como fallback
- **Tools spec format:**
  ```
  Available tools:
  - search(query: str) -> str: Search knowledge graph
  - analyze(entity_id: str) -> str: Deep dive into entity
  ```
- **Deps:** `json`, `re`
- **Error type:** Exception (tool falla, LLM timeout)
- **Notas:**
  - El formato de parseo es flexible (Thought/Action/Observation es un patron comun en LangChain/ReACT)
  - Los callbacks permiten logging/UI sin acoplar al agente
  - La funcion es generica: funciona con cualquier LLM y cualquier set de tools
- **Tests:**
  - Agente que usa 1 tool y da respuesta final
  - Agente que usa multiples tools iterativamente
  - Agente que da respuesta directa sin tools
  - Max iterations alcanzado (fallback)
  - Tool que falla (error handling)
