An AI agent is a loop. A language model reads the goal and everything that has happened so far, then either calls one of the tools you defined or gives a final answer. Your code runs the tool, appends the result and asks again. Step limits, permissions, human approval and tests keep that loop safe.
| Part | What you build | What goes wrong without it |
|---|---|---|
| Loop | Code that calls the model, runs tools and repeats | Nothing happens after the first reply |
| Tools | Named functions with a description and an input schema | The model can only talk, not act |
| Memory | The running transcript, plus any notes saved between runs | The model repeats calls it already made |
| Guardrails | Step and cost limits, least privilege, approval for risky actions | Runaway loops, surprise bills, damaging actions |
| Evaluation | Fixed test tasks with checks you rerun after every change | You find regressions from users |
Updated
Run the simulator to watch one task move through the loop. Turn approval off and on to see where a guardrail interrupts a risky step. The trace is scripted so you can study it; a real run would ask a model at each decide step.
Goal: find the cheapest of three supplier quotes and email the summary to the office manager.
No framework and no vendor SDK. callModel is a stub that plays back fixed decisions so the file runs as-is; replace it with a request to the model service you use.
Tools live in one object, risky ones need approval, and the loop stops at a step limit. Run it with node agent.mjs.
const tools = {
read_quotes: {
risky: false,
run: async () => ({ A: 1240, B: 1180, C: 1315 }),
},
send_email: {
risky: true,
run: async ({ to, text }) => `sent to ${to}: ${text}`,
},
};
// Stub: replace with a real model request that receives the goal,
// the tool list and the transcript, and returns a tool call or an answer.
const script = [
{ tool: "read_quotes", args: {} },
{ tool: "send_email", args: { to: "[email protected]", text: "Quote B is cheapest at $1,180." } },
{ answer: "Quote B is cheapest; summary sent." },
];
async function callModel(transcript) {
return script[transcript.filter((m) => m.role === "tool").length];
}
async function approve(tool, args) {
console.log(`Approval needed for ${tool}:`, args);
return true; // ask a person here
}
async function runAgent(goal, maxSteps = 10) {
const transcript = [{ role: "user", content: goal }];
for (let step = 1; step <= maxSteps; step++) {
const move = await callModel(transcript);
if (move.answer) return move.answer;
const tool = tools[move.tool];
if (!tool) {
transcript.push({ role: "tool", content: `Unknown tool ${move.tool}` });
continue;
}
if (tool.risky && !(await approve(move.tool, move.args))) {
transcript.push({ role: "tool", content: "A person declined this action." });
continue;
}
const result = await tool.run(move.args);
transcript.push({ role: "tool", content: JSON.stringify(result) });
}
return "Stopped: step limit reached.";
}
runAgent("Find the cheapest quote and email the office.").then(console.log);| Risk | How it shows up in an agent | Fix in code |
|---|---|---|
| LLM01:2025 Prompt Injection | A fetched page tells the model to email your data elsewhere | Separate untrusted content, approve privileged actions |
| LLM06:2025 Excessive Agency | The agent can delete records it only needed to read | Fewer tools, narrow credentials, approval for high impact |
| LLM10:2025 Unbounded Consumption | A loop retries a failing tool all night | Step limit, spend limit, timeouts, rate limits |
| LLM05:2025 Improper Output Handling | Model output is pasted into SQL or HTML unchecked | Validate and escape before any downstream use |
OWASP's 2025 list names Excessive Agency as a core risk and traces it to three causes: excessive functionality, excessive permissions and excessive autonomy. Each maps to a fix you control in code.
Give the agent only the tools the task needs, give each tool the narrowest credentials that work, and require a person to approve high-impact actions such as sending, paying or deleting. Check authorization in the system the tool calls rather than trusting the model to behave.
Anything a tool fetches, such as a web page, an email or a file, can contain instructions aimed at your model. OWASP calls this indirect prompt injection.
Mark fetched content clearly as data, keep it apart from your own instructions and never let text from a tool result unlock a more powerful tool on its own. Human approval for privileged steps is the backstop when the other defences miss.
No. The core is a while loop around one model call and a switch over tool names, as the example on this page shows. Frameworks add retries, tracing and integrations, which help later but hide the loop while you are learning.
You send tool definitions with each request. When the model wants one, it replies with the tool name and arguments instead of plain text. Your code runs the function and sends the result back as the next message.
Context is what the model sees on this call: instructions, the goal and the transcript so far. Memory is anything you store and choose to put back into context later, such as notes from a previous run.
Cap the number of steps and the total spend, and end the run with a clear message when either is reached. OWASP lists Unbounded Consumption among its 2025 risks for applications built on language models.
Write a set of fixed tasks with checkable outcomes: the right tool was called, a risky action waited for approval, the final answer contains a figure. Run the set after every prompt or tool change and compare pass counts.
Related: AI agent vs agentic AI, What is an MCP server?, How to build an MCP server, AI agent test checklist, AI API cost calculator.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.