The agent loop

At this point in the syllabus, we have built up all the pieces of a classical agent: state, decision logic, tools, and workflows. What we have not yet done is connect them into a single, repeating structure that runs over time. The sense–decide–act–update cycle exists to provide that structure. It is the backbone that turns isolated logic into an agent that can observe, respond, and evolve continuously.

The core phases of an agent loop

A classical agent loop is organized around a small number of repeating phases. Each phase has a distinct role, and together they form a stable pattern that can run indefinitely. This separation keeps the agent understandable and predictable, even as its behavior becomes more complex.

Conceptually, the loop does not change from iteration to iteration. What changes is the state flowing through it.

Sensing input from the environment or user

The sensing phase gathers information from outside the agent. This might be user input, the contents of a file, a clock tick, or any other signal the agent cares about. Sensing does not make decisions or cause side effects beyond reading data.

In code, sensing is often just a function call that returns new input to be processed.

def sense():
    return input("Command: ")

Deciding what action to take based on state

The decision phase examines the current state along with the newly sensed input. Its job is to determine what should happen next. In a classical agent, this decision is deterministic and rule-based.

The decision logic produces an intention, not an effect. It answers “what should we do?” rather than “do it now.”

def decide(state, command):
    if command == "status":
        return "report_status"
    return "do_nothing"

Acting by invoking tools

The acting phase turns a decision into concrete behavior. This is where tools are invoked and side effects occur. Acting is where files are written, messages are printed, or other external changes are made.

Each action is typically implemented as a tool with a clear input and output.

def report_status(state):
    print(f"Processed items: {state['count']}")

Updating state after an action

The update phase modifies the agent’s internal state to reflect what just happened. This ensures that future decisions can take past actions into account. Updates should be explicit and localized, rather than scattered throughout the code.

State updates close the loop, preparing the agent for the next iteration.

def update(state, action):
    if action == "report_status":
        state["count"] += 1

Conclusion

The sense–decide–act–update cycle provides a simple but powerful structure for classical agents. Each phase has a clear responsibility, and together they create a loop that can run repeatedly without becoming tangled or unpredictable. At this point, we are oriented around how an agent continuously observes its environment, chooses actions, executes them, and carries forward the results into future behavior.