# M10 Lab — Agent Scaffold

This scaffold provides the agent loop. You implement the AI interaction logic.

```python
"""Simple Research Agent — M10 Lab Scaffold."""

import os
from typing import Optional


# --- Configuration ---

MAX_ITERATIONS = 5  # Safety limit to prevent infinite loops
LLM_PROVIDER = os.getenv("LLM_PROVIDER", "openai")  # or anthropic, google


# --- LLM Interface (implement this) ---

def call_llm(prompt: str, system: str = "") -> str:
    """
    TODO: Implement LLM call.
    Use your configured provider (OpenAI, Anthropic, Google).
    Returns the LLM's text response.
    """
    # Your implementation here — use AI to help write this
    raise NotImplementedError("Implement call_llm() before running the agent")


# --- Tool: Simulated Search (implement this) ---

def search_tool(query: str) -> str:
    """
    TODO: Implement a simulated search tool.
    Could be: DuckDuckGo API, a keyword lookup in a local file, or a simple
    mock that returns "No results found for: {query}".
    """
    # Your implementation here
    return f"[Search results for: {query}] — simulated"


# --- Agent Loop ---

def run_agent(question: str) -> dict:
    """
    Run the agent to research a question.

    The agent:
    1. Plans: decomposes the question into sub-questions
    2. Executes: answers each sub-question (using search if needed)
    3. Synthesizes: combines answers into a final summary
    """
    history = []
    result = {"question": question, "steps": [], "summary": ""}

    # Step 1: Plan — decompose the question
    plan_prompt = f"""You are a research assistant. Break this question into
2-4 sub-questions that need to be answered to fully address it.

Question: {question}

Return each sub-question on a new line, numbered."""
    
    plan_response = call_llm(plan_prompt)
    sub_questions = [q.strip() for q in plan_response.split("\n") if q.strip() and q[0].isdigit()]
    result["steps"].append({"type": "plan", "sub_questions": sub_questions})

    # Step 2: Execute — answer each sub-question
    answers = []
    for i, sq in enumerate(sub_questions[:MAX_ITERATIONS]):
        # Decide whether to use search
        # (Simple heuristic: use search if question contains certain keywords)
        if any(word in sq.lower() for word in ["latest", "current", "news", "price", "weather"]):
            search_result = search_tool(sq)
            context = f"Search results: {search_result}\n\n"
        else:
            context = ""

        answer_prompt = f"{context}Answer this question concisely: {sq}"
        answer = call_llm(answer_prompt)
        answers.append({"question": sq, "answer": answer})
        result["steps"].append({"type": "answer", "question": sq, "answer": answer})

    # Step 3: Synthesize — combine into summary
    qa_pairs = "\n".join([f"Q: {a['question']}\nA: {a['answer']}" for a in answers])
    summary_prompt = f"""Synthesize these Q&A pairs into a comprehensive answer
to the original question: "{question}"

{qa_pairs}

Provide a clear, well-structured summary."""
    
    result["summary"] = call_llm(summary_prompt)

    return result


# --- Entry Point ---

if __name__ == "__main__":
    question = input("Research question: ")
    print("\n🤖 Agent researching...\n")
    result = run_agent(question)
    print("=" * 60)
    print(result["summary"])
    print("=" * 60)
    print(f"\nCompleted in {len(result['steps'])} steps.")
# See ~/workshop/m10/README.md for running instructions and tasks
