TechByteByByte

GenAI + Agents

Revisiting agentic AI from the Prompt Engineering course, now framed through this course's complete generative modeling picture: autoregressive generation, sampling, tool use, and layered application architecture.

#Generative AI#AI#Agents#Level 6

Start with the simple idea

An AI agent is a model inside an application loop that can inspect information, choose a tool or step, observe the result, and continue or stop.

Simple learning path: problem → intuition → mechanism → example → limits

What you will learn

  • Explain GenAI + Agents in plain language.
  • Follow its mechanism step by step.
  • Connect a small example to a real AI system.
  • Recognize its strengths, limits, and common mistakes.

How this appears in current AI systems

Current agent systems place GPT, Gemini, Claude, or open models inside tool-using loops. The application, not the model, executes tools and enforces permissions, budgets, and approvals.

Official grounding: OpenAI documents function calling, Google documents Gemini tools, and Hugging Face documents model deployment options. These sources ground the application patterns while showing that API details are provider-specific.

When this knowledge helps

Use GenAI + Agents when it matches the problem described below. Before choosing it, check the task, available data, quality target, cost, response time, privacy, and safety needs; popularity alone is not a reason to use it.

1. The question this module answers

Agentic AI was covered practically in your Prompt Engineering course. This module revisits it through everything covered in THIS course — showing that an agent is really just a foundation model (Module 20), generating text autoregressively (Module 6), orchestrated by application logic (Module 23), often combined with RAG (Module 28) — not a fundamentally separate kind of AI system.


2. What an Agent Really Is, Mechanically

An "agent" = a foundation model (Module 20), given:
   1. A system prompt defining its ROLE and available TOOLS
   2. A LOOP: generate a response -> check if it wants to use a
      tool -> if so, EXECUTE the tool -> feed the RESULT back as
      context -> generate again -> repeat until a final answer is
      reached
User request

Model generates a response (autoregressive generation, Module 6) --
this response may include a request to use a TOOL

IF a tool is requested: application logic (Module 23) EXECUTES the
                        tool, gets a RESULT

Tool result is fed back into the CONTEXT (Module 12's conditioning
idea, directly) -- the model's NEXT generation is conditioned on
this new information

Model generates AGAIN, now informed by the tool result -- may
request ANOTHER tool, or may produce a FINAL answer

Repeat until the task is complete

This entire loop is built ENTIRELY from mechanisms you’ve already studied: autoregressive generation (Module 6), sampling (Module 10), conditioning on context (Module 12), and application orchestration (Module 23). “Agentic AI” doesn’t require a fundamentally different kind of model — it’s a specific way of ORCHESTRATING a foundation model’s existing generative capability.


3. Why This Reframing Really Matters

Understanding an agent as “a foundation model in a loop” rather than “a fundamentally different technology” has real, practical consequences:

- Every LIMITATION covered throughout this course (hallucination,
  Module 32; sampling variability, Module 10; cost compounding
  across calls, Module 27) applies DIRECTLY to agents too -- an
  agent doesn't magically escape these limitations just by being
  "agentic"

- Every latency consideration from Module 25 COMPOUNDS across an
  agent's multiple sequential generation calls -- a really real,
  structural reason multi-step agent tasks take noticeably longer
  than single-turn interactions

- The alignment training covered in Module 22 is DIRECTLY why an
  agent can be trusted to follow its system prompt's defined role
  and constraints reliably enough to be given real tool access

4. Tool Use — Extending the Model’s Generation With Real Actions

Without tools: the model can ONLY generate text -- it has no way to
              check current information, perform calculations
              reliably, or take real actions in the world

With tools: the model can REQUEST that a specific function/API be
           called (still, at the mechanical level, generating TEXT
           describing which tool and what parameters -- Module 18's
           code generation, applied to structured tool-call
           parameters specifically), and the RESULT is fed back as
           new context

This directly connects to Module 18’s code generation discussion: generating a tool call with correct parameters is really a code- generation-like task — structured, syntax-sensitive output that benefits from the same low-temperature, consistency-focused sampling strategy (Module 10) that structured code generation benefits from.


5. Multi-Step Reasoning — Chaining Generations Together

Complex task: "Find our top-selling product last month, then draft
             a social media post celebrating it"

Step 1: model generates a request to use a "query sales data" tool
Step 2: tool executes, returns the result (e.g., "Wireless
        Headphones Pro")
Step 3: this result is fed back as context; model generates a
        request to use a "draft social post" reasoning step,
        OR directly generates the post text, now GROUNDED in the
        actual retrieved sales data (exactly Module 28's RAG
        grounding mechanism, applied within an agent loop)
Step 4: final response delivered to the user

This multi-step chaining is really the same “chain multiple generations together” pattern from Module 1’s opening example (predictive step feeding a generative step) — an agent loop is simply a more general, extended, and often longer version of that same idea.

Analogy: The General Contractor Coordinating Subcontractors Think of a GenAI agent like a general contractor hired to renovate a kitchen:

  • The Goal (User Request): The homeowner says: “Update my kitchen layout.”
  • The Contractor (The LLM Agent): The contractor does not start hammering walls immediately. They sit down, draft a plan, write tasks on a clipboard (Plan / State tracking), and decide which specialists to hire (tool selection).
  • The Subcontractors (Tools):
    • The contractor calls the plumber (plumbing API tool) to check the sink drain.
    • The plumber reports back: “The pipe is rusted and needs replacement” (Observation / Tool output).
  • Observation & Reflection: The contractor writes this info on their clipboard. They revise their plan based on the plumber’s info: “Now I must buy a new copper pipe before the electrician starts.”
  • They repeat this loop of planning, directing, observing, and reflecting until the kitchen is completed.

📊 Visual Flowchart: The ReAct Agent Planning-Execution Loop

Here is how an agent iterates through reasoning steps, tool calls, and observations:

graph TD
    classDef llm fill:#3498db,stroke:#333,stroke-width:1px,color:#fff;
    classDef tool fill:#e67e22,stroke:#333,stroke-width:1px,color:#fff;
    classDef obs fill:#2ecc71,stroke:#333,stroke-width:1px,color:#fff;

    StartGoal["User Input Goal:<br>'Fix bug X in main.py'"] --> AgentThink["1. Thought / Planning Stage:<br>(LLM decides what tool to use)"]:::llm

    AgentThink --> ToolCall["2. Action Stage:<br>(Generate structured tool-call string)"]:::llm

    ToolCall --> ToolExec["3. Tool Execution Stage:<br>(Run shell command / API query)"]:::tool

    ToolExec --> ObsReport["4. Observation Stage:<br>(Capture error code / database return)"]:::obs

    ObsReport --> AppendHistory["5. Append Observation to Context history"]:::obs

    AppendHistory --> CheckDone{"6. Is goal accomplished?"}

    CheckDone -->|No: Reflect & continue| AgentThink
    CheckDone -->|Yes: final reply| FinalOut["Output final solution to User"]:::llm

6. A Real Developer Example

Building a coding agent that can read a codebase, identify a bug, and
propose a fix:

1. Agent generates a request to use a "read file" tool
2. Tool executes, returns file contents
3. Fed back as context; agent GENERATES an analysis of the bug
   (autoregressive text generation, Module 6, grounded in the
   ACTUAL file content -- Module 28's grounding principle, applied)
4. Agent generates CODE for a proposed fix (Module 18's code
   generation, directly)
5. Per Module 18's Section 6 warning: this generated code should be
   RUN AGAINST TESTS (Module 18's responsible workflow) before being
   trusted or automatically applied

Every step here is a DIRECT application of a mechanism from earlier
in this course -- there is really nothing "extra" or separately
mysterious about how the agent works, beyond the orchestration loop
itself.

7. Constraints on Autonomous Action — A Direct Safety Connection

This connects directly to your Prompt Engineering course’s Module 19, and to Module 33 of this course:

An agent that can take REAL actions (not just generate text) carries
GENUINE risk -- exactly Module 18's Section 6 warning about
generated code, but now extended to ANY tool an agent might invoke.

Responsible agent design REQUIRES:
   - Sandboxed/isolated execution for anything potentially risky
   - Human review/approval for really consequential actions
   - Clear, EXPLICIT boundaries on what the agent is authorized to
     do autonomously vs. what requires confirmation

8. How Is This Used in AI?

🤖 How Is This Used in AI?

Agentic AI powers coding assistants that can read, write, and test code; research assistants that can search, retrieve, and synthesize information; and increasingly sophisticated automation across countless domains — all built by orchestrating a foundation model’s generative capability (Module 20) through the loop covered in this module, combined with RAG (Module 28), tool use, and careful alignment-dependent trust (Module 22).


9. Real-World Applications

  • Coding agents (read, analyze, write, test code)
  • Research and information-gathering agents
  • Customer service agents with real system access (checking order status, processing returns)
  • Multi-step workflow automation

10. Common Mistakes

Incorrect idea

Treating agentic AI as a fundamentally different technology from everything else covered in this course.

Why it is incorrect

As shown directly, it’s built entirely from mechanisms already covered — autoregressive generation, conditioning, and application orchestration.

Incorrect idea

Assuming agents escape earlier limitations (hallucination, sampling variability) simply by being “agentic.”

Why it is incorrect

As emphasized directly in Section 3, every limitation covered throughout this course applies directly to agents too.

Incorrect idea

Granting an agent broad autonomous action without genuine safeguards.

Why it is incorrect

As shown directly in Section 7, this carries real risk — sandboxing, review, and explicit boundaries are really necessary, not optional extras.


11. Limitations

  • Agent reliability is fundamentally bounded by the underlying foundation model’s capability and alignment quality (Modules 20, 22) — an agent loop doesn’t add capability the base model doesn’t really have
  • Multi-step agent tasks compound both latency (Module 25) and cost (Module 27) across each sequential generation and tool call
  • Agent behavior, like any generative output, isn’t perfectly predictable — genuine testing and safeguards (Section 7) remain necessary regardless of how capable the underlying model is

12. Quick Reference — The Whole Idea in One Diagram

Agent = foundation model (Module 20) + system prompt (role, tools) +
       ORCHESTRATION LOOP (Module 23's application logic)

Loop:      generate -> [tool requested? execute -> feed result back
                       as context] -> generate again -> repeat until
                       done

Built ENTIRELY from mechanisms already covered:      autoregressive
                                                    generation
                                                    (Module 6),
                                                    conditioning
                                                    (Module 12),
                                                    grounding (RAG,
                                                    Module 28), code
                                                    generation
                                                    (Module 18)

13. Code — A Complete, Minimal Agent Loop

🎯 Target of this example: implement Section 2’s full agent loop directly and observably — a model deciding to use a tool, the tool executing, and the result feeding back into context for a final, grounded response — making the “agent = model + orchestration loop” framing from Section 2 concrete and runnable.

Example 1 — Simple

import anthropic

client = anthropic.Anthropic()

def get_current_stock_price(ticker: str) -> str:
    """A MOCK tool -- stands in for a real API call."""
    prices = {"ACME": "$142.50", "TECHCO": "$88.20"}
    return prices.get(ticker, "Unknown ticker")

tools = [{
    "name": "get_current_stock_price",
    "description": "Get the current stock price for a given ticker symbol.",
    "input_schema": {
        "type": "object",
        "properties": {"ticker": {"type": "string", "description": "Stock ticker symbol"}},
        "required": ["ticker"],
    },
}]

response = client.messages.create(
    model="claude-sonnet-4-6", max_tokens=200, tools=tools,
    messages=[{"role": "user", "content": "What's the current price of ACME stock?"}]
)

for block in response.content:
    if block.type == "tool_use":
        print(f"Model requested tool: {block.name} with input: {block.input}")
    elif block.type == "text":
        print(f"Model text: {block.text}")

Expected Output:

Model requested tool: get_current_stock_price with input: {'ticker':
'ACME'}

What we conclude from this example: the model, generating text autoregressively, produced a structured TOOL REQUEST rather than a plain text answer — exactly Module 18’s structured code-generation-like output, applied to tool calling. This is Step 1 of Section 2’s loop, observed directly.

Example 2 — Intermediate

import anthropic

client = anthropic.Anthropic()

def get_current_stock_price(ticker: str) -> str:
    prices = {"ACME": "$142.50", "TECHCO": "$88.20"}
    return prices.get(ticker, "Unknown ticker")

tools = [{
    "name": "get_current_stock_price",
    "description": "Get the current stock price for a given ticker symbol.",
    "input_schema": {
        "type": "object",
        "properties": {"ticker": {"type": "string"}},
        "required": ["ticker"],
    },
}]

def run_agent_loop(user_message: str) -> str:
    """Implements the FULL loop from Section 2: generate -> check
    for tool request -> execute -> feed result back -> generate
    final answer."""
    messages = [{"role": "user", "content": user_message}]

    response = client.messages.create(
        model="claude-sonnet-4-6", max_tokens=200, tools=tools, messages=messages
    )

    if response.stop_reason == "tool_use":
        tool_use_block = next(b for b in response.content if b.type == "tool_use")
        tool_result = get_current_stock_price(tool_use_block.input["ticker"])

        # Feed the tool result back as CONTEXT (Module 12's conditioning,
        # applied directly) for the model's NEXT generation.
        messages.append({"role": "assistant", "content": response.content})
        messages.append({"role": "user", "content": [
            {"type": "tool_result", "tool_use_id": tool_use_block.id, "content": tool_result}
        ]})

        final_response = client.messages.create(
            model="claude-sonnet-4-6", max_tokens=200, tools=tools, messages=messages
        )
        return final_response.content[0].text

    return response.content[0].text

result = run_agent_loop("What's the current price of ACME stock?")
print(result)

Expected Output:

The current price of ACME stock is $142.50.

What we conclude from this example: the final answer is GROUNDED in the actual tool result ($142.50), not a guess from the model’s training data — this is precisely Section 5’s grounding mechanism, now demonstrated end-to-end: the model requests a tool, the tool executes, the result becomes context, and the final generation is conditioned on that real, current data.

Example 3 — Production Grade

import anthropic
from dataclasses import dataclass, field

client = anthropic.Anthropic()

@dataclass
class AgentStep:
    step_number: int
    action: str
    details: str

@dataclass
class AgentRunResult:
    final_answer: str
    steps: list = field(default_factory=list)
    total_tool_calls: int = 0

def get_current_stock_price(ticker: str) -> str:
    prices = {"ACME": "$142.50", "TECHCO": "$88.20"}
    return prices.get(ticker, "Unknown ticker")

TOOLS = [{
    "name": "get_current_stock_price",
    "description": "Get the current stock price for a given ticker symbol.",
    "input_schema": {"type": "object", "properties": {"ticker": {"type": "string"}}, "required": ["ticker"]},
}]

def run_agent_with_logging(user_message: str, max_steps: int = 5) -> AgentRunResult:
    """A production-style agent loop with EXPLICIT step logging and a
    max_steps SAFETY LIMIT -- directly implementing Section 7's
    'constraints on autonomous action' principle: an agent should
    never be allowed to loop indefinitely without bound."""
    messages = [{"role": "user", "content": user_message}]
    steps = []
    tool_call_count = 0

    for step_num in range(max_steps):
        response = client.messages.create(
            model="claude-sonnet-4-6", max_tokens=200, tools=TOOLS, messages=messages
        )

        if response.stop_reason == "tool_use":
            tool_use_block = next(b for b in response.content if b.type == "tool_use")
            tool_result = get_current_stock_price(tool_use_block.input["ticker"])
            tool_call_count += 1

            steps.append(AgentStep(
                step_number=step_num + 1, action="tool_call",
                details=f"{tool_use_block.name}({tool_use_block.input}) -> {tool_result}"))

            messages.append({"role": "assistant", "content": response.content})
            messages.append({"role": "user", "content": [
                {"type": "tool_result", "tool_use_id": tool_use_block.id, "content": tool_result}
            ]})
        else:
            steps.append(AgentStep(step_number=step_num + 1, action="final_answer",
                                    details=response.content[0].text))
            return AgentRunResult(final_answer=response.content[0].text,
                                   steps=steps, total_tool_calls=tool_call_count)

    return AgentRunResult(final_answer="Max steps reached without a final answer.",
                           steps=steps, total_tool_calls=tool_call_count)

result = run_agent_with_logging("What's the current price of ACME stock?")
print(f"Final answer: {result.final_answer}")
print(f"Total tool calls: {result.total_tool_calls}")
print("Step log:")
for step in result.steps:
    print(f"  [{step.step_number}] {step.action}: {step.details}")

Expected Output:

Final answer: The current price of ACME stock is $142.50.
Total tool calls: 1
Step log:
  [1] tool_call: get_current_stock_price({'ticker': 'ACME'}) ->
  $142.50
  [2] final_answer: The current price of ACME stock is $142.50.

What we conclude from this example: the max_steps safety limit and explicit step logging directly implement Section 7’s real safety principle — preventing an agent from looping indefinitely, and providing a genuine audit trail of every action taken. This is exactly the kind of responsible engineering discipline a production agent system needs, on top of the same core loop mechanism from Section 2.


14. Interview Questions

Q: Explain, mechanically, what an “agent” actually is, using concepts from earlier in this course.

Ans: An agent is a foundation model given a system prompt defining its role and available tools, orchestrated through a loop: the model generates a response (using ordinary autoregressive generation), the application logic checks whether the response requests a tool, if so the tool is executed and its result is fed back as new context (exactly the conditioning mechanism from Module 12), and the model generates again, informed by that new information. This repeats until a final answer is reached. It’s built entirely from mechanisms already covered in this course — there’s no fundamentally new model type involved, only a specific orchestration pattern.

Q: Why is it important to recognize that agentic AI doesn’t escape the limitations covered earlier in this course, like hallucination and sampling variability?

Ans: Because an agent is fundamentally a foundation model generating text autoregressively, every limitation that applies to that underlying generation process applies directly to the agent too — hallucination risk, sampling variability, and cost/latency compounding across sequential calls don’t disappear simply because the system is “agentic.” Recognizing this prevents overconfidence in agent reliability and reinforces the need for the same kinds of safeguards (grounding via RAG, validation, testing) that apply to any generative system.

Q: How does tool use extend a model’s capability beyond pure text generation, and what mechanism from earlier in this course does generating a tool call resemble?

Ans: Tool use lets a model request that a specific function or API be called, with the result fed back into context, extending the model’s capability beyond generating text alone to effectively taking real actions or retrieving real, current information. Mechanically, generating a tool call with correctly structured parameters closely resembles code generation (Module 18) — it’s structured, syntax- sensitive output, which is why it typically benefits from the same low-temperature, consistency-focused sampling strategy that structured code generation benefits from.

Q: Why does a production agent system need explicit constraints like a maximum step limit, and what real risk does this address?

Ans: Without an explicit bound, an agent could theoretically loop indefinitely — repeatedly requesting tools or generating further steps without ever reaching a final, useful answer — consuming unbounded time and cost (Module 25, 27) with no guarantee of resolution. A maximum step limit is a genuine, practical safeguard, directly connecting to the broader principle that agents capable of autonomous action need explicit, deliberate constraints rather than open-ended trust in the model to always behave and terminate as expected.


15. What You Should Remember

  • An agent is really a foundation model orchestrated through a loop — generate, check for tool requests, execute, feed results back as context, repeat — built entirely from mechanisms already covered in this course.
  • Agents do not escape earlier limitations — hallucination, sampling variability, and cost/latency compounding all apply directly, verified through a complete, working agent loop example.
  • Constraints on autonomous action (sandboxing, review, explicit step limits) are really necessary for responsible agent design — verified directly with a production-style implementation including a max-step safety limit and full action logging.

16. Quick Practice

Design a simple agent loop (in words, not code) for a task like “check the weather and suggest what to wear” — identify each step in Section 2’s loop (generate, tool request, tool execution, context feedback, final generation) as it would apply to this specific task.

17. Next Step

Next: Module 30 — GenAI + Prompt Engineering & Context Engineering — closing Level 6: directly connecting your entire Prompt Engineering course to everything covered in this course’s generative modeling framework.

Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed