The mystique around agents evaporates the moment you write one. At its heart it is a loop: ask the model what to do, do the safe part of it, feed back the result, repeat until done or until a human says stop.

The whole thing, roughly

Here is a stripped-down version of the pipeline-triage agent we run internally. It reads a failing render log, proposes a fix, and — crucially — never applies anything destructive without confirmation.

pythonagent.py
def agent(task, tools, model, max_steps=8):
    history = [system_prompt(tools), user(task)]
    for step in range(max_steps):
        reply = model.complete(history)
        if reply.done:
            return reply.answer
        call = reply.tool_call
        if call.destructive and not human_ok(call):
            history.append(tool_result(call, "denied by human"))
            continue
        result = tools[call.name](**call.args)
        history.append(tool_result(call, result))
    return "stopped: step budget reached"

Notice what is doing the work. It is not a clever model. It is the guardrails: a step budget, a destructive-action gate, and a log the human can read. The intelligence is in the constraints.

An agent is only as trustworthy as the smallest action it can take without asking.

What broke, and what I learned

  • Give tools narrow, boring interfaces. The model behaves when the surface area is small.
  • Log every step in human language. You will need it at 2 a.m.
  • Design for the model being wrong. Then it being wrong is a Tuesday, not an incident.

Start with one tool and a loop this weekend. You will understand more about this moment in our industry than a hundred think-pieces will teach you.