Module 1 of 10, lesson 1 of 5
What an agent really is
Tell a model, a program and an agent apart, and know when an agent is the wrong choice.
An LLM on its own turns text into other text. It only knows what it saw in training and what you put in its context. It can’t check your database or send an email.
The first step is to wrap it in code: fetch some data, place it in the prompt, generate the answer. That’s useful, but a developer still wrote the path. A classic RAG pipeline takes the same route whatever the question.
An agent changes one thing, and it’s the one that matters: the model chooses the next step. The developer provides a goal, tools and limits. The model decides which tool to call, reads the result, and repeats until it’s done.
Three capabilities
- Reason: break down a goal and choose an action.
- Act: call tools that read or change the outside world.
- Remember: keep what it has learned, during the task and sometimes beyond it.
Agent or chatbot
This comparison misleads, because the two terms describe different things. A chatbot is an interface. Agency is a way of organizing the system behind that interface. So a chatbot may or may not be agentic.
The cost of autonomy
Letting the model decide costs calls, time and predictability. If the problem is narrow and every request is handled the same way, a regular program is faster, cheaper and more reliable. An agent earns its place when the path changes from one request to the next.
If you can write the path in advance, write it.
Worked example: The same request, two systems
A fixed workflow handles the case it was written for. As soon as a request needs a step nobody planned, it answers the wrong thing without noticing.
function fixedWorkflow(request, orders) {
const order = orders[request.orderId];
return order.delivered ? 'refund' : 'wait';
}
const orders = { 4512: { delivered: true, returnReceived: false } };
fixedWorkflow({ orderId: 4512, text: 'Broken, and I kept it' }, orders);
'refund'
The code refunds a customer whose return never arrived, because no step reads the request. An agent can check the return first, but it costs more calls and more risk. If every request follows this path, keep the workflow.
Try it in the editor
async function runAgent({ model, tools, prompt }) { const messages = [{ role: 'user', content: prompt }]; while (true) { const response = await model.create({ messages }); messages.push({ role: 'assistant', content: response.content }); if (response.stop_reason === 'end_turn') { return response.content.find((b) => b.type === 'text').text;