🛠️ Lab 2 — Build a ReAct Agent by Hand in LangGraph (50 pts)

Goal: Implement the ReAct Thought → Action → Observation loop yourself as an explicit LangGraph graph — a model-call node and a tool node — running against a free-tier LLM, so you understand exactly what the "agent" abstraction is doing underneath. Then trace and compare that behavior against a ready-made LangChain ReAct agent supplement. Steps:

  1. Set up your free-tier model access. Choose one: (a) get a free Google AI Studio API key for the Gemini API free tier, or (b) install Ollama and pull a small local model (e.g., llama3.2 or qwen2.5) to run entirely offline with no API key. Either option is fully free.
  2. Install dependencies in a fresh Python virtual environment: pip install langgraph langchain langchain-google-genai (for Gemini) or pip install langgraph langchain langchain-ollama (for Ollama).
  3. Define 2–3 simple tools using Python functions with type hints and docstrings (e.g., a calculator(expression: str) tool and a search_notes(query: str) tool that looks up a small local dictionary or text file you provide — no paid search API needed).
  4. Build the graph by hand: create a LangGraph StateGraph with (a) a call_model node that sends the running message list to your chat model with tools bound, and (b) a call_tools node that executes any tool calls the model produced and appends the results as tool messages. Add a conditional edge from call_model: if the last message has tool calls, route to call_tools; otherwise, route to END. Add a normal edge from call_tools back to call_model, closing the loop. Use the LangGraph ReAct Agent Template as a structural reference, but write the graph yourself rather than importing the prebuilt agent.
  5. Run your agent on a multi-step prompt that requires at least two tool calls in sequence (e.g., "look up the value of X in my notes, then calculate X times 12"). Capture the full console output showing each Thought, Action, and Observation.
  6. Read and annotate the trace. In your own words, mark on the captured output where the model reasoned, where it acted, and where the observation changed its next decision.
  7. Supplement — run the ready-made notebook. Open a Colab notebook wiring a LangChain ReAct agent to an OpenRouter free (:free) model ID with 2–3 tools (calculator, search). Run the same or a similar multi-step prompt and observe how the prebuilt AgentExecutor/LangGraph prebuilt agent handles tool selection step-by-step.
  8. Write a short comparison (200–300 words): what did building the loop by hand teach you that the ready-made agent hid from you? Where did your agent's behavior match your expectations from the lecture, and where did it surprise you?

Deliverables: Submit your Python source file(s) (or a .ipynb), the captured trace output from Step 5 with your annotations from Step 6, and your written comparison from Step 8, either as an uploaded file or pasted directly into the text entry box.