Lesson 5.1: What is an AI Agent
Duration: 45 minutes
Learning Objectives
By the end of this lesson, you will be able to:
- Define what an AI agent is and how it differs from a chatbot
- Identify the core components of an agent system
- Understand the agent loop and how agents make decisions
- Recognize different agent architectures and their trade-offs
From Chatbots to Agents
In previous modules, you built chatbots and AI systems that respond to queries. These systems follow a simple pattern:
User Question → AI Response
This works well for single-turn interactions, but falls short for complex tasks that require:
- Multiple steps to complete
- Gathering information from different sources
- Making decisions based on intermediate results
- Adapting to unexpected situations
AI Agents extend this model by adding autonomy. An agent does not just respond to queries - it works toward goals, makes decisions, uses tools, and adapts its approach based on results.
What Makes an Agent
An AI agent has four defining characteristics:
1. Autonomy
Agents operate independently. Given a goal, they decide what steps to take without requiring human input for each action.
2. Perception
Agents observe their environment. This includes reading tool outputs, processing user messages, and understanding context.
3. Reasoning
Agents think about what to do next. They analyze information, consider options, and make decisions.
4. Action
Agents take actions to achieve goals. They call tools, generate responses, and interact with external systems.
The Agent Loop
Every agent follows a continuous loop:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────┐ │
│ │ Perceive │ ← Observe environment, read inputs │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Think │ ← Analyze situation, plan next step │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Act │ ← Execute tool or generate response │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Evaluate │ ← Check if goal is achieved │
│ └──────┬───────┘ │
│ │ │
│ ├─── Goal achieved? ─── Yes ──▶ Return result │
│ │ │
│ └─── No ──▶ Loop back to Perceive │
│ │
└─────────────────────────────────────────────────────────────────┘
This loop continues until the agent determines it has achieved its goal or cannot proceed further.
Agent vs Chatbot Comparison
| Aspect | Chatbot | Agent |
|---|---|---|
| Interaction | Single turn | Multi-turn, autonomous |
| Decision Making | None | Plans and decides |
| Tool Use | Optional, user-triggered | Autonomous |
| State | Stateless or simple history | Rich state with memory |
| Goal Handling | Responds to queries | Works toward objectives |
| Error Recovery | Returns error message | Retries, adapts approach |
Core Components of an Agent
A complete agent system consists of these components:
1. Language Model (Brain)
The LLM provides reasoning capabilities. It interprets inputs, generates plans, and decides which actions to take.
interface AgentBrain {
think(context: string): Promise<AgentThought>;
decide(options: Action[]): Promise<Action>;
}
2. Tools (Capabilities)
Tools extend what the agent can do. They provide access to external systems, APIs, and functionality.
interface Tool {
name: string;
description: string;
execute(input: unknown): Promise<unknown>;
}
3. Memory (Context)
Memory stores conversation history, intermediate results, and learned information.
interface AgentMemory {
shortTerm: Message[]; // Recent conversation
workingMemory: Record<string, unknown>; // Current task state
longTerm?: VectorStore; // Persistent knowledge
}
4. Executor (Action Handler)
The executor runs tools and manages the agent loop.
interface AgentExecutor {
run(goal: string): Promise<AgentResult>;
step(): Promise<StepResult>;
}
Building a Simple Agent
Here is a minimal agent implementation to illustrate the concepts:
import OpenAI from 'openai';
interface Tool {
name: string;
description: string;
parameters: Record<string, unknown>;
execute: (args: Record<string, unknown>) => Promise<string>;
}
interface AgentConfig {
model: string;
systemPrompt: string;
tools: Tool[];
maxIterations: number;
}
class SimpleAgent {
private client: OpenAI;
private config: AgentConfig;
private messages: OpenAI.Chat.ChatCompletionMessageParam[] = [];
constructor(client: OpenAI, config: AgentConfig) {
this.client = client;
this.config = config;
this.messages = [{ role: 'system', content: config.systemPrompt }];
}
async run(goal: string): Promise<string> {
this.messages.push({ role: 'user', content: goal });
for (let i = 0; i < this.config.maxIterations; i++) {
const response = await this.think();
// Check if agent wants to use a tool
if (response.tool_calls && response.tool_calls.length > 0) {
await this.executeTools(response.tool_calls);
} else {
// Agent is done - return final response
return response.content || 'Task completed.';
}
}
return 'Max iterations reached without completing the task.';
}
private async think(): Promise<OpenAI.Chat.ChatCompletionMessage> {
const response = await this.client.chat.completions.create({
model: this.config.model,
messages: this.messages,
tools: this.config.tools.map((tool) => ({
type: 'function' as const,
function: {
name: tool.name,
description: tool.description,
parameters: tool.parameters,
},
})),
});
const message = response.choices[0].message;
this.messages.push(message);
return message;
}
private async executeTools(
toolCalls: OpenAI.Chat.ChatCompletionMessageToolCall[]
): Promise<void> {
for (const toolCall of toolCalls) {
const tool = this.config.tools.find((t) => t.name === toolCall.function.name);
if (!tool) {
this.messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: `Error: Tool ${toolCall.function.name} not found`,
});
continue;
}
try {
const args = JSON.parse(toolCall.function.arguments);
const result = await tool.execute(args);
this.messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: result,
});
} catch (error) {
this.messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: `Error executing tool: ${error}`,
});
}
}
}
}
Using the Simple Agent
Here is how to use the agent with a calculator tool:
import OpenAI from 'openai';
const client = new OpenAI();
// Define a calculator tool
const calculatorTool: Tool = {
name: 'calculator',
description: 'Performs mathematical calculations. Use for any math operations.',
parameters: {
type: 'object',
properties: {
expression: {
type: 'string',
description: "The mathematical expression to evaluate, e.g., '2 + 2' or '15 * 7'",
},
},
required: ['expression'],
},
execute: async (args) => {
const { expression } = args as { expression: string };
try {
// Simple eval for demo - use a proper math parser in production
const result = Function(`"use strict"; return (${expression})`)();
return `Result: ${result}`;
} catch {
return `Error: Could not evaluate "${expression}"`;
}
},
};
// Create and run the agent
const agent = new SimpleAgent(client, {
model: 'gpt-4o',
systemPrompt: `You are a helpful assistant that can perform calculations.
When asked to do math, use the calculator tool.
After getting a result, explain it clearly to the user.`,
tools: [calculatorTool],
maxIterations: 5,
});
const result = await agent.run('What is 15% of 850, and then add 42 to that result?');
console.log(result);
Output:
15% of 850 is 127.5. Adding 42 to that gives us 169.5.
The agent autonomously:
- Recognized the need for calculation
- Broke down the problem into steps
- Used the calculator tool twice
- Combined results into a clear response
Agent Architectures
Different architectures suit different use cases:
ReAct (Reasoning + Acting)
The simplest agent pattern. The agent alternates between reasoning (thinking out loud) and acting (using tools).
Thought: I need to find the current weather
Action: weather_tool("New York")
Observation: 72°F, sunny
Thought: I have the weather information
Action: respond("The weather in New York is 72°F and sunny")
Plan-and-Execute
The agent first creates a complete plan, then executes each step. Better for complex, multi-step tasks.
Plan:
1. Search for company information
2. Find recent news articles
3. Analyze financial data
4. Write summary report
Executing step 1...
Executing step 2...
...
Tree of Thoughts
The agent explores multiple reasoning paths before choosing the best one. Useful for problems requiring creative solutions.
┌── Path A: Direct calculation ──┐
│ │
Start ─┼── Path B: Use approximation ───┼── Evaluate ── Best Path
│ │
└── Path C: Break into parts ────┘
When to Use Agents
Agents are ideal for:
- Research tasks: Gathering and synthesizing information from multiple sources
- Data analysis: Multi-step analysis with intermediate processing
- Workflow automation: Tasks requiring multiple tool interactions
- Problem solving: Complex problems requiring adaptive approaches
Agents may be overkill for:
- Simple Q&A where a single response suffices
- Tasks with fixed, predictable steps
- Situations requiring deterministic outputs
- Low-latency requirements (agents are slower)
Challenges with Agents
Building reliable agents presents challenges:
1. Unpredictable Behavior
Agents can take unexpected paths. Testing all possible behaviors is difficult.
2. Cost
Each iteration requires an API call. Complex tasks can become expensive.
3. Latency
Multiple LLM calls and tool executions add up. Agents are slower than direct responses.
4. Error Accumulation
Errors in early steps can compound. Agents need robust error handling.
5. Infinite Loops
Agents can get stuck. Always set maximum iteration limits.
Key Takeaways
- Agents are autonomous - they work toward goals without constant human guidance
- The agent loop consists of perceive, think, act, and evaluate steps
- Core components include the LLM brain, tools, memory, and executor
- Different architectures suit different problems - ReAct for simple, Plan-and-Execute for complex
- Trade-offs exist - agents provide flexibility but add cost, latency, and complexity
Practice Exercise
Build a simple agent with these tools:
get_time: Returns the current timeget_date: Returns the current datecalculate: Performs math operations
Test the agent with this prompt: "What day of the week will it be 100 days from now?"
Observe how the agent:
- Gets the current date
- Calculates the future date
- Determines the day of the week
Resources
| Resource | Type | Level |
|---|---|---|
| LangChain.js Agents | Documentation | Beginner |
| OpenAI Function Calling Guide | Documentation | Beginner |
| Building LLM Agents | Article | Intermediate |
Next Lesson
In the next lesson, you will learn about planning and reasoning - how to make agents think more systematically about complex problems.