Chapter 17
15 min read
Section 104 of 175

AutoGPT Architecture

AutoGPT and Autonomous Agents

Introduction

AutoGPT represents a paradigm shift in AI agents: fully autonomous systems that can pursue goals with minimal human intervention. Unlike orchestrated agents like those in LangGraph or CrewAI, AutoGPT-style agents generate their own next steps through recursive self-prompting.

Chapter Overview: We'll explore the architecture of autonomous agents, understand the self-prompting loop, examine goal decomposition strategies, and learn when autonomous agents are appropriate.

What is AutoGPT

AutoGPT, released in March 2023, demonstrated that LLMs could autonomously pursue complex goals by breaking them down into subtasks and executing them iteratively. It sparked a wave of autonomous agent development.

The Autonomous Agent Vision

🐍python
1"""
2Traditional vs Autonomous Agents
3
4Traditional (Orchestrated):
5β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
6β”‚                 Orchestrator                 β”‚
7β”‚    (LangGraph, CrewAI, Human-defined)       β”‚
8β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
9                   β”‚ Defines flow
10    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
11    β–Ό              β–Ό              β–Ό
12β”Œβ”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”
13β”‚Task 1β”‚ ───▢ β”‚Task 2β”‚ ───▢ β”‚Task 3β”‚
14β””β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”˜
15
16Autonomous (Self-Directed):
17β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
18β”‚                   Goal                       β”‚
19β”‚    "Build a market research report"         β”‚
20β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
21                   β”‚
22                   β–Ό
23    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
24    β”‚     Autonomous Agent Loop     β”‚
25    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
26    β”‚  β”‚   Think about goal      β”‚ β”‚
27    β”‚  β”‚         ↓               β”‚ β”‚
28    β”‚  β”‚   Decide next action    β”‚ β”‚
29    β”‚  β”‚         ↓               β”‚ β”‚
30    β”‚  β”‚   Execute action        β”‚ β”‚
31    β”‚  β”‚         ↓               β”‚ β”‚
32    β”‚  β”‚   Observe result        β”‚ β”‚
33    β”‚  β”‚         ↓               β”‚ β”‚
34    β”‚  β”‚   Update memory         │──┼──▢ Loop until done
35    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
36    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
37"""
38
39# Key difference: The agent decides what to do next,
40# not a predefined workflow

Core Capabilities

CapabilityDescription
Goal PursuitWorks toward user-defined objectives autonomously
Task GenerationCreates its own subtasks dynamically
Self-PromptingGenerates prompts for itself to continue
Long-term MemoryPersists information across sessions
Tool UseExecutes code, browses web, manages files
Self-ReflectionEvaluates its own progress and adjusts

Core Architecture

The Main Loop

🐍python
1from typing import TypedDict, List, Optional
2from langchain_openai import ChatOpenAI
3from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
4import json
5
6
7class AgentState(TypedDict):
8    """State for autonomous agent."""
9    goals: List[str]
10    memory: List[dict]
11    current_task: Optional[str]
12    completed_tasks: List[str]
13    iteration: int
14    max_iterations: int
15    is_complete: bool
16
17
18class AutonomousAgent:
19    """Basic autonomous agent implementation."""
20
21    def __init__(
22        self,
23        goals: List[str],
24        max_iterations: int = 20
25    ):
26        self.llm = ChatOpenAI(model="gpt-4o", temperature=0.3)
27        self.state: AgentState = {
28            "goals": goals,
29            "memory": [],
30            "current_task": None,
31            "completed_tasks": [],
32            "iteration": 0,
33            "max_iterations": max_iterations,
34            "is_complete": False
35        }
36        self.tools = self._setup_tools()
37
38    def _setup_tools(self) -> dict:
39        """Setup available tools."""
40        return {
41            "search": self._search,
42            "write_file": self._write_file,
43            "read_file": self._read_file,
44            "execute_code": self._execute_code,
45            "think": self._think,
46            "complete": self._mark_complete
47        }
48
49    def run(self) -> dict:
50        """Main autonomous loop."""
51        while not self.state["is_complete"]:
52            if self.state["iteration"] >= self.state["max_iterations"]:
53                print("Max iterations reached")
54                break
55
56            # Think about what to do next
57            action = self._decide_next_action()
58
59            # Execute the action
60            result = self._execute_action(action)
61
62            # Update memory with result
63            self._update_memory(action, result)
64
65            # Check if goals are achieved
66            self._evaluate_progress()
67
68            self.state["iteration"] += 1
69
70        return {
71            "completed_tasks": self.state["completed_tasks"],
72            "memory": self.state["memory"],
73            "iterations": self.state["iteration"]
74        }
75
76    def _decide_next_action(self) -> dict:
77        """Use LLM to decide next action."""
78        prompt = self._build_decision_prompt()
79
80        messages = [
81            SystemMessage(content=self._get_system_prompt()),
82            HumanMessage(content=prompt)
83        ]
84
85        response = self.llm.invoke(messages)
86        return self._parse_action(response.content)
87
88    def _get_system_prompt(self) -> str:
89        """System prompt for autonomous behavior."""
90        return """You are an autonomous AI agent working toward goals.
91
92For each step, you must output a JSON action:
93{
94    "thoughts": "Your reasoning about what to do",
95    "action": "tool_name",
96    "action_input": "input for the tool"
97}
98
99Available tools:
100- search: Search the web for information
101- write_file: Write content to a file
102- read_file: Read a file's contents
103- execute_code: Execute Python code
104- think: Internal reasoning/planning
105- complete: Mark the goal as achieved
106
107Always think step by step. Be thorough but efficient."""

Action Execution

🐍python
1class AutonomousAgent:
2    # ... continued from above ...
3
4    def _build_decision_prompt(self) -> str:
5        """Build prompt for next action decision."""
6        recent_memory = self.state["memory"][-5:]  # Last 5 actions
7
8        return f"""
9Goals: {json.dumps(self.state['goals'])}
10
11Completed tasks: {json.dumps(self.state['completed_tasks'])}
12
13Recent actions and results:
14{json.dumps(recent_memory, indent=2)}
15
16Current iteration: {self.state['iteration']} / {self.state['max_iterations']}
17
18Based on your goals and progress, decide the next action.
19Output your response as JSON.
20"""
21
22    def _parse_action(self, response: str) -> dict:
23        """Parse LLM response into action."""
24        try:
25            # Extract JSON from response
26            start = response.find('{')
27            end = response.rfind('}') + 1
28            json_str = response[start:end]
29            return json.loads(json_str)
30        except Exception as e:
31            return {
32                "thoughts": f"Parse error: {e}",
33                "action": "think",
34                "action_input": response
35            }
36
37    def _execute_action(self, action: dict) -> str:
38        """Execute the decided action."""
39        tool_name = action.get("action", "think")
40        tool_input = action.get("action_input", "")
41
42        print(f"\n[Iteration {self.state['iteration']}]")
43        print(f"Thoughts: {action.get('thoughts', 'N/A')}")
44        print(f"Action: {tool_name}")
45        print(f"Input: {tool_input[:100]}...")
46
47        if tool_name in self.tools:
48            try:
49                result = self.tools[tool_name](tool_input)
50                print(f"Result: {result[:100]}...")
51                return result
52            except Exception as e:
53                return f"Error executing {tool_name}: {str(e)}"
54        else:
55            return f"Unknown tool: {tool_name}"
56
57    def _update_memory(self, action: dict, result: str):
58        """Add action and result to memory."""
59        memory_entry = {
60            "iteration": self.state["iteration"],
61            "thoughts": action.get("thoughts", ""),
62            "action": action.get("action", ""),
63            "action_input": action.get("action_input", ""),
64            "result": result[:500]  # Truncate long results
65        }
66        self.state["memory"].append(memory_entry)
67
68    def _evaluate_progress(self):
69        """Check if goals are achieved."""
70        if self.state["memory"]:
71            last_action = self.state["memory"][-1]
72            if last_action["action"] == "complete":
73                self.state["is_complete"] = True

Memory Systems

Short and Long-term Memory

🐍python
1import chromadb
2from chromadb.config import Settings
3from typing import List
4import hashlib
5
6
7class AgentMemory:
8    """Memory system for autonomous agents."""
9
10    def __init__(self, agent_id: str):
11        self.agent_id = agent_id
12
13        # Short-term memory: Recent context
14        self.short_term: List[dict] = []
15        self.short_term_limit = 10
16
17        # Long-term memory: Vector store for retrieval
18        self.chroma_client = chromadb.Client(Settings(
19            anonymized_telemetry=False
20        ))
21        self.collection = self.chroma_client.get_or_create_collection(
22            name=f"agent_{agent_id}_memory"
23        )
24
25    def add_memory(self, entry: dict, long_term: bool = False):
26        """Add memory entry."""
27        # Always add to short-term
28        self.short_term.append(entry)
29        if len(self.short_term) > self.short_term_limit:
30            # Move oldest to long-term
31            old_entry = self.short_term.pop(0)
32            self._add_to_long_term(old_entry)
33
34        # Optionally add important items to long-term immediately
35        if long_term:
36            self._add_to_long_term(entry)
37
38    def _add_to_long_term(self, entry: dict):
39        """Add entry to vector store."""
40        text = f"""
41        Action: {entry.get('action', '')}
42        Input: {entry.get('action_input', '')}
43        Result: {entry.get('result', '')}
44        Thoughts: {entry.get('thoughts', '')}
45        """
46
47        entry_id = hashlib.md5(text.encode()).hexdigest()
48
49        self.collection.add(
50            documents=[text],
51            ids=[entry_id],
52            metadatas=[{"iteration": entry.get("iteration", 0)}]
53        )
54
55    def recall(self, query: str, n_results: int = 5) -> List[str]:
56        """Retrieve relevant memories."""
57        results = self.collection.query(
58            query_texts=[query],
59            n_results=n_results
60        )
61        return results["documents"][0] if results["documents"] else []
62
63    def get_recent(self, n: int = 5) -> List[dict]:
64        """Get recent short-term memories."""
65        return self.short_term[-n:]
66
67    def summarize(self) -> str:
68        """Summarize memory state."""
69        return f"""
70Memory Status:
71- Short-term entries: {len(self.short_term)}
72- Long-term entries: {self.collection.count()}
73- Recent actions: {[m.get('action') for m in self.short_term[-3:]]}
74"""

Evolution and Variants

AutoGPT Family

SystemKey InnovationFocus
AutoGPTOriginal self-prompting loopGeneral autonomous tasks
BabyAGITask-driven queueTask management
AgentGPTWeb-based interfaceAccessibility
SuperAGIInfrastructure and pluginsProduction deployment
GPT-EngineerCode-focused autonomySoftware development

BabyAGI Implementation

🐍python
1from collections import deque
2from typing import List, Deque
3
4
5class TaskQueue:
6    """Task management for BabyAGI-style agents."""
7
8    def __init__(self):
9        self.tasks: Deque[dict] = deque()
10        self.completed: List[dict] = []
11        self.task_id = 0
12
13    def add_task(self, description: str, priority: int = 1):
14        """Add task to queue."""
15        self.task_id += 1
16        task = {
17            "id": self.task_id,
18            "description": description,
19            "priority": priority,
20            "status": "pending"
21        }
22        self.tasks.append(task)
23        self._sort_by_priority()
24
25    def _sort_by_priority(self):
26        """Sort tasks by priority."""
27        self.tasks = deque(sorted(
28            self.tasks,
29            key=lambda x: x["priority"],
30            reverse=True
31        ))
32
33    def get_next_task(self) -> dict | None:
34        """Get highest priority task."""
35        if self.tasks:
36            return self.tasks.popleft()
37        return None
38
39    def complete_task(self, task: dict, result: str):
40        """Mark task as complete."""
41        task["status"] = "completed"
42        task["result"] = result
43        self.completed.append(task)
44
45
46class BabyAGI:
47    """BabyAGI-style task-driven agent."""
48
49    def __init__(self, objective: str):
50        self.objective = objective
51        self.llm = ChatOpenAI(model="gpt-4o")
52        self.task_queue = TaskQueue()
53        self.memory = AgentMemory("babyagi")
54
55    def run(self, max_iterations: int = 10):
56        """Main BabyAGI loop."""
57
58        # Generate initial tasks
59        self._create_initial_tasks()
60
61        iteration = 0
62        while iteration < max_iterations:
63            # Get next task
64            task = self.task_queue.get_next_task()
65            if not task:
66                print("No more tasks!")
67                break
68
69            print(f"\nExecuting: {task['description']}")
70
71            # Execute task
72            result = self._execute_task(task)
73
74            # Complete task
75            self.task_queue.complete_task(task, result)
76
77            # Create new tasks based on result
78            self._create_new_tasks(task, result)
79
80            iteration += 1
81
82        return self.task_queue.completed
83
84    def _create_initial_tasks(self):
85        """Generate initial task list from objective."""
86        messages = [
87            SystemMessage(content="""Break down the objective into 3-5
88            initial tasks. Output as JSON list of task descriptions."""),
89            HumanMessage(content=f"Objective: {self.objective}")
90        ]
91
92        response = self.llm.invoke(messages)
93        tasks = json.loads(response.content)
94
95        for i, task in enumerate(tasks):
96            self.task_queue.add_task(task, priority=len(tasks) - i)
97
98    def _execute_task(self, task: dict) -> str:
99        """Execute a single task."""
100        context = self.memory.get_recent(3)
101
102        messages = [
103            SystemMessage(content=f"Objective: {self.objective}"),
104            HumanMessage(content=f"""
105Task: {task['description']}
106
107Recent context: {json.dumps(context)}
108
109Complete this task and provide the result.
110""")
111        ]
112
113        response = self.llm.invoke(messages)
114        return response.content
115
116    def _create_new_tasks(self, completed_task: dict, result: str):
117        """Generate new tasks based on completed task."""
118        messages = [
119            SystemMessage(content=f"""Objective: {self.objective}
120
121Based on the completed task and its result, determine if any new
122tasks should be added. Output as JSON list of new task descriptions,
123or empty list if no new tasks needed."""),
124            HumanMessage(content=f"""
125Completed: {completed_task['description']}
126Result: {result}
127
128Remaining tasks: {[t['description'] for t in self.task_queue.tasks]}
129""")
130        ]
131
132        response = self.llm.invoke(messages)
133        try:
134            new_tasks = json.loads(response.content)
135            for task in new_tasks:
136                self.task_queue.add_task(task)
137        except json.JSONDecodeError:
138            pass  # No new tasks

Key Takeaways

  • AutoGPT pioneered autonomous agents that pursue goals through self-prompting loops.
  • Core architecture consists of goal input, decision loop, action execution, and memory.
  • Memory systems combine short-term context with long-term vector storage.
  • Variants like BabyAGI focus on task queue management for goal decomposition.
  • Iteration limits are essential to prevent runaway execution and control costs.
Next Section Preview: We'll explore the self-prompting loop in detail - the heart of autonomous agent behavior.