Agentic Loop

What's an Agentic Loop?

Agentic Loop

What's an Agentic Loop?

In the realm of AI Agents an Agentic Loop in simple terms is a model call inside a while loop. In each iteration of the loop the model says either "run this tool for me" or "I'm done", and your code either calls the tool or exits. You can think of it like a turn based game between you and the model.

The agentic loopThe user's request goes to the model. If the model wants to run tools, the tools run and the whole conversation, with tool results, is sent back to the model. When it no longer wants tools, the final response is returned.The user's requestCall the modelModel wants to runtool(s)?Return the final responseRun the tool(s)no, it's doneyes, run tool(s)resend the wholeconversation with toolresults
The agentic loop

The model never executes anything, it asks. Your tool/code decides what actually runs, not the model. This is where sandboxing and permissions live.

The final answer is the response that broke the loop. You don't make a closing call to ask for a summary. The turn that came back without tool use already is the final answer.

Anthropic SDK Example

add_numbers.py
# /// script
# requires-python = ">=3.10"
# dependencies = ["anthropic"]
# ///
import anthropic

client = anthropic.Anthropic()

# Tool Declaration
tools = [{
    "name": "add",
    "description": "Add two numbers",
    "input_schema": {
        "type": "object",
        "properties": {
            "a": {"type": "number"},
            "b": {"type": "number"},
        },
        "required": ["a", "b"],
    },
}]

# Tool Implementation
def run_tool(name, args):
    if name == "add":
        return str(args["a"] + args["b"])

# Initial Prompt
messages = [{"role": "user", "content": "What is 5 + 10?"}]

# The Agentic Loop
while True:
    # Initial call with the prompt
    response = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )
    # Agent's response (agent's turn) appended to the messages array.
    messages.append({"role": "assistant", "content": response.content})

    # Done: model gave a final answer instead of calling a tool
    if response.stop_reason != "tool_use":
        print(response.content[0].text)
        break

    # Otherwise: run each requested tool and send the results back
    results = []
    for block in response.content:
        if block.type == "tool_use":
            results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": run_tool(block.name, block.input),
            })
    # The tool results are appended to messages as role: user (user's turn)
    messages.append({"role": "user", "content": results})

Logic Breakdown

In the above example, a total of 8 steps happen across 2 model calls and 1 tool call. Here's the run, step by step.

Setup: before the loop

  1. Declare the tools. tools is what the model sees. Each tool has a name, a description and a JSON schema for the input.
  2. Seed the conversation. messages starts with a single prompt: the user's question, "What is 5 + 10?".

Iteration 1: the model asks for a tool

  1. Call the model. We send the tools and the initial messages array. The model decides it needs add tool and replies with a stop_reason as "tool_use". The response from the model has a tool_use block with tool name, input & a unique id.
  2. Record the model's turn. The reply from the model goes onto messages as role: "assistant", unchanged. This matters because the model is stateless, it doesn't remember anything between the calls. So every call resends everthing in the messages (the conversation).
  3. Check the exit condition. stop_reason is "tool_use", so we don't break.
  4. Run the tool and send the result back. For every tool_use block, our code calls run_tool, gets the result, and wraps it in a tool_result whose tool_use_id matches the tool block's id. The tool_use_id is how the model correlates the tool call request and the result. The tool results go onto messages as role: "user". From the model's point of view, the tool result is the user's next turn because the user runs it for the model.

Iteration 2: the model answers

  1. Call the model again with the whole conversation so far (with tool results from the previous iteration). This time it has what it needs and replies with plain text, "5 + 10 = 15". stop_reason is "end_turn".
  2. Exit. The reply is appended, and since stop_reason is no longer "tool_use", we print the text and break. That reply is the final answer.

By the time the loop exits, messages holds four entries:

#rolecontent
1user"What is 5 + 10?"
2assistanttool_use: add(a=5, b=10)
3usertool_result: "15"
4assistant"5 + 10 = 15"

The roles alternate user, assistant, user, assistant: the turn based game from the diagram.

To Summarize

An agentic loop is a model call inside a while loop:

  • The model asks, your code acts. Sandboxing and permissions live in your code.
  • stop_reason drives the loop. "tool_use" means run the tools and go again; anything else means done.
  • The model is stateless. Every call resends the whole conversation.
  • Tool results are the user's turn, matched to their request by tool_use_id.
  • The reply that breaks the loop is the final answer.

Swap add for real tools and the loop stays the same.