Agentic AI

Foundations Of Agentic AI

Classical Agent Types, Reframed

The AI Notes present five classical agent types. They predate LLMs by decades, and they map onto modern systems precisely — because they classify by what inform

JrCodex·7 min read

Jr Codex Agentic AI Notes

Level: Beginner–Intermediate Prerequisites: Chapter 2: What Makes a System Agentic; AI Notes, Module 5, Chapter 1 Time to complete: ~20 minutes


Table of Contents

  1. Why an Old Taxonomy Still Earns Its Place
  2. Simple Reflex Agents
  3. Model-Based Reflex Agents
  4. Goal-Based Agents
  5. Utility-Based Agents
  6. Learning Agents
  7. Diagnosing Your Own System
  8. Summary & Next Steps

1. Why an Old Taxonomy Still Earns Its Place

The AI Notes present five classical agent types. They predate LLMs by decades, and they map onto modern systems precisely — because they classify by what information the agent uses to decide, which is independent of what technology does the deciding.

The Organising Axis
─────────────────────────────────────────
  Each type adds ONE thing the previous lacked:

  Reflex          current input only
  Model-based     + internal state (memory)
  Goal-based      + a target and lookahead
  Utility-based   + a way to RANK outcomes
  Learning        + improvement from experience
─────────────────────────────────────────

The practical payoff: when an agent misbehaves, this taxonomy usually names the missing capability.


2. Simple Reflex Agents

Classical                    Modern equivalent
─────────────────────────────────────────
  condition-action rules      a single LLM call with
  on the current percept      no history and no tools
─────────────────────────────────────────
def classify_ticket(client, text):
    """A reflex agent. Same input ──► same response. No state, no goal."""
    return client.chat.completions.create(
        model="gpt-4o-mini", temperature=0,
        messages=[{"role": "system", "content": "Reply with exactly one of: "
                                                "BILLING, TECHNICAL, REFUND."},
                  {"role": "user", "content": text}],
    ).choices[0].message.content.strip()
The Characteristic Failure
─────────────────────────────────────────
  A reflex agent cannot handle anything requiring
  what came BEFORE. Ask it "what about the second
  one?" and it has no idea what the first was.

  Levels 1-2 on Chapter 2's spectrum. Fast, cheap,
  testable, and correct for a large share of real
  tasks.
─────────────────────────────────────────

3. Model-Based Reflex Agents

Adds an internal representation of the world that persists across steps.

Classical                    Modern equivalent
─────────────────────────────────────────
  maintains internal state     conversation history,
  to handle partial            scratchpad, or a
  observability                working-memory object
─────────────────────────────────────────
class ModelBasedAgent:
    def __init__(self, client):
        self.client, self.state = client, {}          # the internal MODEL of the world
 
    def step(self, observation):
        self.state.update(extract_facts(observation))  # update what is believed
        return self.client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "system", "content": f"Known state: {self.state}"},
                      {"role": "user", "content": observation}],
        ).choices[0].message.content
The Key Insight for LLM Agents
─────────────────────────────────────────
  The conversation history IS the world model, and
  it is the ONLY one most agents have.

  This is why memory is not a nice-to-have feature
  but the difference between two agent classes —
  and why Module 3 treats it as foundational rather
  than as an optimisation.
─────────────────────────────────────────

4. Goal-Based Agents

Adds an explicit target and the ability to consider whether an action moves toward it.

Classical                    Modern equivalent
─────────────────────────────────────────
  searches ahead for action    the ReAct loop —
  sequences reaching a goal    "have I achieved the
                               goal, or is another
                               action needed?"
─────────────────────────────────────────
def goal_based_agent(client, goal, tools, max_steps=10):
    messages = [{"role": "system", "content":
                 f"GOAL: {goal}\nAt each step, state whether the goal is met. "
                 f"If not, take the action that best advances it."},
                {"role": "user", "content": "Begin."}]
 
    for _ in range(max_steps):
        reply = client.chat.completions.create(
            model="gpt-4o", messages=messages, tools=tools.schemas).choices[0].message
        if not reply.tool_calls:
            return reply.content                       # the model judged the GOAL MET
        messages.append(reply)
        for call in reply.tool_calls:
            messages.append({"role": "tool", "tool_call_id": call.id,
                             "content": str(tools.run(call))})
    return None
The Distinguishing Property
─────────────────────────────────────────
  A goal-based agent can evaluate its own progress.
  It has a notion of "not done yet" that a reflex
  agent structurally lacks.

  This is the threshold at which a system becomes an
  agent in the ordinary sense — level 4 on the
  spectrum.
─────────────────────────────────────────

5. Utility-Based Agents

Adds preference: not merely whether the goal is met, but how well, so competing options can be ranked.

Classical                    Modern equivalent
─────────────────────────────────────────
  maximises a utility          explicit trade-off
  function over outcomes       criteria in the prompt,
                               or a scoring function
                               over candidate plans
─────────────────────────────────────────
UTILITY = """When choosing among approaches, rank by:
  1. Correctness   — a wrong answer has NEGATIVE value
  2. Cost          — prefer one cheap tool call over five
  3. Latency       — prefer fast paths when quality is comparable
Explicitly state the trade-off you are making before acting."""
 
def utility_based_agent(client, goal, tools):
    messages = [{"role": "system", "content": f"GOAL: {goal}\n\n{UTILITY}"}, ...]
    # ... same loop; what changed is that the model now has a basis for CHOOSING
Where This Matters in Practice
─────────────────────────────────────────
  Most real agents face several valid routes to the
  same goal: search the web, query the database, or
  ask the user. All three "work".

  Without stated preferences, the model picks
  arbitrarily — and arbitrary usually means the most
  expensive option, because thoroughness reads as
  helpfulness.

  Writing down the trade-offs is the cheapest
  intervention in this entire curriculum.
─────────────────────────────────────────

6. Learning Agents

Adds improvement from experience.

Classical                    Modern equivalent
─────────────────────────────────────────
  a learning element that      three distinct things,
  improves the performance     often confused:
  element from feedback
─────────────────────────────────────────
The Three Kinds of "Learning"
─────────────────────────────────────────
  WITHIN A RUN       reflection — critique and revise
                     the current attempt.
                     Module 4, Chapter 3.
                     Nothing persists.

  ACROSS RUNS        write outcomes to long-term
                     memory and retrieve them later.
                     Module 3, Chapter 3.
                     This is where most practical
                     "learning" lives.

  IN THE WEIGHTS     fine-tuning on collected
                     trajectories.
                     NLP Notes, Module 6. Rare for
                     agents — expensive, slow, and
                     usually beaten by better memory.
─────────────────────────────────────────
class LearningAgent:
    """Learns ACROSS runs by recording outcomes and retrieving similar past cases."""
    def __init__(self, client, memory): self.client, self.memory = client, memory
 
    def run(self, task):
        lessons = self.memory.search(task, k=3)        # what happened on similar tasks
        result = self.execute(task, prior=lessons)
        self.memory.add(task=task, outcome=result.outcome,
                        lesson=result.what_worked)     # write it back for NEXT time
        return result

7. Diagnosing Your Own System

The taxonomy's real use is diagnostic. Match the symptom to the missing capability.

Symptom                        Missing Capability
─────────────────────────────────────────
  "It forgets what we           internal state
   discussed two turns ago"     ──► model-based (Mod.3)

  "It answers, but never        a goal and a
   checks whether it            completion test
   actually finished"           ──► goal-based

  "It always picks the          a utility function
   slowest, most expensive      ──► utility-based
   route"                       (Section 5)

  "It makes the same mistake    learning across runs
   every single time"           ──► Module 3, Ch.3

  "It retries the identical     adaptability
   failing action forever"      ──► Module 4, Ch.4
─────────────────────────────────────────
The Reframe Worth Keeping
─────────────────────────────────────────
  These are not five architectures to choose
  between. They are five capabilities that ACCUMULATE.

  A production agent is usually all five at once:
  reflex for classification, model-based for memory,
  goal-based for the loop, utility-based for choosing
  tools, learning through stored outcomes.

  When one is missing, this table tells you which.
─────────────────────────────────────────

8. Summary & Next Steps

Key Takeaways

  • The classical taxonomy classifies by what information drives the decision, so it maps cleanly onto LLM agents despite predating them.
  • Each type adds exactly one capability: internal state, then a goal, then a way to rank outcomes, then improvement from experience.
  • For LLM agents the conversation history is the world model, which is why memory separates two agent classes rather than being an optimisation.
  • Without stated trade-offs an agent chooses arbitrarily among valid routes, usually the most expensive — writing down utility criteria is the cheapest available fix.

Concept Check

  1. Why does the classical taxonomy still apply to systems built on a technology that did not exist when it was written?
  2. An agent completes tasks correctly but always uses the slowest tool available. Which capability is missing, and what is the fix?
  3. Distinguish the three kinds of learning available to an agent, and say which is most practical and why.

Next Chapter

Chapter 4: Anatomy of an Agent


Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index | Back to Agentic AI Index