Skip to content
AI-grafen
EUniversityAgents and tool use· about 60 min· fast-moving, sources checked often· verified 2026-09-20· EN

Agents — plan, act, observe

Be able to build a simple agent loop, limit it with a budget and stopping conditions, and log every step.

Prerequisites

Intuition

An agent is a language model in a loop: it is given a goal, picks a tool, sees the result, picks the next one — until it considers itself done. The difference from a simple tool call is that the model decides how many steps and which.

What makes agents useful is also what makes them dangerous: they can go in circles, burn through the budget, or do something irreversible. Which is why the loop is never just while True:

  • A budget: a maximum number of steps (10, say), a maximum number of tokens, a maximum number of seconds.
  • Stopping conditions: the model signals «done» or the budget runs out → return the best so far, marked «incomplete».
  • Guard rails: tools with side effects require confirmation; repeated identical calls are broken.
  • A log: every step (the reasoning, the call, the result, the cost) is saved. Without a log nobody can debug it or trust the result.

Code

import time, json

def agent(goal, llm, tools, max_steps=10, max_sec=60):
    msgs = [{"role": "system", "content": "Solve the task with the tools. When you are done: answer with FINAL: <answer>."},
            {"role": "user", "content": goal}]
    log, t0, previous = [], time.time(), None
    for step in range(max_steps):
        if time.time() - t0 > max_sec:
            return {"status": "timeout", "answer": None, "log": log}
        out = llm(msgs, tools=tools.spec())
        if out.text and out.text.startswith("FINAL:"):
            return {"status": "done", "answer": out.text[6:].strip(), "log": log}
        for call in out.tool_calls:
            key = (call.name, call.arguments)
            if key == previous:
                res = {"error": "the same call as the previous step — change strategy"}
            else:
                res = tools.run(call)
            previous = key
            log.append({"step": step, "tool": call.name, "args": call.arguments, "result": str(res)[:300]})
            msgs += [out.as_message(), {"role": "tool", "tool_call_id": call.id, "content": json.dumps(res)}]
    return {"status": "budget_exhausted", "answer": None, "log": log}

The pattern is often called ReAct (reason + act). Evaluate agents at the task level (did it solve the goal?) and on the cost per successful task.

Mastery means

  • Builds an agent loop (plan → act → observe) with stopping conditions
  • Sets a budget for steps, tokens and time
  • Logs every step so that a run can be audited

Sign in to do the exercises and build your mastery up.

Sources

All the sources and licences