How to Build an Agent Loop with Plan, Act, Observe in Python

Implements a simple plan-act-observe loop that an AI agent uses to iteratively complete a task in an environment while storing observations in memory.

Easy Python 3.9+ Aug 9, 2026 AI & LLM integration patterns 18 views 0 copies

Python code

28 lines
Python 3.9+
class Agent:
    def __init__(self, name):
        self.name = name
        self.memory = {}

    def plan(self, task):
        return f"Plan for {task}: step 1, step 2, step 3"

    def act(self, plan, environment):
        return f"Executing {plan} in {environment}"

    def observe(self, action_result):
        self.memory["last_observation"] = action_result
        return f"Observed: {action_result}"


def agent_loop(agent, task, environment, iterations=3):
    for i in range(iterations):
        plan = agent.plan(task)
        result = agent.act(plan, environment)
        observation = agent.observe(result)
        print(f"Iteration {i + 1}: {observation}")
    print(f"Memory: {agent.memory}")


if __name__ == "__main__":
    agent = Agent("MockBot")
    agent_loop(agent, "navigate maze", "grid_world")

Output

stdout
Iteration 1: Observed: Executing Plan for navigate maze: step 1, step 2, step 3 in grid_world
Iteration 2: Observed: Executing Plan for navigate maze: step 1, step 2, step 3 in grid_world
Iteration 3: Observed: Executing Plan for navigate maze: step 1, step 2, step 3 in grid_world
Memory: {'last_observation': 'Executing Plan for navigate maze: step 1, step 2, step 3 in grid_world'}

How it works

The Agent class uses three methods—plan, act, and observe—to separate the cognitive steps of an AI loop. plan generates a strategy, act executes it within a given environment, and observe records the outcome into the agent's memory dictionary. The agent_loop function orchestrates these calls in a fixed number of iterations, printing each observation. This pattern mirrors the reasoning loop used by LLM-based agents, where memory accumulates context for future decisions.

Common mistakes

  • Forgetting to clear or update memory between tasks, causing stale observations to leak across runs.
  • Assuming the loop terminates based on task success instead of fixed iterations.
  • Hard-coding environment details into the plan method instead of passing them dynamically.

Variations

  1. Add a `should_stop` method to break the loop when the task is completed or a max step count is reached.
  2. Use a list for memory instead of a dict to store the full history of observations.

Real-world use cases

  • Building a conversational AI assistant that plans, calls tools, and observes results before responding.
  • Creating a reinforcement learning loop where an agent evaluates state, takes action, and records rewards.
  • Implementing a retrieval-augmented generation pipeline that iterates over documents to refine answers.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from AI & LLM integration patterns

Related tutorials and quizzes for this topic.