AI Agents and Workflows
Chain multiple tool calls into a bounded plan-act-observe loop.
What you'll learn
- Describe the plan → act → observe agent loop
- Explain why an agent loop must be bounded
- Implement a simple bounded loop that stops on a completion condition
Prerequisites
Explanation
A single tool call answers "look this one thing up." An agent goes further: it can chain multiple steps together, using the result of one action to decide the next one, until it judges the task complete. The common shape is a loop:
- Plan — given the goal and everything observed so far, decide what to do next (answer directly, or call a specific tool).
- Act — actually perform that action (call the chosen tool with the chosen arguments).
- Observe — receive the tool's result and add it to the agent's working context.
- Repeat, incorporating each observation into the next planning step, until the agent decides it has enough information to give a final answer — or until a safety limit is hit.
That safety limit matters enormously. An unbounded loop is dangerous: a model that gets confused could call tools indefinitely, burning cost and time with no guaranteed termination. Every real agent loop needs a maximum step count (e.g., "stop after 6 tool calls no matter what, and give the best answer available") as a hard backstop, independent of whether the model ever explicitly decides it's done.
Agents are a good fit for tasks that genuinely require multiple dependent steps — "find this user's most recent order, then check its shipping status, then draft a message about it" — where each step's outcome determines the next action. They're overkill (and a reliability/cost risk) for tasks a single prompt or a single tool call already solves well; more autonomy is not automatically better, and a fixed, deterministic workflow you designed yourself is often more predictable and debuggable than an open-ended agent loop, especially for the beta stage of a product.
Observability matters just as much here as capability: log every planning decision, every tool call with its arguments, and every observation, in an auditable form — both for debugging when something goes wrong, and so a human can review exactly what actions an agent took and why, especially before granting it access to anything with real-world consequences.
The bounded agent loop
Plan (decide next action) → Act (call a tool) → Observe (read the result) → loop back to Plan, until either a completion condition is met or a maximum step count is reached, whichever comes first.
Example
A tiny bounded agent loop using mock tools and a mock 'planner' function (a real agent's planning step would be an LLM call; here it's a simple rule for teaching purposes).
const tools = {
lookupWeather: () => ({ tempC: 22, condition: "sunny" }),
};
function mockPlan(observations) {
if (observations.length === 0) {
return { action: "call-tool", tool: "lookupWeather" };
}
return { action: "final-answer", text: "It's a sunny 22°C day." };
}
function runAgent(maxSteps) {
const observations = [];
for (let step = 0; step < maxSteps; step++) {
const decision = mockPlan(observations);
if (decision.action === "final-answer") {
return decision.text;
}
const result = tools[decision.tool]();
observations.push(result);
}
return "Stopped after reaching the maximum number of steps.";
}
console.log(runAgent(5));Try it yourself
Lower maxSteps to 0 and see the loop's safety backstop trigger instead of ever calling the tool.
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Guided exercise
Guided exercise
Complete `runBoundedLoop(isDone, step, maxSteps)` where `step` is a function taking the current iteration count and returning some value, and `isDone` takes that value and returns a boolean. Call step() repeatedly (passing the iteration index starting at 0), stopping as soon as isDone(result) is true, or after maxSteps calls — whichever comes first. Return the last result produced.
Checks: Stops early once isDone is true · plus 1 hidden check
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Independent exercise
Independent exercise
Write `runAgentLoop(tools, plan, maxSteps)`. `plan(observations)` returns either `{ action: 'call-tool', tool: name }` or `{ action: 'final-answer', text }`. Call plan with the growing observations array; if it requests a tool, call `tools[name]()`, push the result into observations, and continue; if it returns a final answer, return that text immediately. If maxSteps is reached without a final answer, return the string 'Stopped: step limit reached.'
Checks: Completes correctly after one tool call · plus 1 hidden check
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Common mistakes
- Building an agent loop with no maximum step count, risking runaway cost or an infinite loop.
- Reaching for an agent when a single deterministic function call would have solved the task more predictably.
- Not logging each planning decision and tool call, making failures impossible to debug or audit later.
Knowledge check
Takeaway
An agent is a bounded plan-act-observe loop — powerful for multi-step tasks, but only as safe as its hard step limit.
Summary
Agents chain multiple tool calls together in a plan → act → observe loop, using each observation to inform the next decision, until a completion condition or a hard maximum step count is reached. Agents suit genuinely multi-step, adaptive tasks; simpler deterministic workflows are often better for everything else.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.