Lesson 22 of 30
A plain chat completion answers once and stops. An agent is a model given tools and put in a loop — plan, act, observe, decide if it's done — and that loop, not the tools themselves, is what actually makes it an agent.
13 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A request sends the model a tool definition, the model calls exactly one tool, and the result is returned to the user. Is this an agent?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A plain chat completion has a fixed shape: you send a request, the model generates a response, the interaction ends. Giving the model function calling (the ability to request that a specific tool be invoked, with specific arguments) doesn't change that shape by itself — a single call that decides to invoke one tool and return a result is still just one request-response cycle, only with an extra step inside it.
An agent is what you get when you take that same tool-calling model and put it in a loop: given a goal, the model plans a next step, acts (calls a tool), observes the result, and then decides for itself whether the goal is met or another step is needed — repeating until it's done or it gives up. The defining thing isn't the tools. It's the loop, and specifically who controls it: the model decides how many steps to take and in what order, not a developer hardcoding "call tool A, then tool B, then respond."
That's also the honest boundary to draw in an interview: "an LLM with function calling" and "an agent" are not automatically the same thing. A single tool call inside one request-response cycle is function calling. Only when the model is allowed to keep looping — re-planning based on what it just observed — does it become agentic.
// Rough sketch of an agent loop — NOT this app's actual implementation,
// which doesn't run agents; this is the general shape the pattern takes.
async function runAgent(goal: string, tools: Tool[]) {
const history: Message[] = [{ role: "user", content: goal }];
while (true) {
const step = await model.generate({ messages: history, tools });
if (step.type === "final_answer") {
return step.content; // model decided the goal is met — loop ends here
}
// step.type === "tool_call": act, then observe the result
const result = await callTool(step.toolName, step.args);
history.push({ role: "assistant", content: step.raw });
history.push({ role: "tool", content: JSON.stringify(result) });
// loop back to plan again, now with the tool's result in context
}
}
A goal comes in. The model plans its next step toward it.
Nothing here forces a fixed number of steps. A simple goal might resolve in one tool call; a harder one might take five, with the model changing its plan after seeing what the third tool call actually returned. That open-ended, model-driven step count is exactly what a single fixed function-calling request-response can't do.
"What actually makes something an agent, versus just an LLM that can call functions?" is a common way this gets tested, and naming the loop — plan, act, observe, decide — plus who controls it (the model, not a fixed script) is the answer that shows real understanding rather than buzzword familiarity.