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.
Python code
28 linesclass 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
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
- Add a `should_stop` method to break the loop when the task is completed or a max step count is reached.
- 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
More from AI & LLM integration patterns
- Cache LLM Completions by Hashing the Prompt in Python easy
- Chain of Thought Prompting in Python: Step-by-Step Reasoning Demo easy
- Circuit Breaker Pattern in Python for LLM API Calls medium
- Cosine Similarity to Retrieve Top K Chunks in Python easy
- Demonstrate Prompt Injection Bypass in Python easy
- How to Accumulate Streamed Tokens into a Final String in Python easy
Keep learning
Related tutorials and quizzes for this topic.