AI Agents

A practical loop for building AI agents with Python

Start with a small, inspectable agent loop that chooses tools, observes results, and knows when to stop.

Diagram of an agent choosing a tool, receiving an observation, and deciding whether to continue.
On this page

An agent is not a mysterious new kind of program. At its simplest, it is a model inside a controlled loop: the model receives a goal, can request a tool, observes the result, and either continues or returns an answer.

That small definition is useful because it makes the important engineering questions visible. Which tools can run? What data can they access? How many steps are allowed? What happens when a tool fails?

Start with a bounded loop

Keep the first version narrow. Give the model a few explicit tools, record each call, and set a hard step limit. The loop should be ordinary application code that you can inspect and test.

python
MAX_STEPS = 5
 
def run_agent(goal, model, tools):
    messages = [{"role": "user", "content": goal}]
 
    for _ in range(MAX_STEPS):
        response = model.respond(messages, tools=tools.schemas())
        if response.is_final:
            return response.text
 
        result = tools.call(response.tool_name, response.arguments)
        messages.extend([response.message, result.to_message()])
 
    raise RuntimeError("Agent reached its step limit")

The API names here are illustrative; the important part is the boundary between model output and tool execution.

Treat tool calls as untrusted input

Validate arguments against a schema before invoking a tool. Apply authorization in the tool implementation, not in the prompt. Return small, structured results so the next model step has useful context without receiving secrets or an entire database row.

For external or consequential actions, add a human approval step. A request to draft an email is different from permission to send one.

Make each step observable

Log a correlation ID, tool name, duration, success state, and a redacted summary of inputs and outputs. Avoid storing private prompts or credentials by default. These records help explain slow runs and repeated tool failures without turning logs into a second data leak.

Test decisions separately from the model

Unit-test argument validation, permission checks, tool error handling, and the step limit with a deterministic fake model. Then evaluate model behavior against a fixed set of tasks. This separates application defects from model variability.

Add complexity only when it earns its place

Begin with one model call and one or two tools. Add planning, memory, or multiple agents only when a measured limitation calls for it. A clear state machine is easier to debug than a clever prompt whose behavior nobody can reproduce.

A useful first milestone

Build one read-only tool, capture every tool call, and test invalid arguments and timeouts. Once that path is reliable, expand the set of actions carefully. The small loop is not a toy architecture; it is the foundation that keeps a larger agent understandable.

Keep learning with Sri

More practical tutorials and experiments on the channel.

Watch on YouTube
Back to articles