Components of an AI agent

In the last lesson you built an agent that found a stopped print spooler on its own. It worked, but it forgot everything the moment the script ended. Ask it the same question tomorrow and it starts from zero.

That’s because an agent is more than a model with tools. Its AI agent architecture has six parts: the model, the instructions, the tools, memory, planning and guardrails. Each part changes what the agent can do, and each one can fail in its own way.

In this lesson you’ll add memory and planning to your agent and see both help. Then you’ll break memory twice: once with a broken file, and once with a note that has gone out of date.

TimeYou needBy the end you can
About 60 minutesPython 3 and Ollama with llama3.2:3b (from Lessons 2 and 13)Name the six components of an agent, add long-term memory and a planning step, and protect an agent from broken or stale memory

What it is, in one line

AI agent architecture is the set of parts around the model: instructions, tools, memory, planning and guardrails, all held together by the loop in your code.

In Simple Words

A new engineer’s first month

Think about a new engineer on your team. They have a brain, but that alone doesn’t make them useful.

They get a job description that says what to do and what not to do. They get access to the admin tools. They keep a notebook, so the fix they learned on Monday is still there on Friday.

For a big job, they write a short plan before touching anything. And the team sets limits: they can look at anything, but they ask before restarting a server.

An AI agent has the same six parts. The model is the brain, the instructions are the job description, the tools are the admin access, memory is the notebook, planning is the to-do list, and guardrails are the team’s rules.

Engineer's View

Six components and the loop that joins them

1. Model. It reads the conversation and decides the next step. Pick it for how well it calls tools, how much context it holds and how fast it answers, not only for its size.

2. Instructions. The system prompt sets the role, the rules and the answer format (Lessons 8 and 12). In the lab this is the RULES line.

3. Tools. Functions the model can ask for, described by a name, a description and a JSON schema (Lesson 13). Keep each tool small, clearly named, and marked as read-only or as a change.

4. Memory. There are two kinds:

  • Short-term memory is the messages list for one task. It’s lost when the script ends and is limited by the context window (Lesson 10).
  • Long-term memory is stored outside the model: a JSON file, a database, or a vector store searched by meaning, as in RAG (Lesson 11). Relevant notes are loaded into the prompt at the start of each task.

Long-term memory needs a write policy: what gets saved, who can save it, and when it expires. Every saved note will steer future answers.

5. Planning. The model writes a short plan before acting, then follows it. Plans help with multi-step jobs and let the model ask for several tools at once. A plan is still only text, so the agent should re-plan when a result surprises it.

6. Guardrails. Step limits, approvals, argument checks, least privilege and error handling (Lesson 13). They live in your code, because the model can ignore instructions.

The loop and the logs. Your code joins the six parts: it builds the prompt, calls the model, runs tools and enforces limits. It should also log every step, because the trace is how you debug an agent.

Why it matters on the job: when an agent fails, the first question is which component failed. A wrong answer is often a memory or tool problem, not a model problem.

How it works, step by step

Here are the six components, with the piece of agent2.py that plays each part:

AI agent architecture: model, instructions, tools, memory, planning and guardrails around the loop in your code

One task moves through them in this order:

  1. Load memory. Your code reads memory.json and adds the notes to the system prompt.
  2. Build the prompt. Instructions, notes, the question and the tool list go to the model.
  3. Plan (optional). The model writes a short numbered plan, with no tools yet.
  4. Act. The model asks for tools; your code checks the guardrails and runs them.
  5. Save. If the model calls remember, your code adds a dated note to memory.json for next time.

Here’s what long-term memory changes, using the runs from the lab:

AI agent architecture: a note saved in memory.json lets the next run skip two steps, without checking

With the note, the agent skipped two steps and went straight to the fix. That’s faster, and it’s also the risk. If the note is wrong or out of date, the agent acts on it just as quickly.

Is memory the same as RAG?

They use the same idea: store text outside the model and put the useful parts back into the prompt. RAG usually reads documents that people wrote and maintain.

Agent memory is written by the agent itself, while it works. That makes it more useful, and it needs more checking.

Hands-on Lab: build an AI agent architecture with memory and planning

You’ll use agent2.py, the Lesson 13 agent with two new parts: long-term memory in memory.json and an optional planning step. Error handling for tools is already built in.

The tools, the memory file and the step limit always behave exactly as shown. Which tools the model picks, and its wording, can differ a little on your laptop. On macOS or Linux, use python3, nano and cat instead of type.

1Run the agent and read its parts

Run this:

cd C:\ai-lab\agent
notepad agent2.py

Paste this whole block into agent2.py, then save:

import datetime
import json
import os
import urllib.request

MODEL = "llama3.2:3b"
QUESTION = "Nobody on the 2nd floor can print. Can you check?"
MEMORY = False        # True = load memory.json and add a remember tool
PLAN = False          # True = write a short plan before using any tools
APPROVE = True        # True = ask you before any tool that changes something
MAX_STEPS = 6         # stop after this many calls to the model
RULES = "You are an IT support agent. Check with the tools before you answer. Answer in two sentences."

# A pretend network, so the lab is safe to run on any laptop
SERVERS = {
    "web01": {"role": "intranet web server", "disk": 41, "services": {"nginx": "running"}},
    "file01": {"role": "file server", "disk": 97, "services": {"smb": "running"}},
    "print01": {"role": "print server for floors 1 to 3", "disk": 58, "services": {"spooler": "stopped"}},
}


def list_servers():
    return "\n".join(f"{name}: {s['role']}" for name, s in SERVERS.items())


def check_disk(server):
    return f"{server}: disk {SERVERS[server]['disk']}% used"


def check_service(server, service):
    state = SERVERS[server]["services"].get(service, "not installed")
    return f"{service} on {server}: {state}"


def restart_service(server, service):
    SERVERS[server]["services"][service] = "running"
    return f"{service} on {server} restarted, now running"


def load_memory():
    if not os.path.exists("memory.json"):
        return []
    with open("memory.json") as f:
        return json.load(f)


def remember(note):
    notes = load_memory()
    notes.append({"note": note, "saved": datetime.date.today().isoformat()})
    with open("memory.json", "w") as f:
        json.dump(notes, f, indent=2)
    return "Saved to memory."


FUNCS = {f.__name__: f for f in [list_servers, check_disk, check_service, restart_service, remember]}
CHANGES = {"restart_service"}      # tools that change something


def tool(name, description, **params):
    props = {p: {"type": "string", "description": d} for p, d in params.items()}
    return {"type": "function", "function": {"name": name, "description": description,
            "parameters": {"type": "object", "properties": props, "required": list(params)}}}


TOOLS = [
    tool("list_servers", "List all servers and what each one does."),
    tool("check_disk", "Show how full a server's disk is.", server="Server name, for example web01"),
    tool("check_service", "Show whether a service is running.", server="Server name, for example web01", service="Service name, for example nginx"),
    tool("restart_service", "Restart a service. Only use it when check_service shows a problem.", server="Server name, for example web01", service="Service name, for example nginx"),
]
if MEMORY:
    TOOLS.append(tool("remember", "Save a useful fact for future conversations.", note="The fact to save, in one sentence"))


def chat(messages, use_tools=True):
    body = {"model": MODEL, "messages": messages, "stream": False, "options": {"temperature": 0}}
    if use_tools:
        body["tools"] = TOOLS
    req = urllib.request.Request("http://localhost:11434/api/chat", data=json.dumps(body).encode(),
                                 headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as r:
        return json.load(r)


notes = load_memory() if MEMORY else []
system = RULES
if notes:
    system += "\n\nNotes from earlier conversations:\n" + "\n".join(f"- {n['note']} (saved {n['saved']})" for n in notes)
print(f"Model: {MODEL} | Tools: {len(TOOLS)} | Notes in memory: {len(notes)} | Plan: {'on' if PLAN else 'off'} | "
      f"Approval: {'on' if APPROVE else 'off'} | Step limit: {MAX_STEPS}")
messages = [{"role": "system", "content": system}, {"role": "user", "content": QUESTION}]
print("Question:", QUESTION)
if PLAN:
    ask = messages + [{"role": "user", "content": "Before you use any tools, write a numbered plan of at most 4 steps."}]
    plan = chat(ask, use_tools=False)["message"]["content"].strip()
    print("Plan:\n  " + plan.replace("\n", "\n  "))
    messages.append({"role": "assistant", "content": "My plan:\n" + plan})
for step in range(1, MAX_STEPS + 1):
    msg = chat(messages)["message"]
    messages.append(msg)
    calls = msg.get("tool_calls")
    if not calls:
        print("Answer:", msg["content"].strip())
        break
    for call in calls:
        name, args = call["function"]["name"], call["function"]["arguments"]
        print(f"Step {step}: {name}(" + ", ".join(f"{k}={v!r}" for k, v in args.items()) + ")")
        if name in CHANGES and APPROVE and input("  Allow this change? [y/n] ").strip().lower() != "y":
            result = "The user did not allow this change."
        else:
            try:
                result = FUNCS[name](**args)
            except Exception as e:
                result = f"Error: {e}"
        print("  -> " + result.replace("\n", "\n     "))
        messages.append({"role": "tool", "content": result, "tool_name": name})
else:
    print(f"Stopped: no answer after {MAX_STEPS} steps.")

Run this:

python agent2.py

When the script asks Allow this change?, type y and press Enter.

You should see something like this (the model’s words and choices may differ a little):

Model: llama3.2:3b | Tools: 4 | Notes in memory: 0 | Plan: off | Approval: on | Step limit: 6
Question: Nobody on the 2nd floor can print. Can you check?
Step 1: list_servers()
  -> web01: intranet web server
     file01: file server
     print01: print server for floors 1 to 3
Step 2: check_service(server='print01', service='spooler')
  -> spooler on print01: stopped
Step 3: restart_service(server='print01', service='spooler')
  Allow this change? [y/n] y
  -> spooler on print01 restarted, now running
Answer: The print spooler on print01 had stopped, so nobody could print. I restarted it and it is running again, so printing should work now.

The first line lists the components: model, tools, memory, planning and guardrails. Memory is off, so it takes three steps, like in Lesson 13.

✅ Checkpoint: The first line shows Tools: 4 and Notes in memory: 0, and the agent takes three steps.

2Turn on memory and teach it something

Change these two lines:

MEMORY = True
QUESTION = "Remember this: on print01 the spooler stops after Windows updates. Restarting it is safe."

Run this:

python agent2.py

You should see something like this (the model’s words and choices may differ a little):

Model: llama3.2:3b | Tools: 5 | Notes in memory: 0 | Plan: off | Approval: on | Step limit: 6
Question: Remember this: on print01 the spooler stops after Windows updates. Restarting it is safe.
Step 1: remember(note='On print01 the print spooler stops after Windows updates, and restarting it is safe.')
  -> Saved to memory.
Answer: Got it. I've saved that note, so next time I'll know the spooler on print01 can stop after Windows updates.

Memory on adds a fifth tool, remember. The model decided this message was worth saving and called it. Now look at the file it wrote:

Run this:

type memory.json

You should see something like this (your date will be today’s date):

[
  {
    "note": "On print01 the print spooler stops after Windows updates, and restarting it is safe.",
    "saved": "2026-10-19"
  }
]

The note is stored with the date it was saved. That date matters later in this lesson.

✅ Checkpoint: memory.json exists and holds one note about the print01 spooler.

3Ask again with memory

Change this line:

QUESTION = "Nobody on the 2nd floor can print. Can you check?"

Run this:

python agent2.py
AI agent architecture lab: the agent saves a note to memory, then uses it to fix printing in one step
Example output. Your numbers and the model’s exact words will be a little different.

You should see something like this (the model’s words and choices may differ a little):

Model: llama3.2:3b | Tools: 5 | Notes in memory: 1 | Plan: off | Approval: on | Step limit: 6
Question: Nobody on the 2nd floor can print. Can you check?
Step 1: restart_service(server='print01', service='spooler')
  Allow this change? [y/n] y
  -> spooler on print01 restarted, now running
Answer: The print spooler on print01 stops after Windows updates, so I restarted it. Printing should work again now.

One step instead of three. The note was in the system prompt, so the model went straight to the restart and even explained why.

Look closely, though: it didn’t check anything first. Keep that in mind for the second Break It lab.

✅ Checkpoint: Notes in memory: 1, and the agent restarts the spooler in one step.

4Add a planning step

Change these two lines:

PLAN = True
QUESTION = "Check every server and tell me what needs attention."

Run this:

python agent2.py
AI agent architecture lab: the agent writes a plan, then checks every server in three steps
Example output. Your numbers and the model’s exact words will be a little different.

You should see something like this (the model’s words and choices may differ a little):

Model: llama3.2:3b | Tools: 5 | Notes in memory: 1 | Plan: on | Approval: on | Step limit: 6
Question: Check every server and tell me what needs attention.
Plan:
  1. List all servers.
  2. Check the disk on every server.
  3. Check the main service on every server.
  4. Report anything that needs attention.
Step 1: list_servers()
  -> web01: intranet web server
     file01: file server
     print01: print server for floors 1 to 3
Step 2: check_disk(server='web01')
  -> web01: disk 41% used
Step 2: check_disk(server='file01')
  -> file01: disk 97% used
Step 2: check_disk(server='print01')
  -> print01: disk 58% used
Step 3: check_service(server='web01', service='nginx')
  -> nginx on web01: running
Step 3: check_service(server='file01', service='smb')
  -> smb on file01: running
Step 3: check_service(server='print01', service='spooler')
  -> spooler on print01: stopped
Answer: Two things need attention: file01's disk is 97% full, and the print spooler on print01 has stopped. web01 looks fine, so ask me to restart the spooler if you want it fixed now.

The model wrote a four-line plan before using any tool, then followed it. In steps 2 and 3 it asked for three tools in one reply, so seven checks took only three model calls.

It also didn’t restart the spooler, because this question asked for a report, not a fix. The plan kept it on task.

✅ Checkpoint: A numbered plan appears first, and the answer names file01’s disk and the stopped spooler.

Break It, Then Fix It

Memory makes an agent faster. It also gives you two new ways to fail.

1Break it: a memory file edited by hand

A teammate wants to add a note without asking the agent, so they edit memory.json in Notepad. They copy the first note and forget one comma.

Change these two lines:

PLAN = False
QUESTION = "Nobody on the 2nd floor can print. Can you check?"

Run this:

notepad memory.json

Replace everything in memory.json with this, then save (note there’s no comma after the first }):

[
  {
    "note": "On print01 the print spooler stops after Windows updates, and restarting it is safe.",
    "saved": "2026-10-19"
  }
  {
    "note": "file01 is cleaned up every Friday evening.",
    "saved": "2026-10-19"
  }
]

Run this:

python agent2.py

You’ll get an error like this (the middle lines come from Python’s json module and vary by version):

Traceback (most recent call last):
  File "C:\ai-lab\agent\agent2.py", line 85, in <module>
    notes = load_memory() if MEMORY else []
  File "C:\ai-lab\agent\agent2.py", line 44, in load_memory
    return json.load(f)
  ...
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 6 column 3 (char 138)

One missing comma, and the whole agent stops before it does anything. Python is precise: line 6, column 3 is where it expected a comma.

Memory is data from outside your code. Treat it like any other input that can be broken.

The fix, part 1: a broken memory file shouldn’t stop the agent. Replace the load_memory function so it warns and carries on:

Find this function:

def load_memory():
    if not os.path.exists("memory.json"):
        return []
    with open("memory.json") as f:
        return json.load(f)

Replace it with this:

def load_memory():
    if not os.path.exists("memory.json"):
        return []
    try:
        with open("memory.json") as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        print(f"WARNING: memory.json is broken ({e}). Running without memory.")
        return []

Run this:

python agent2.py

You should see something like this (the model’s words and choices may differ a little):

WARNING: memory.json is broken (Expecting ',' delimiter: line 6 column 3 (char 138)). Running without memory.
Model: llama3.2:3b | Tools: 5 | Notes in memory: 0 | Plan: off | Approval: on | Step limit: 6
Question: Nobody on the 2nd floor can print. Can you check?
Step 1: list_servers()
  -> web01: intranet web server
     file01: file server
     print01: print server for floors 1 to 3
Step 2: check_service(server='print01', service='spooler')
  -> spooler on print01: stopped
Step 3: restart_service(server='print01', service='spooler')
  Allow this change? [y/n] y
  -> spooler on print01 restarted, now running
Answer: The print spooler on print01 had stopped, so nobody could print. I restarted it and it is running again, so printing should work now.

The agent warns you, works without memory, and still fixes the spooler the long way. That’s the right behaviour, but don’t leave it here.

The fix, part 2: repair the file. Add the missing comma after the first }:

Run this:

notepad memory.json

memory.json should now look like this:

[
  {
    "note": "On print01 the print spooler stops after Windows updates, and restarting it is safe.",
    "saved": "2026-10-19"
  },
  {
    "note": "file01 is cleaned up every Friday evening.",
    "saved": "2026-10-19"
  }
]

Run this:

python agent2.py

You should see something like this (the model’s words and choices may differ a little):

Model: llama3.2:3b | Tools: 5 | Notes in memory: 2 | Plan: off | Approval: on | Step limit: 6
Question: Nobody on the 2nd floor can print. Can you check?
Step 1: restart_service(server='print01', service='spooler')
  Allow this change? [y/n] y
  -> spooler on print01 restarted, now running
Answer: The print spooler on print01 stops after Windows updates, so I restarted it. Printing should work again now.

Both notes load again, and the agent is back to one step. If the agent called remember while the file was broken, it would have saved over your old notes, which is why you fix the file straight away.

✅ Checkpoint: The missing comma gives a JSONDecodeError. The new load_memory warns instead, and the repaired file loads 2 notes.

2Break it again: a note that’s out of date

A month later, the problem on print01 is different. The spooler is running, but the disk is full. Change the pretend network to match:

Find this line in SERVERS:

    "print01": {"role": "print server for floors 1 to 3", "disk": 58, "services": {"spooler": "stopped"}},

Change it to this:

    "print01": {"role": "print server for floors 1 to 3", "disk": 100, "services": {"spooler": "running"}},

Run this:

python agent2.py
AI agent architecture lab: a stale memory note makes the agent restart the wrong thing, then a rule makes it check first
Example output. Your numbers and the model’s exact words will be a little different.

You’ll see something like this:

Model: llama3.2:3b | Tools: 5 | Notes in memory: 2 | Plan: off | Approval: on | Step limit: 6
Question: Nobody on the 2nd floor can print. Can you check?
Step 1: restart_service(server='print01', service='spooler')
  Allow this change? [y/n] y
  -> spooler on print01 restarted, now running
Answer: The print spooler on print01 stops after Windows updates, so I restarted it. Printing should work again now.

The agent trusted its note, restarted a spooler that was already running, and told the user printing should work. It doesn’t, because the disk is still 100% full. It never looked.

The note was true when it was saved, but nothing in the system knew it had gone stale.

The fix: tell the model what notes are, and make checking the current state part of its instructions:

Change the RULES line to this:

RULES = "You are an IT support agent. Notes are hints from the past: always check the current state with a tool before you change anything. Answer in two sentences."

Run this:

python agent2.py

You should see something like this (the model’s words and choices may differ a little):

Model: llama3.2:3b | Tools: 5 | Notes in memory: 2 | Plan: off | Approval: on | Step limit: 6
Question: Nobody on the 2nd floor can print. Can you check?
Step 1: check_service(server='print01', service='spooler')
  -> spooler on print01: running
Step 2: check_disk(server='print01')
  -> print01: disk 100% used
Answer: The spooler on print01 is running, so this isn't the Windows update problem from my notes. The disk on print01 is 100% full, which stops print jobs; free up space on it and printing should recover.

Now the note is a hint, not an order. The agent checked the spooler, saw it running, checked the disk and found the real cause. Notice it didn’t ask to restart anything, because nothing needed restarting.

In real systems you’d also give notes an expiry date and record which server version they apply to.

✅ Checkpoint: With the stale note, the agent restarts the spooler and misses the full disk. With the new rule, it checks first and reports the disk at 100%.

This happened at work

The note that locked out sixty people

A company gave its service desk agent long-term memory, so it could learn fixes from engineers. One evening, an engineer closed a VPN ticket by resetting the user’s MFA token. The agent saved a note: “VPN problems are fixed by resetting the MFA token.”

Two weeks later, a VPN certificate expired and many users couldn’t connect. The agent followed its note and reset MFA tokens for about sixty users. None of them could sign in afterwards, and the service desk spent a day re-enrolling phones.

The real fix was renewing one certificate. Nobody had reviewed what the agent saved, and the note had no scope, owner or expiry date.

The fix: notes now wait in a review queue until an engineer approves them. Each note says which system and which kind of problem it applies to, and it expires after 90 days unless renewed. Any action taken because of a note must first be confirmed with a check tool.

The lesson: long-term memory is a write path into every future decision the agent makes. Treat what it saves with the same care as a change to production config.

Common mistakes and troubleshooting

MistakeWhat happensHow to avoid it
Saving everything the agent learnsWrong or one-off fixes become “rules”Use a write policy: what to save, who approves, when it expires
Acting on memory without checkingStale notes cause the wrong fix, fastTreat notes as hints; check the current state before any change
Loading memory without validationOne bad file stops the agentValidate memory on load, warn, and keep a backup
Putting all memory into every promptLong, slow prompts and confused answersLoad only notes that match the task, or search memory by meaning
Treating the plan as a promiseThe agent follows a plan that no longer fitsLet it re-plan when results surprise it; keep the step limit
Blaming the model for every failureTime wasted swapping modelsFind the failing component first: instructions, tools, memory, planning or guardrails
No logs of steps and memory readsYou can’t explain why it actedLog each prompt, tool call, result and note that was loaded

Troubleshooting the lab

ProblemFix
json.decoder.JSONDecodeError at start-upmemory.json is broken. Fix the JSON, or delete the file to start with no memory
The model never calls rememberCheck that MEMORY = True, and start your message with “Remember this:”
Notes in memory: 0, but the file existsThe script reads memory.json from the folder you run it in. Run it from C:\ai-lab\agent
No plan appearsCheck that PLAN = True. The plan only prints before the first step
urllib.error.HTTPError: HTTP Error 404: Not FoundThe model isn’t downloaded. Run ollama pull llama3.2:3b
The script seems to hangIt’s waiting for your answer to Allow this change? Type y or n and press Enter

Interview questions

Click a question to open it. Under each one you’ll find what the interviewer is actually looking for, and one good way to answer.

Fresher level

1. What are the main components of an AI agent?

What they’re really checking: Can you name the parts beyond the model?

How you could answer: The model, the instructions or system prompt, the tools, memory, planning and guardrails. The code loop joins them: it builds the prompt, runs tools and enforces limits.

2. What’s the difference between short-term and long-term memory in an agent?

What they’re really checking: Do you know where each lives?

How you could answer: Short-term memory is the conversation for the current task, held in the messages list and limited by the context window. Long-term memory is stored outside the model, in a file or database, and loaded into future prompts.

3. Why would an agent write a plan before acting?

What they’re really checking: Do you see the value and the limits?

How you could answer: A plan breaks a big job into steps, keeps the agent on task and lets it batch tool calls. It’s still only text, so the agent should change the plan when results surprise it.

2–5 years experience

4. How would you design long-term memory for a support agent?

What they’re really checking: Do you think about write policies?

How you could answer: Store notes with a source, date, scope and expiry. Approve notes before they become active, and load only notes that match the task, often by searching with embeddings. Validate the store on load and log which notes were used for each answer.

5. An agent gives a wrong fix confidently. How do you find the cause?

What they’re really checking: Can you debug by component?

How you could answer: Read the trace and check each component. Were the instructions clear, did the tools return the right data, was a memory note loaded, did the plan fit? Often the cause is stale memory or a misleading tool result, not the model.

6. Where do guardrails belong: in the prompt or in code?

What they’re really checking: Do you know which controls are enforceable?

How you could answer: Rules in the prompt guide the model, but it can ignore them. Anything that must hold, such as approvals, step limits, permissions and argument checks, belongs in code, with the prompt explaining it.

Senior level

7. How do you stop an agent’s memory from being poisoned?

What they’re really checking: Do you treat memory as an attack surface?

How you could answer: Only trusted sources can write to memory, and new notes are reviewed. Notes carry provenance and expiry, memory is treated as data and never as instructions, and actions based on a note must be confirmed with a check. I’d also audit and be able to roll back the memory store.

8. How do you choose the model for an agent?

What they’re really checking: Do you weigh more than benchmark scores?

How you could answer: I test candidate models on our own agent scenarios: tool-call accuracy, following rules, context size, latency and cost per task. A smaller, faster model with good tools and memory often beats a larger model with poor ones.

9. What would you log for an agent in production?

What they’re really checking: Do you design for observability?

How you could answer: Every model call with its prompt size, every tool call with arguments and result, which memory notes were loaded, approvals and their answers, and the final answer. Each run gets an ID, so I can replay a bad run and add it to the eval set.

Quick quiz

Q1. In the lab, where does the agent’s long-term memory live?

  1. Inside the model’s weights
  2. In memory.json, loaded into the system prompt
  3. In Ollama’s cache
Show answer

B — The model doesn’t change. Your code stores notes in a file and puts them into the prompt.

Q2. Why did the agent fix printing in one step on the second run?

  1. It was a bigger model
  2. A memory note told it the likely fix
  3. The step limit was lower
Show answer

B — The note was in the system prompt, so it went straight to the restart.

Q3. What did the planning step change in the “check every server” run?

  1. It made the model skip tools
  2. It kept the agent on task and let it ask for several tools at once
  3. It removed the need for approval
Show answer

B — Seven checks took only three model calls, and it reported instead of restarting.

Q4. One missing comma in memory.json stopped the agent. What’s the lasting lesson?

  1. Never use JSON
  2. Validate memory on load and handle errors
  3. Disable memory
Show answer

B — Memory is outside input. Check it, warn, and keep working safely.

Q5. The stale note made the agent restart a running spooler. What fixed it?

  1. Deleting all memory
  2. Treating notes as hints and checking the current state first
  3. A higher temperature
Show answer

B — Notes describe the past. The agent must confirm before it acts.

Quick recap

  • AI agent architecture = model, instructions, tools, memory, planning and guardrails, joined by your loop.
  • Short-term memory is the messages list; long-term memory is stored outside and loaded into the prompt.
  • Memory needs a write policy: what to save, who approves, and when it expires.
  • Notes are hints. Check the current state before acting on them.
  • Planning keeps an agent on task; guardrails belong in code.
  • When an agent fails, find the component that failed before changing the model.

Next lesson

Multi-agent systems → One agent with five tools is manageable. In the last lesson of the course, several agents with different jobs work together, and you’ll see when that helps and when one agent is the better choice.

Further reading: AI agent architecture

Want to go deeper into AI agent architecture? Read Building effective agents from Anthropic and the survey A Survey on Large Language Model based Autonomous Agents (Wang et al., 2023). You can also follow the full Generative AI and Agents course on SaatVedha, step by step.

Scroll to Top