GenAI Speedrun
Home Mock Exam
⚡ PART 4 · BUILDING AI APPLICATIONS

AI Agents

Building AI that acts, not just talks — the LLM brain, tools, memory and planning, the ReAct framework, state management and LangGraph.

Syllabus topics 71–78 ⏱ ~18 min read 24 practice questions

From Chatbots to Agents

🧑‍💼 The Digital Intern A standard LLM (ChatGPT) is a brilliant encyclopedia — it answers questions and generates text, but it does not do anything beyond producing information. Agentic AI is a digital intern — it can reason, plan, and execute tasks using available tools. An intern has general knowledge (the Brain) but needs instructions and access to software (Tools) to be useful.
Agentic AI — an AI system that can reason, plan and act autonomously to achieve a goal, using tools to interact with the outside world. Generative AI is a "thinker" (produces text); Agentic AI is a "doer" (uses tools to execute tasks).

The Brain, Hands & Instructions

Every agent is built from three pillars:

PillarWhat it isRole
The BrainThe LLMReasoning, language understanding, decision-making — the "common sense" that figures out how to solve a problem
The HandsToolsCapabilities that let the agent interact with the world — search files, run code, call APIs
The InstructionsPromptsThe logic defining the agent's purpose, behaviour and workflow

The Brain — an LLM is a probabilistic prediction engine

The LLM brain is a "next-word predictor", not a sentient mind. It has a training phase (learns patterns by minimising prediction error on huge text data) and a decoding phase (generates text by producing a probability distribution over the next token). Decoding strategies: greedy search (always pick the most likely word) or stochastic sampling (get creative, controlled by temperature/top-p).

Why a "naked" LLM is not enough

⚠️ The limits of the Brain alone A plain LLM cannot: access real-time info (training cutoff), verify facts (hallucinations), perform actions like sending an email (no actions — it only outputs text), or do precise maths (poor at calculation). Ask "What's 2347 × 8563?" and it gives an approximate, often wrong answer. Tools fix all of this.

Tools & the Agentic Loop

Tools — external functions the agent can "call" when it needs help beyond its training data. The Brain (LLM) decides which tool to use; the system executes it. This is the foundation of Function Calling / Tool Calling.

Common tools: web search (real-time info), calculator (precise maths), API requests (weather, stock prices, email), code interpreter (run code, analyse data).

The agentic workflow loop

User Request → LLM Reasoning → Tool Selection → Execution → Synthesis

Example: "Is it raining in London?" → the LLM reasons "I need real-time data" → selects the Weather tool → the system executes it and returns "Rainy, 12°C" → the LLM synthesises "Yes, it is raining in London." The hallmark of a true agent is that moment when the model stops generating text and instead writes a command to call a tool.

Python · giving an LLM a tool (function calling)
from langchain_core.tools import tool

# 1. Define a tool - a normal function with a docstring
@tool
def multiply(a: int, b: int) -> int:
    """Multiply two numbers together."""
    return a * b

# 2. Bind the tool to the LLM (the "calculator" is handed over)
llm_with_tools = llm.bind_tools([multiply])

# 3. The LLM does not answer directly - it requests the tool
response = llm_with_tools.invoke("Calculate 50 times 173")
print("Tool call:", response.tool_calls)
OutputTool call: [{'name': 'multiply', 'args': {'a': 50, 'b': 173}, 'type': 'tool_call'}]

Notice the LLM did not compute the answer itself — it recognised it needs the tool and produced a structured tool call. The system then runs multiply(50, 173) = 8650 and feeds the result back.

Memory & Planning

Memory Management

TypeAnalogyHoldsLifespan
Short-term memorySticky noteImmediate info for the current task (e.g. "flight AA123 on March 15")The current session/task
Long-term memoryFiling cabinetPermanent info across sessions (e.g. "user prefers aisle seats")Permanent — stored in vector databases

Short-term memory handles the "what" of the current task; long-term memory stores the "who" and user preferences for personalised experiences.

Planning & Goal Decomposition

Planning — breaking a complex goal into smaller, manageable, sequential steps. Like building a skyscraper one floor at a time, with a site manager coordinating.

Example — "Plan my vacation" decomposes into: (1) Find flights → (2) Book hotel → (3) List restaurants. Planning makes impossible tasks possible, enables step-by-step progress tracking, and allows error recovery at each step.

Closed vs Open-Source LLMs & Ollama

Closed Source ("Walled Garden")Open Source ("Community Park")
ExamplesGPT (OpenAI), Gemini (Google), ClaudeLLaMA (Meta), Gemma (Google), Mistral
ProsTop reasoning benchmarks, managed infrastructure, regular updatesFree to run, privacy (runs locally), customisable & transparent
ConsPaid API, your data leaves your network, "black box"Needs local hardware (RAM/GPU), manual setup

Why go open source?

Ollama — the "MP3 player" for AI models

Ollama — a lightweight runtime that lets you easily download and run open-source LLMs locally. Raw model files are heavy files of weights you cannot just "open"; Ollama is the backend "runner" that loads and manages them (CPU/GPU allocation).
Ollama commandWhat it does
ollama pull llama4Downloads the model to your machine
ollama run llama4Loads the model into memory and starts a chat session (auto-pulls if missing)
ollama listShows all models installed in your library
ollama rm llama4Deletes a model to free disk space
ollama psShows which models are currently running & using RAM
💡 Tip — pull vs run ollama pull just downloads the model (like downloading an app). ollama run downloads if needed AND starts the chat (boots up the agent). If you only want the files for later, use pull.

The ReAct Framework

ReAct (Reason + Act) — a framework where the agent repeatedly cycles through Think → Act → Observe. It reasons about the situation, takes an action, observes the result, then reasons again — adapting until the task is complete.
THINK → ACT → OBSERVE → (THINK again) → …
🧩 ReAct in action Think: "I need to search for 'best Italian restaurants'." → Act: search executed. → Observe: "No results found." → Think again: "Try 'top rated pasta places' instead." → ActObserve … The loop repeats, each observation feeding back into reasoning, so the agent adapts when things go wrong.
🔑 Why ReAct matters A plain LLM gives one answer and stops. ReAct lets an agent self-correct — if an action fails, the next "Think" step reconsiders and tries a different approach. This adaptability is what makes agents reliable on multi-step real-world tasks.

State Management of AI Agents

State — a memory object that stores all the context an agent needs throughout an interaction. Like a waiter's order pad, constantly updated as the conversation progresses.

State management lets the agent: prevent forgetting previous context, support multi-turn conversations, track progress through complex workflows, and validate inputs.

🧩 State validation — the Pizza Bot User: "Order a pizza with shoe topping." → State check: "shoe" not in valid toppings → reject & loop back ("Please choose from Cheese, Pepperoni…"). User: "Cheese." → State check: valid ✓ → accept & proceed. State both remembers the order and guards the workflow.

Types of state (recap)

Complex Control Flow

Simple chatbots are linear — one straight path. Real agents need complex control flow:

💡 Tip — Human-in-the-Loop (HITL) Agents can make mistakes (book the wrong ticket, email the wrong person). HITL pauses the workflow before a critical or irreversible action and waits for a human to approve it — e.g. an agent drafts an email, pauses, a manager clicks "Approve", then the agent sends it.

LangGraph: Graphs, Nodes, Edges, State

LangGraph — a Python library for building stateful, multi-actor agent applications. Instead of a linear chat, you build a graph of logic — a decision tree where the agent can route itself based on conditions, loop, and maintain shared state.

LangGraph has four core components:

1. State — the shared diary

A typed Python dictionary (TypedDict) passed between every step. Each node reads from it and writes to it, carrying context forward. TypedDict gives type safety and prevents key errors. The add_messages reducer appends new messages instead of overwriting the history.

2. Nodes — the workers

Python functions that perform work. Each node receives the current state, performs an operation (call an LLM, run a tool, compute), and returns updates to the state. Keep each node to a single responsibility.

3. Edges — the logic gates

4. The StateGraph — the builder

The StateGraph assembles nodes and edges into an executable workflow. Three essential methods: add_node() (register a worker), add_edge() / add_conditional_edges() (connect them), and set_entry_point() (define where execution starts). Finally .compile() turns it into a runnable app.

🔑 Why graphs beat linear code for agents A graph allows cycles (loop back for the ReAct loop or user input), conditional routing (different paths per state), and deterministic, debuggable execution. State updates happen incrementally at each node; checkpointing lets a workflow resume after a failure.

Building an Agent Graph

Python · defining the State
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages

# State = a typed dictionary shared across all nodes
class AgentState(TypedDict):
    messages: Annotated[list, add_messages]  # add_messages APPENDS
    flight_price: int                        # other fields OVERWRITE
    decision: str
Python · nodes and conditional routing
# Node: receives state, returns state updates
def check_price(state: AgentState):
    if state["flight_price"] > 500:
        return {"decision": "ask_user"}
    return {"decision": "book"}

# Routing function for the conditional edge
def route(state: AgentState):
    return "ask" if state["decision"] == "ask_user" else "book"
Python · building & compiling the graph
from langgraph.graph import StateGraph, START, END

builder = StateGraph(AgentState)

# 1. Register nodes (workers)
builder.add_node("find_flight", find_flight)
builder.add_node("check_price", check_price)
builder.add_node("book_flight", book_flight)
builder.add_node("ask_user", ask_user)

# 2. Connect with edges
builder.add_edge(START, "find_flight")
builder.add_edge("find_flight", "check_price")
builder.add_conditional_edges("check_price", route,
                              {"book": "book_flight", "ask": "ask_user"})
builder.add_edge("book_flight", END)

# 3. Compile into a runnable app
app = builder.compile()
result = app.invoke({"flight_price": 0, "decision": "", "messages": []})
Python · a ReAct-style tool-using agent
from langgraph.prebuilt import ToolNode
from langgraph.graph import StateGraph, START, END

def assistant_node(state):                      # the "Think" node
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

tool_node = ToolNode([multiply])                # the "Act" node

def should_continue(state):                     # router: loop or stop?
    last = state["messages"][-1]
    return "tools" if last.tool_calls else END

builder = StateGraph(State)
builder.add_node("assistant", assistant_node)
builder.add_node("tools", tool_node)
builder.add_edge(START, "assistant")
builder.add_conditional_edges("assistant", should_continue)
builder.add_edge("tools", "assistant")          # loop back -> ReAct cycle
graph = builder.compile()
Output (for "Calculate 50 times 173 then divide by 5")The result of 50 times 173 is 8650. Dividing 8650 by 5 gives 1730.

The edge tools → assistant creates the loop — the agent keeps reasoning and acting until should_continue returns END. That loop is the ReAct cycle implemented as a graph.

💡 Tip — checkpointing for reliability Add a checkpointer (e.g. MemorySaver) when compiling the graph to save state snapshots. The agent can then recover from crashes, resume multi-turn conversations after a restart, and avoid recomputing completed work.
? Practice Questions

Agent components and Ollama commands are common exam material.

MCQQ1Agent vs chatbot

The key difference between Generative AI and Agentic AI is that Agentic AI:

  • A Only produces text
  • B Can use tools to take actions and execute tasks, not just talk
  • C Never uses an LLM
  • D Cannot reason
Answer: B

Generative AI is a "thinker" that produces content. Agentic AI is a "doer" — it reasons, plans, and uses tools to act on the world.

MCQQ2Pillars

In the "digital intern" framework, what plays the role of the Brain?

  • A The tools
  • B The LLM
  • C The vector database
  • D The user interface
Answer: B

The LLM is the Brain (reasoning); Tools are the Hands; Prompts are the Instructions.

MCQQ3Tools

Why does an agent need a calculator tool for "What is 2347 × 8563?"

  • A Because the LLM cannot read numbers
  • B Because LLMs predict tokens and are unreliable at precise calculation
  • C Because tools are always faster
  • D Because the LLM has no memory
Answer: B

LLMs are linguistic engines, not computational ones — they often give approximate, wrong arithmetic. A calculator tool gives exact results.

MCQQ4Function calling

When an LLM with tools decides it needs a tool, it produces:

  • A The final answer directly
  • B A structured tool call specifying the tool name and arguments
  • C An error message
  • D Nothing
Answer: B

The model pauses generation and emits a tool call (name + arguments). The system runs the tool and feeds the result back to the LLM.

MCQQ5Memory

An agent permanently remembering "this user prefers vegetarian meals" is using:

  • A Short-term memory
  • B Long-term memory
  • C No memory
  • D A tool call
Answer: B

Long-term memory (the "filing cabinet", often a vector DB) stores permanent preferences across sessions. Short-term memory is just for the current task.

MCQQ6Planning

Goal decomposition / planning means the agent:

  • A Answers the whole task in one giant step
  • B Breaks a complex goal into smaller sequential steps
  • C Deletes its memory
  • D Refuses hard tasks
Answer: B

Planning splits a goal (e.g. "plan my vacation") into manageable steps (find flights → book hotel → list restaurants), enabling progress tracking and error recovery.

MCQQ7Open source

Which is an open-source / open-weight LLM family?

  • A GPT-4
  • B Gemini
  • C LLaMA
  • D Claude
Answer: C

LLaMA (Meta), Gemma (Google) and Mistral are open-weight models you can run locally. GPT, Gemini and Claude are closed-source/proprietary.

MCQQ8Ollama

Which Ollama command downloads a model AND immediately starts a chat session?

  • A ollama pull
  • B ollama list
  • C ollama run
  • D ollama rm
Answer: C

ollama run loads the model into memory and starts the chat (auto-pulling it first if missing). ollama pull only downloads.

MCQQ9Privacy

A major reason a hospital might choose an open-source LLM run locally is:

  • A It always has the highest benchmark scores
  • B Data privacy & compliance — sensitive patient data never leaves the network
  • C It needs no hardware
  • D It cannot hallucinate
Answer: B

Local open-source models keep prompts and data on-device — essential for HIPAA and other regulations. Closed APIs send data to a third party.

CodingQ10Define a tool

Using LangChain, define a tool that returns the length of a string, and bind it to an LLM.

Solution
Python
from langchain_core.tools import tool

@tool
def string_length(text: str) -> int:
    """Return the number of characters in a string."""
    return len(text)

# Hand the tool to the LLM
llm_with_tools = llm.bind_tools([string_length])

response = llm_with_tools.invoke("How long is the word 'agent'?")
print(response.tool_calls)
Output[{'name': 'string_length', 'args': {'text': 'agent'}, 'type': 'tool_call'}]

The @tool decorator + docstring tell the LLM what the tool does and when to call it.

Short AnswerQ11Concept

List the four main limitations of a "naked" LLM (without tools) and explain how tools address them.

Model answer

(1) Training cutoff — no real-time info; a web-search tool fetches current data. (2) Hallucinations — it invents facts; tools/RAG return verified data. (3) No actions — it only outputs text; API tools let it send emails, query databases. (4) Poor maths — it predicts tokens, not computes; a calculator tool gives exact results.

Short AnswerQ12Agentic loop

Describe the agentic workflow loop for the request "What's the weather in Tokyo?".

Model answer

User request → "What's the weather in Tokyo?". LLM reasoning → the model recognises it needs real-time data it does not have. Tool selection → it generates a call to the Weather tool with location = Tokyo. Execution → the system runs the tool and returns raw data (e.g. "Sunny, 22°C"). Synthesis → the LLM turns that into a natural reply: "It is currently sunny and 22°C in Tokyo."

MCQQ13ReAct

The ReAct framework cycles through which three steps?

  • A Read → Encode → Generate
  • B Think → Act → Observe
  • C Train → Test → Deploy
  • D Retrieve → Augment → Generate
Answer: B

ReAct = Reason + Act: Think (decide), Act (execute), Observe (review the result) — then think again. (Retrieve→Augment→Generate is RAG.)

MCQQ14ReAct benefit

The main benefit of the ReAct loop is that the agent can:

  • A Answer instantly without reasoning
  • B Adapt and self-correct when an action fails
  • C Avoid using any tools
  • D Skip the observe step
Answer: B

Each Observe feeds back into Think, so when an action fails the agent reconsiders and tries a different approach — it self-corrects.

MCQQ15State

In an AI agent, "state" is best described as:

  • A The model's weights
  • B A memory object holding all context the agent needs during an interaction
  • C The temperature setting
  • D A type of activation function
Answer: B

State is the constantly-updated "order pad" that stores messages, intermediate results and progress so the agent stays coherent.

MCQQ16LangGraph

In LangGraph, a node is:

  • A A connection between two functions
  • B A Python function that receives state and returns state updates
  • C The final answer
  • D A type of embedding
Answer: B

A node is a worker function: it takes the current state, does an operation, and returns updates. Edges connect nodes.

MCQQ17Edges

A conditional edge in LangGraph:

  • A Always sends the flow to a fixed next node
  • B Uses a routing function to choose the next node based on the state
  • C Deletes the state
  • D Trains the model
Answer: B

A conditional edge runs a routing function that inspects the state and dynamically picks which node executes next — like a GPS rerouting.

MCQQ18add_messages

Annotating the messages field with add_messages ensures that new messages are:

  • A Deleted
  • B Appended to the existing list, not overwriting history
  • C Translated
  • D Sent to a different graph
Answer: B

add_messages is a reducer that appends new messages, preserving the full conversation history instead of replacing it.

MCQQ19HITL

Human-in-the-Loop (HITL) is used to:

  • A Make the agent run faster
  • B Pause for human approval before a critical or risky action
  • C Remove the LLM from the system
  • D Increase the temperature
Answer: B

HITL inserts a human checkpoint — the workflow pauses for approval before irreversible actions (sending an email, making a purchase).

MCQQ20Why graphs

Why is a graph-based approach better than linear code for AI agents?

  • A Graphs never use state
  • B Graphs support cycles, conditional routing and deterministic, debuggable flow
  • C Graphs do not need an LLM
  • D Graphs run only once
Answer: B

Graphs allow loops (ReAct), conditional routing based on state, and explicit, predictable execution that is easy to debug and scale.

CodingQ21Define state

Define a LangGraph State TypedDict with a messages list (appended) and a task_status string.

Solution
Python
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages

class AgentState(TypedDict):
    messages: Annotated[list, add_messages]   # appended each step
    task_status: str                          # overwritten each step

The Annotated[..., add_messages] reducer makes messages append; plain fields like task_status are overwritten on update.

CodingQ22Build a graph

Build a minimal LangGraph with a single node chat connected from START to END, and compile it.

Solution
Python
from langgraph.graph import StateGraph, START, END
from langchain_core.messages import AIMessage

def chat_node(state):
    text = state["messages"][-1].content
    return {"messages": [AIMessage(content=f"I heard: {text}")]}

graph = StateGraph(AgentState)
graph.add_node("chat", chat_node)
graph.add_edge(START, "chat")
graph.add_edge("chat", END)

app = graph.compile()

add_node registers the worker, two add_edge calls wire START → chat → END, and .compile() produces a runnable app.

CodingQ23Conditional edge

Write a routing function and add a conditional edge so that, after a check node, the graph goes to "approve" if state["amount"] > 1000, otherwise to "auto".

Solution
Python
def route(state):
    if state["amount"] > 1000:
        return "approve"      # needs human approval
    return "auto"             # auto-process

builder.add_conditional_edges(
    "check", route,
    {"approve": "approve_node", "auto": "auto_node"}
)

The routing function inspects the state and returns a key; the mapping dictionary sends the flow to the matching node.

Short AnswerQ24Concept

Name LangGraph's four core components and state the role of each in one line.

Model answer

State — a typed dictionary (the shared "diary") passed between steps, holding all context. Nodes — Python worker functions that receive state and return updates. Edges — connections defining flow; conditional edges route dynamically based on state. StateGraph — the builder that registers nodes, connects edges and compiles everything into a runnable app.

🎯Key Takeaways Agent = "digital intern": Brain (LLM) + Hands (Tools) + Instructions (Prompts). LLM alone fails: training cutoff, hallucinations, no actions, poor maths. Tools/Function Calling fix this. Loop: Request → Reason → Select tool → Execute → Synthesise. Memory: short-term (sticky note) vs long-term (filing cabinet/vector DB). Planning = goal decomposition. Closed: GPT/Gemini/Claude; Open: LLaMA/Gemma/Mistral. Ollama runs local models (pull, run, list, rm). ReAct = Think → Act → Observe (loop, enables self-correction). State = the agent's memory "order pad"; also validates inputs. Complex control flow: branching, loops, conditional routing, HITL (pause for human approval). LangGraph: State (typed dict), Nodes (worker functions), Edges (standard or conditional), StateGraph builder → .compile(). add_messages appends history; checkpointing enables recovery.