🤖 AgentGPT 源码解读

浏览器智能体架构深度解析

基于 reworkd/AgentGPT 开源项目
52 页 · Next.js + FastAPI + LangChain

📑 目录

第一部分:项目概览

  • AgentGPT 简介与定位
  • 核心架构总览
  • 技术栈全景

第二部分:前后端架构

  • Next.js 前端架构
  • FastAPI 后端架构
  • 目录结构详解

第三部分:Agent 核心

  • Agent 循环机制
  • 思考-行动-观察范式
  • LLM 集成层

第四部分:工具与记忆

  • 工具系统架构
  • 内置工具详解
  • 向量记忆系统

第五部分:工程实践

  • 数据库与认证
  • Prompt 工程
  • Docker 部署

第六部分:总结

  • 设计模式分析
  • 对比与优化
  • 扩展阅读

🤖 AgentGPT 简介

AgentGPT 是一个开源的 AI 智能体平台,允许用户在浏览器中创建和部署自主 AI Agent,无需编程即可配置自定义智能体。

核心特性

  • 浏览器端 Agent 配置与运行
  • 自主任务分解与执行
  • 内置多种工具(搜索、浏览、代码执行)
  • 长期向量记忆(Pinecone)
  • 多 LLM 提供商支持

项目数据

  • ★ 31k+ GitHub Stars
  • v2 当前主版本
  • MIT 开源协议
  • Python + TypeScript
  • 活跃社区维护

📐 项目背景与定位

2023 年 AI Agent 爆发期的标志性项目之一,AgentGPT 将自主 Agent 的能力带给了普通用户。

Before AgentGPT

  • AutoGPT 命令行操作
  • BabyAGI 需要编程
  • 门槛高、部署复杂

AgentGPT 的创新

  • 浏览器可视化界面
  • 零代码配置
  • 一键部署体验

生态影响

  • 推动了 Agent 框架发展
  • 验证了 Web Agent 范式
  • 开源社区标杆

🏗️ 核心架构总览

┌─────────────────────────────────────────────────────┐ │ 浏览器 (Next.js) │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │ Agent UI │ │ Chat │ │ Settings Panel │ │ │ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │ │ └──────────────┼─────────────────┘ │ │ │ REST / WebSocket │ ├──────────────────────┼──────────────────────────────┤ │ ▼ │ │ FastAPI 后端 │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │ API Router│ │ Agent │ │ Tool Registry │ │ │ │ │ │ Executor │ │ (Web/Code/KB) │ │ │ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │ │ │ │ │ │ │ ┌────┴─────┐ ┌────┴─────┐ ┌───────┴────────┐ │ │ │ Auth/JWT │ │ LLM │ │ Vector Store │ │ │ │ │ │ Provider │ │ (Pinecone) │ │ │ └──────────┘ └──────────┘ └────────────────┘ │ ├────────────────────────────────────────────────────┤ │ PostgreSQL + Redis + Pinecone │ └────────────────────────────────────────────────────┘

🛠️ 技术栈全景

前端

技术用途
Next.js 14React 框架
TypeScript类型安全
Tailwind CSS样式系统
NextAuth.js认证
Prisma ClientORM 客户端
Zustand状态管理

后端

技术用途
Python 3.11运行时
FastAPIWeb 框架
LangChainAgent 框架
OpenAI SDKGPT 调用
Pinecone向量存储
PostgreSQL关系数据库

⚛️ 前端架构 - Next.js

AgentGPT 前端基于 Next.js 14 App Router,采用 React Server Components + Client Components 混合架构。

关键设计

  • App Router 目录约定路由
  • Server Components 减少客户端 JS
  • Client Components 处理交互
  • Tailwind CSS 实用优先样式
  • API Routes 代理后端请求

状态管理

  • Zustand 轻量状态管理
  • WebSocket 实时更新 Agent 状态
  • React Query 数据缓存
  • URL 状态持久化

📁 前端目录结构

next/
├── src/
│   ├── app/                    # App Router
│   │   ├── (auth)/            # 认证相关页面
│   │   │   ├── login/
│   │   │   └── register/
│   │   ├── (workspace)/       # 工作区页面
│   │   │   ├── agent/[id]/    # Agent 详情
│   │   │   └── new/           # 创建 Agent
│   │   ├── api/               # API 代理路由
│   │   ├── layout.tsx         # 根布局
│   │   └── page.tsx           # 首页
│   ├── components/            # 组件库
│   │   ├── agent/             # Agent 相关组件
│   │   ├── ui/                # 通用 UI 组件
│   │   └── layout/            # 布局组件
│   ├── stores/                # Zustand 状态
│   ├── hooks/                 # 自定义 Hooks
│   ├── types/                 # TypeScript 类型
│   └── utils/                 # 工具函数
├── public/                    # 静态资源
├── tailwind.config.ts
├── next.config.js
└── package.json

🐍 后端架构 - FastAPI

后端使用 FastAPI 构建,基于 LangChain 实现 Agent 核心,支持异步任务处理和流式响应。

架构特点

  • 异步 ASGI 服务器(Uvicorn)
  • 依赖注入(DI)模式
  • 自动 OpenAPI 文档
  • Pydantic 数据校验
  • 后台任务队列

核心模块

  • web/api/ - REST API 路由
  • services/ - 业务逻辑层
  • db/ - 数据库操作
  • schemas/ - Pydantic 模型
  • settings.py - 配置管理

📁 后端目录结构

platform/
├── reworkd_platform/
│   ├── __init__.py
│   ├── __main__.py            # 入口
│   ├── settings.py            # 配置(Pydantic BaseSettings)
│   ├── constants.py           # 常量定义
│   ├── timer.py               # 计时器
│   ├── logging.py             # 日志配置
│   ├── web/
│   │   ├── application.py     # FastAPI app 创建
│   │   ├── lifetime.py        # 启动/关闭生命周期
│   │   └── api/
│   │       ├── v1/            # API v1 路由
│   │       │   ├── agent.py   # Agent 相关 API
│   │       │   ├── auth.py    # 认证 API
│   │       │   └── tool.py    # 工具 API
│   │       └── router.py      # 路由注册
│   ├── services/
│   │   ├── anthropic.py       # Anthropic 集成
│   │   ├── aws/               # AWS 服务
│   │   ├── pinecone/          # 向量存储
│   │   ├── tokenizer/         # Token 计数
│   │   ├── security.py        # 安全服务
│   │   └── oauth_installers.py
│   ├── db/                    # 数据库模型
│   └── schemas/               # Pydantic schemas
├── pyproject.toml             # Poetry 配置
├── Dockerfile
└── entrypoint.sh

🔄 Agent 核心循环

AgentGPT 采用经典的 Thought → Action → Observation 循环,Agent 持续思考并执行直到任务完成。

┌──────────┐ │ 用户输入 │ │ (目标) │ └────┬─────┘ ▼ ┌──────────┐ │ Thought │ ◄── LLM 推理:分析当前状态 │ (思考) │ 决定下一步行动 └────┬─────┘ ▼ ┌──────────┐ │ Action │ ◄── 选择工具 + 生成参数 │ (行动) │ (搜索/浏览/代码/记忆) └────┬─────┘ ▼ ┌──────────┐ │Observation│ ◄── 工具返回结果 │ (观察) │ 加入上下文 └────┬─────┘ ▼ ┌──────────┐ 否 │ 任务完成? │──────┐ └────┬─────┘ │ │ 是 │ ▼ ▼ ┌──────────┐ 回到 Thought │ 输出结果 │ └──────────┘

💻 Agent 循环源码

class AgentExecutor:
    """AgentGPT 核心 Agent 执行器"""

    def __init__(
        self,
        llm: BaseLanguageModel,
        tools: list[BaseTool],
        memory: BaseMemory,
        max_iterations: int = 15,
    ):
        self.llm = llm
        self.tools = tools
        self.memory = memory
        self.max_iterations = max_iterations

    async def execute(self, goal: str) -> AsyncIterator[AgentStep]:
        """执行 Agent 循环,流式返回每一步"""
        context = await self._build_context(goal)

        for i in range(self.max_iterations):
            # 1. 思考:让 LLM 分析当前状态
            thought = await self._think(context)

            # 2. 判断是否完成
            if thought.is_final_answer:
                yield AgentStep(
                    type="final",
                    output=thought.output,
                    iterations=i + 1,
                )
                return

            # 3. 行动:执行选中的工具
            observation = await self._act(thought)

            # 4. 更新上下文
            context = self._update_context(
                context, thought, observation
            )

            yield AgentStep(
                type="action",
                thought=thought,
                observation=observation,
            )

🧠 思考-行动-观察

Thought(思考)

LLM 接收当前上下文,包括:

  • 原始目标
  • 历史 Thought/Action/Observation
  • 可用工具列表

输出:推理链 + 行动决策

Observation(观察)

工具执行的结果被格式化后加入上下文,作为下一次 Thought 的输入。

Action(行动)

LLM 选择一个工具并生成参数:

{
  "tool": "web_search",
  "input": {
    "query": "AgentGPT latest features"
  }
}

终止条件

  • LLM 输出 "Final Answer"
  • 达到最大迭代次数
  • 发生不可恢复的错误

🧩 LLM 集成层

AgentGPT 通过 LangChainBaseLanguageModel 接口抽象 LLM 调用,支持多个提供商无缝切换。

┌─────────────────────────────┐ │ AgentExecutor │ │ (不关心具体 LLM) │ └──────────┬──────────────────┘ │ 依赖 ▼ ┌─────────────────────────────┐ │ BaseLanguageModel (LangChain)│ │ + predict() │ │ + predict_messages() │ │ + agenerate() │ └──────────┬──────────────────┘ │ 实现 ┌────────┼────────┐ ▼ ▼ ▼ ┌────────┐┌────────┐┌────────┐ │ OpenAI ││Anthropic││ Azure │ │ GPT-4 ││ Claude ││ OpenAI │ └────────┘└────────┘└────────┘

🔵 OpenAI 集成

# settings.py - 模型配置
class Settings(BaseSettings):
    openai_api_key: str = ""
    openai_organization: str | None = None
    openai_model: str = "gpt-4"
    openai_temperature: float = 0.7
    openai_max_tokens: int = 1000

    # Token 限制
    model_token_limit: int = 8192

    class Config:
        env_prefix = ""  # 直接读取环境变量
# services/llm_factory.py
from langchain.chat_models import ChatOpenAI

def create_openai_llm(settings: Settings) -> ChatOpenAI:
    """创建 OpenAI LLM 实例"""
    return ChatOpenAI(
        model=settings.openai_model,
        temperature=settings.openai_temperature,
        max_tokens=settings.openai_max_tokens,
        openai_api_key=settings.openai_api_key,
        openai_organization=settings.openai_organization,
        streaming=True,  # 支持流式输出
    )

🟣 Anthropic 集成

# services/anthropic.py
from langchain.chat_models import ChatAnthropic

def create_anthropic_llm(settings: Settings) -> ChatAnthropic:
    """创建 Anthropic Claude LLM 实例"""
    return ChatAnthropic(
        model="claude-3-opus-20240229",
        temperature=settings.anthropic_temperature,
        max_tokens=settings.anthropic_max_tokens,
        anthropic_api_key=settings.anthropic_api_key,
        streaming=True,
    )

# LLM 工厂 - 根据配置自动选择
def create_llm(settings: Settings) -> BaseLanguageModel:
    """根据配置创建对应的 LLM"""
    if settings.model_provider == "openai":
        return create_openai_llm(settings)
    elif settings.model_provider == "anthropic":
        return create_anthropic_llm(settings)
    elif settings.model_provider == "azure":
        return create_azure_llm(settings)
    else:
        raise ValueError(
            f"Unknown provider: {settings.model_provider}"
        )

🔧 工具系统架构

工具是 AgentGPT 的"手脚",通过 LangChain BaseTool 标准接口实现,Agent 通过自然语言决策调用哪个工具。

┌─────────────────────────────────────┐ │ BaseTool (LangChain) │ │ + name: str │ │ + description: str │ │ + args_schema: Pydantic BaseModel │ │ + _run(input) -> str │ │ + _arun(input) -> str (async) │ └──────────┬──────────────────────────┘ │ 实现 ┌──────────┼──────────┬──────────┬──────────┐ ▼ ▼ ▼ ▼ ┌────────┐┌────────┐┌────────┐┌────────┐ │Search ││Browse ││Code ││Knowledge│ │Engine ││Web ││Execute ││Graph │ └────────┘└────────┘└────────┘└────────┘

📐 Tool 接口定义

from langchain.tools import BaseTool
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    """搜索工具的输入 Schema"""
    query: str = Field(
        description="搜索查询关键词"
    )
    num_results: int = Field(
        default=5,
        description="返回结果数量"
    )

class WebSearchTool(BaseTool):
    """网页搜索工具"""
    name = "web_search"
    description = (
        "用于在互联网上搜索信息。"
        "输入搜索查询,返回相关网页结果。"
    )
    args_schema = SearchInput

    def _run(self, query: str, num_results: int = 5) -> str:
        """同步执行搜索"""
        return self._search(query, num_results)

    async def _arun(
        self, query: str, num_results: int = 5
    ) -> str:
        """异步执行搜索(Agent 使用此方法)"""
        return await self._async_search(query, num_results)

🧰 内置工具一览

工具名功能底层实现用途场景
web_search 网页搜索 DuckDuckGo / SerpAPI 信息检索、事实查询
web_browser 网页浏览 Selenium / Playwright 读取网页内容、填表
code_execution 代码执行 沙箱 Python 解释器 计算、数据处理
knowledge_graph 知识图谱 Pinecone 向量存储 长期记忆存取
writing 文本写入 文件系统 生成报告、保存结果

🔍 网页搜索工具

class WebSearchTool(BaseTool):
    """基于 DuckDuckGo 的网页搜索"""
    name = "web_search"
    description = "搜索互联网获取最新信息"

    async def _arun(self, query: str) -> str:
        # 使用 DuckDuckGo 搜索
        async with aiohttp.ClientSession() as session:
            params = {
                "q": query,
                "format": "json",
                "no_html": 1,
            }
            async with session.get(
                "https://api.duckduckgo.com/",
                params=params
            ) as resp:
                data = await resp.json()

        # 格式化搜索结果
        results = []
        for item in data.get("RelatedTopics", [])[:5]:
            if "Text" in item:
                results.append(
                    f"- {item['FirstURL']}\n"
                    f"  {item['Text']}"
                )

        return "\n".join(results) if results \
            else "No results found."

🌐 网页浏览工具

class WebBrowserTool(BaseTool):
    """网页内容提取工具"""
    name = "web_browser"
    description = "浏览并提取网页内容"

    async def _arun(self, url: str) -> str:
        try:
            # 获取网页内容
            async with aiohttp.ClientSession() as s:
                async with s.get(url, timeout=10) as r:
                    html = await r.text()

            # 使用 BeautifulSoup 提取文本
            soup = BeautifulSoup(html, "html.parser")

            # 移除脚本和样式
            for tag in soup(
                ["script", "style", "nav", "footer"]
            ):
                tag.decompose()

            text = soup.get_text(
                separator="\n", strip=True
            )

            # 截断过长内容
            return text[:4000] if len(text) > 4000 \
                else text

        except Exception as e:
            return f"Error browsing {url}: {str(e)}"

💻 代码执行工具

class CodeExecutionTool(BaseTool):
    """安全的 Python 代码执行环境"""
    name = "code_execution"
    description = (
        "在沙箱中执行 Python 代码。"
        "可用于数学计算、数据分析。"
    )

    # 允许的模块白名单
    ALLOWED_MODULES = {
        "math", "json", "re", "datetime",
        "collections", "statistics", "itertools",
    }

    async def _arun(self, code: str) -> str:
        """在受限环境中执行代码"""
        # 限制可用模块
        restricted_globals = {
            "__builtins__": {
                k: v for k, v in __builtins__.items()
                if k in ("print", "len", "range",
                         "int", "float", "str", "list",
                         "dict", "set", "tuple", "abs",
                         "min", "max", "sum", "sorted")
            },
            **{
                m: __import__(m)
                for m in self.ALLOWED_MODULES
            },
        }
        # 执行并捕获输出
        stdout = StringIO()
        with redirect_stdout(stdout):
            exec(code, restricted_globals, {})

        return stdout.getvalue() or "Code executed."

🧠 知识图谱工具

class KnowledgeGraphTool(BaseTool):
    """基于 Pinecone 的长期记忆工具"""
    name = "knowledge_graph"
    description = (
        "存储和检索长期记忆。"
        "可用于记住重要信息和经验。"
    )

    def __init__(self, pinecone_client, embedding_model):
        super().__init__()
        self.pinecone = pinecone_client
        self.embeddings = embedding_model
        self.index_name = "agent-memory"
        self.namespace = "agent-v1"

    async def _arun(self, command: str) -> str:
        """支持 store/retrieve 命令"""
        if command.startswith("store:"):
            content = command[6:].strip()
            return await self._store(content)
        elif command.startswith("retrieve:"):
            query = command[9:].strip()
            return await self._retrieve(query)

    async def _store(self, content: str) -> str:
        vector = await self.embeddings.aembed(content)
        self.pinecone.Index(self.index_name).upsert(
            vectors=[{
                "id": str(uuid4()),
                "values": vector,
                "metadata": {"text": content}
            }],
            namespace=self.namespace,
        )
        return "Memory stored."

⚡ 工具调用流程

Agent LLM Tool Registry │ │ │ │ 1. 发送上下文 + 工具列表 │ │ │───────────────────────►│ │ │ │ │ │ 2. 返回 Thought + │ │ │ Action(tool, args) │ │ │◄───────────────────────│ │ │ │ │ │ 3. 查找并验证工具 │ │ │─────────────────────────────────────────────────►│ │ │ │ │ 4. 工具描述 + Schema │ │ │◄─────────────────────────────────────────────────│ │ │ │ │ 5. 执行工具(args) │ │ │─────────────────────────────────────────────────►│ │ │ │ │ 6. Observation 结果 │ │ │◄─────────────────────────────────────────────────│ │ │ │ │ 7. 将 Observation │ │ │ 加入上下文,继续循环 │ │

💾 向量记忆系统

AgentGPT 使用 Pinecone 向量数据库实现长期记忆,Agent 可以跨会话存储和检索信息。

记忆架构

  • 短期记忆:当前会话上下文
  • 长期记忆:Pinecone 向量存储
  • 工作记忆:当前任务的中间状态

向量化流程

  • 文本 → Embedding 向量
  • OpenAI text-embedding-ada-002
  • 相似度检索(余弦距离)
  • 自动过期与清理

🌲 Pinecone 集成

# services/pinecone/client.py
from pinecone import Pinecone

class MemoryStore:
    """Pinecone 向量记忆存储"""

    def __init__(self, settings: Settings):
        self.client = Pinecone(
            api_key=settings.pinecone_api_key
        )
        self.index_name = settings.pinecone_index
        self.dimension = 1536  # ada-002 维度

    async def ensure_index(self):
        """确保索引存在"""
        if self.index_name not in \
            self.client.list_indexes().names():
            self.client.create_index(
                name=self.index_name,
                dimension=self.dimension,
                metric="cosine",
                metadata_config={
                    "indexed": ["agent_id", "created_at"]
                },
            )

    async def search(
        self, query_vector: list, top_k: int = 5,
        filter_dict: dict = None
    ) -> list[MemoryRecord]:
        """语义搜索相似记忆"""
        index = self.client.Index(self.index_name)
        results = index.query(
            vector=query_vector,
            top_k=top_k,
            include_metadata=True,
            filter=filter_dict,
        )
        return [
            MemoryRecord(
                id=m["id"],
                text=m["metadata"]["text"],
                score=m["score"],
            )
            for m in results["matches"]
        ]

💾 记忆存取源码

# services/pinecone/memory.py
class AgentMemory:
    """Agent 记忆管理器"""

    def __init__(
        self,
        store: MemoryStore,
        embeddings: Embeddings,
        agent_id: str,
    ):
        self.store = store
        self.embeddings = embeddings
        self.agent_id = agent_id

    async def save(self, text: str) -> str:
        """保存记忆到向量存储"""
        vector = await self.embeddings.aembed(text)
        record_id = str(uuid4())

        self.store.upsert(
            id=record_id,
            values=vector,
            metadata={
                "text": text,
                "agent_id": self.agent_id,
                "created_at": datetime.utcnow().isoformat(),
            },
        )
        return record_id

    async def recall(
        self, query: str, top_k: int = 3
    ) -> list[str]:
        """检索相关记忆"""
        query_vector = \
            await self.embeddings.aembed(query)
        results = await self.store.search(
            query_vector,
            top_k=top_k,
            filter_dict={"agent_id": self.agent_id},
        )
        return [r.text for r in results]

🗄️ 数据库设计

AgentGPT 使用 PostgreSQL 作为主数据库,通过 Prisma ORM(前端)和 SQLAlchemy(后端)操作。

┌──────────────┐ ┌──────────────┐ │ User │ │ Agent │ ├──────────────┤ ├──────────────┤ │ id │◄──┐ │ id │ │ email │ │ │ user_id (FK)│──┐ │ name │ │ │ name │ │ │ password_hash│ │ │ goal │ │ │ created_at │ │ │ model │ │ └──────────────┘ │ │ settings │ │ │ │ created_at │ │ │ └──────────────┘ │ │ │ │ ┌──────────────┐ │ │ │ AgentRun │ │ │ ├──────────────┤ │ │ │ id │ │ │ │ agent_id (FK)│◄─┘ │ │ status │ │ │ steps (JSON) │ │ │ result │ │ │ created_at │ │ └──────────────┘ └─────────────────────

📊 Prisma Schema

// prisma/schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id           String    @id @default(cuid())
  email        String    @unique
  name         String?
  image        String?
  emailVerified DateTime?
  accounts     Account[]
  sessions     Session[]
  agents       Agent[]
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @updatedAt
}

model Agent {
  id        String      @id @default(cuid())
  userId    String
  user      User        @relation(
    fields: [userId], references: [id]
  )
  name      String
  goal      String
  model     String      @default("gpt-4")
  settings  Json        @default("{}")
  runs      AgentRun[]
  createdAt DateTime    @default(now())
  updatedAt DateTime    @updatedAt
}

model AgentRun {
  id        String   @id @default(cuid())
  agentId   String
  agent     Agent    @relation(
    fields: [agentId], references: [id]
  )
  status    String   // running/success/failed
  steps     Json     // AgentStep[]
  result    String?
  createdAt DateTime @default(now())
}

🔐 认证与安全

认证方案

NextAuth.js 处理前端认证:

  • OAuth(Google/GitHub)
  • 邮箱密码登录
  • JWT Session
  • CSRF 保护

后端 JWT 验证

  • Bearer Token 认证
  • Token 过期刷新
  • API Key 支持

安全措施

# services/security.py
from passlib.context import \
    CryptContext

pwd_context = CryptContext(
    schemes=["bcrypt"],
    deprecated="auto",
)

def verify_password(
    plain: str, hashed: str
) -> bool:
    return pwd_context.verify(
        plain, hashed
    )

def hash_password(
    password: str
) -> str:
    return pwd_context.hash(password)

🌐 API 路由设计

方法路径功能
POST/api/v1/agents创建 Agent
GET/api/v1/agents获取 Agent 列表
GET/api/v1/agents/{id}获取 Agent 详情
POST/api/v1/agents/{id}/run启动 Agent 执行
POST/api/v1/agents/{id}/stop停止 Agent
GET/api/v1/agents/{id}/runs获取执行历史
POST/api/v1/auth/login用户登录
POST/api/v1/auth/register用户注册
GET/api/v1/auth/me获取当前用户

📡 WebSocket 实时通信

# web/api/v1/agent.py
from fastapi import WebSocket, WebSocketDisconnect

@router.websocket("/ws/agent/{agent_id}")
async def agent_websocket(
    websocket: WebSocket,
    agent_id: str,
    current_user: User = Depends(
        get_current_user_ws
    ),
):
    await websocket.accept()

    try:
        # 验证 Agent 归属
        agent = await verify_agent_owner(
            agent_id, current_user.id
        )

        # 启动 Agent 并流式推送
        async for step in agent_executor.execute(
            agent.goal
        ):
            await websocket.send_json({
                "type": step.type,
                "data": {
                    "thought": step.thought,
                    "action": step.action,
                    "observation": step.observation,
                    "iteration": step.iterations,
                },
            })

    except WebSocketDisconnect:
        logger.info("Client disconnected")
    except Exception as e:
        await websocket.send_json({
            "type": "error",
            "data": {"message": str(e)},
        })

📦 前端状态管理

// stores/agentStore.ts
import { create } from 'zustand';

interface AgentState {
  agents: Agent[];
  currentAgent: Agent | null;
  isRunning: boolean;
  steps: AgentStep[];

  // Actions
  createAgent: (name: string, goal: string) 
    => Promise<void>;
  startRun: (agentId: string) => AsyncGenerator;
  stopRun: () => void;
  addStep: (step: AgentStep) => void;
}

export const useAgentStore = create<AgentState>(
  (set, get) => ({
    agents: [],
    currentAgent: null,
    isRunning: false,
    steps: [],

    createAgent: async (name, goal) => {
      const res = await fetch('/api/agents', {
        method: 'POST',
        body: JSON.stringify({ name, goal }),
      });
      const agent = await res.json();
      set((s) => ({
        agents: [...s.agents, agent]
      }));
    },

    startRun: async (agentId) => {
      set({ isRunning: true, steps: [] });
      const ws = new WebSocket(
        `/ws/agent/${agentId}`
      );
      ws.onmessage = (e) => {
        const step = JSON.parse(e.data);
        set((s) => ({
          steps: [...s.steps, step]
        }));
      };
    },
  })
);

🎨 Agent UI 组件

核心组件

  • AgentCard - Agent 列表卡片
  • AgentRunner - 执行界面
  • StepTimeline - 步骤时间线
  • ThoughtBubble - 思考气泡
  • ToolResult - 工具结果展示
  • AgentConfig - 配置面板

UI 设计理念

  • 实时流式更新(WebSocket)
  • 每步可视化展示
  • 深色主题 + 渐变
  • 响应式移动端适配
  • 骨架屏加载状态

交互流程:创建 Agent → 配置目标和工具 → 点击运行 → 实时查看步骤 → 查看最终结果

📝 Prompt 工程策略

AgentGPT 的 Prompt 设计是核心竞争力的关键,直接影响 Agent 的推理质量和工具选择准确性。

Prompt 组成

  • System Prompt:角色定义 + 规则
  • 目标描述:用户输入的目标
  • 工具说明:每个工具的描述和参数
  • 历史记录:之前的 Thought/Action
  • 格式约束:JSON 输出格式

设计原则

  • 清晰的输出格式要求
  • 明确的终止条件
  • 工具使用指导
  • 错误处理指引
  • Token 预算控制

🎯 System Prompt 设计

SYSTEM_PROMPT = """
You are an autonomous AI agent. Your goal is to
achieve the user's objective using available tools.

## Available Tools
{tool_descriptions}

## Instructions
1. Analyze the current context and your goal
2. Choose the most appropriate tool to use
3. Provide the tool name and input arguments
4. If you have enough information, provide
   the final answer

## Response Format
Respond ONLY with valid JSON:
{{
  "thought": "Your reasoning process",
  "tool": "tool_name or 'final'",
  "input": {{ "key": "value" }} or null,
  "output": "final answer if done"
}}

## Constraints
- You have {max_iterations} iterations
- Be concise and efficient
- Prioritize accuracy over speed
- Use tools to gather information before answering
"""

📊 Token 管理策略

Token 预算

# services/tokenizer/counter.py
class TokenBudget:
    """Token 预算管理器"""

    def __init__(
        self,
        model_limit: int = 8192,
        reserve_output: int = 1000,
    ):
        self.total = model_limit
        self.reserve = reserve_output
        self.available = model_limit \
            - reserve_output

    def allocate(self, parts: dict) -> dict:
        """按比例分配 Token"""
        total_input = sum(parts.values())
        return {
            k: int(
                self.available * v / total_input
            )
            for k, v in parts.items()
        }

上下文裁剪

def trim_context(
    messages: list[dict],
    max_tokens: int,
    counter: TokenCounter,
) -> list[dict]:
    """裁剪历史消息以适应 Token 限制"""
    trimmed = []
    total = 0

    # 保留 System Prompt
    trimmed.append(messages[0])
    total += counter.count(messages[0])

    # 从最新消息开始保留
    for msg in reversed(messages[1:]):
        cost = counter.count(msg)
        if total + cost > max_tokens:
            break
        trimmed.insert(1, msg)
        total += cost

    return trimmed

⚠️ 错误处理与重试

# services/retry.py
from tenacity import (
    retry,
    stop_after_attempt,
    wait_exponential,
    retry_if_exception_type,
)

class AgentError(Exception):
    """Agent 执行错误基类"""

class LLMRateLimitError(AgentError):
    """LLM 速率限制"""

class ToolExecutionError(AgentError):
    """工具执行错误"""

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(
        min=1, max=60, multiplier=2
    ),
    retry=retry_if_exception_type(
        (LLMRateLimitError, TimeoutError)
    ),
    before_sleep=lambda _: logger.warning(
        "Retrying after rate limit..."
    ),
)
async def call_llm_with_retry(
    llm: BaseLanguageModel,
    messages: list[dict],
) -> str:
    """带重试的 LLM 调用"""
    try:
        return await llm.apredict(messages=messages)
    except RateLimitError as e:
        raise LLMRateLimitError(
            f"Rate limited: {e}"
        ) from e

🚦 并发与限流

并发控制

import asyncio

class ConcurrencyLimiter:
    """Agent 并发执行限制"""

    def __init__(self, max_concurrent: int = 5):
        self.semaphore = asyncio.Semaphore(
            max_concurrent
        )
        self.active_tasks: dict[
            str, asyncio.Task
        ] = {}

    async def run_agent(
        self, agent_id: str, goal: str
    ):
        async with self.semaphore:
            task = asyncio.current_task()
            self.active_tasks[agent_id] = task
            try:
                async for step in \
                    executor.execute(goal):
                    yield step
            finally:
                del self.active_tasks[
                    agent_id
                ]

限流策略

  • 用户级限流:每用户同时 3 个 Agent
  • API 限流:100 req/min
  • LLM 限流:尊重提供商限制
  • 工具限流:搜索 10 次/分钟

优雅降级

  • 队列等待而非拒绝
  • 优先级调度
  • 超时自动取消

🐳 Docker 部署架构

┌─────────────────────────────────────────────────┐ │ Docker Compose │ │ │ │ ┌──────────────┐ ┌──────────────────────┐ │ │ │ Next.js │ │ FastAPI │ │ │ │ (Port 3000)│ │ (Port 8000) │ │ │ │ │◄──►│ │ │ │ └──────────────┘ └──────────┬───────────┘ │ │ │ │ │ ┌────────────────────────┼──────┐ │ │ │ │ │ │ │ ┌──────┴──────┐ ┌──────────────┴──┐ ┌┴─────┐ │ │ │ PostgreSQL │ │ Redis │ │Nginx │ │ │ │ (Port 5432) │ │ (Port 6379) │ │(80) │ │ │ └─────────────┘ └─────────────────┘ └──────┘ │ │ │ │ ┌─────────────┐ (External) │ │ │ Pinecone │◄──── 云端向量数据库 │ │ │ (Cloud) │ │ │ └─────────────┘ │ └─────────────────────────────────────────────────┘

⚙️ Docker Compose 配置

# docker-compose.yml
version: "3.9"

services:
  frontend:
    build:
      context: ./next
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - NEXTAUTH_SECRET=${AUTH_SECRET}
      - DATABASE_URL=${DATABASE_URL}
    depends_on:
      - postgres

  backend:
    build:
      context: ./platform
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - PINECONE_API_KEY=${PINECONE_API_KEY}
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis

  postgres:
    image: pgvector/pgvector:pg16
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: agentgpt
      POSTGRES_PASSWORD: ${DB_PASSWORD}

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  pgdata:

♟️ 设计模式 - 策略模式

LLM Provider 切换:通过策略模式实现多 LLM 提供商的灵活切换,符合开闭原则。

# 策略接口
class LLMStrategy(ABC):
    @abstractmethod
    async def generate(self, prompt: str) -> str:
        ...

# 具体策略
class OpenAIStrategy(LLMStrategy):
    async def generate(self, prompt: str) -> str:
        return await self.client.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}]
        )

class AnthropicStrategy(LLMStrategy):
    async def generate(self, prompt: str) -> str:
        return await self.client.messages.create(
            model="claude-3-opus",
            messages=[{"role": "user", "content": prompt}]
        )

# 上下文
class AgentContext:
    def __init__(self, strategy: LLMStrategy):
        self._strategy = strategy

    def set_strategy(self, strategy: LLMStrategy):
        self._strategy = strategy

    async def think(self, prompt: str) -> str:
        return await self._strategy.generate(prompt)

👁️ 设计模式 - 观察者模式

Agent 步骤通知:通过观察者模式实现 Agent 执行步骤的实时推送,解耦 Agent 执行与 UI 更新。

class AgentEventEmitter:
    """Agent 事件发射器"""

    def __init__(self):
        self._listeners: dict[
            str, list[Callable]
        ] = {}

    def on(self, event: str, callback: Callable):
        if event not in self._listeners:
            self._listeners[event] = []
        self._listeners[event].append(callback)

    async def emit(self, event: str, data: Any):
        for callback in self._listeners.get(
            event, []
        ):
            await callback(data)

# 使用
emitter = AgentEventEmitter()

# WebSocket 订阅
emitter.on("step", websocket.send_json)
emitter.on("error", log_error)
emitter.on("complete", save_result)

# Agent 执行中发射事件
await emitter.emit("step", step_data)

🏭 设计模式 - 工厂模式

工具创建:通过工厂模式根据配置动态创建工具实例,支持灵活的工具组合。

class ToolFactory:
    """工具工厂 - 根据配置创建工具"""

    _registry: dict[str, type[BaseTool]] = {
        "web_search": WebSearchTool,
        "web_browser": WebBrowserTool,
        "code_execution": CodeExecutionTool,
        "knowledge_graph": KnowledgeGraphTool,
    }

    @classmethod
    def register(
        cls, name: str, tool_class: type[BaseTool]
    ):
        """注册自定义工具"""
        cls._registry[name] = tool_class

    @classmethod
    def create_tools(
        cls, tool_names: list[str], **kwargs
    ) -> list[BaseTool]:
        """批量创建工具实例"""
        tools = []
        for name in tool_names:
            if name not in cls._registry:
                raise ValueError(
                    f"Unknown tool: {name}"
                )
            tool = cls._registry[name](**kwargs)
            tools.append(tool)
        return tools

🔄 Agent 执行流程

用户点击"运行" │ ▼ ┌─────────────┐ │ 创建 AgentRun │ ← 保存到 PostgreSQL │ status=running│ └──────┬──────┘ ▼ ┌─────────────┐ │ 加载记忆 │ ← 从 Pinecone 检索相关记忆 │ 构建上下文 │ ← System Prompt + 工具列表 + 历史 └──────┬──────┘ ▼ ╔═════════════╗ ║ Agent Loop ║ ◄─── 核心循环 ╠═════════════╣ ║ 1. 调用 LLM ║ ← 发送上下文给 GPT-4 ║ 2. 解析响应 │ ← JSON → Thought + Action ║ 3. 检查终止 │ ← 是否 Final Answer? ║ 4. 执行工具 │ ← 工具名 + 参数 ║ 5. 推送步骤 │ ← WebSocket → 前端 ║ 6. 更新上下文│ ← 加入 Observation ║ 7. 裁剪Token │ ← 保持上下文在限制内 ╚═══════╤═════╝ │ 完成/超时 ▼ ┌─────────────┐ │ 保存结果 │ ← 更新 AgentRun status │ 存储新记忆 │ ← 重要信息存入 Pinecone └─────────────┘

⚖️ 与 AutoGPT/BabyAGI 对比

特性AgentGPTAutoGPTBabyAGI
界面 Web 浏览器 命令行 命令行
语言 Python + TS Python Python
部署 Docker Compose 本地安装 本地安装
实时性 WebSocket 流式 终端输出 终端输出
多用户 ✅ 支持 ❌ 单用户 ❌ 单用户
长期记忆 Pinecone 本地 JSON ChromaDB
任务管理 简单队列 任务列表 优先级队列

⚡ 性能优化实践

LLM 调用优化

  • 流式输出减少等待
  • Prompt 压缩减少 Token
  • 缓存相似查询
  • 并行工具调用
  • 模型降级策略

数据库优化

  • 连接池管理
  • 查询索引优化
  • JSON 列压缩
  • 定期清理历史
  • 读写分离

前端优化

  • React Server Components
  • 虚拟滚动长列表
  • WebSocket 减少轮询
  • 代码分割懒加载
  • 图片资源优化

🐛 常见陷阱与调试

常见问题

  • 死循环:Agent 重复相同操作
  • 幻觉:LLM 编造不存在的工具
  • Token 溢出:上下文超过限制
  • 工具失败:网络超时/格式错误
  • 过早终止:Agent 未完成就停止

解决方案

  • 设置最大迭代 + 循环检测
  • 严格的 JSON Schema 约束
  • 自动上下文裁剪
  • 工具重试 + 超时控制
  • Prompt 中强调完成目标

调试技巧:启用详细日志 → 检查每步 Thought → 验证工具输入 → 确认上下文窗口使用率

📚 扩展阅读

官方资源

相关项目

推荐论文

  • ReAct: Reasoning and Acting
  • Toolformer: Language Models Can Teach Themselves to Use Tools
  • Generative Agents: Interactive Simulacra of Human Behavior
  • Chain-of-Thought Prompting

关键概念

  • Thought-Action-Observation Loop
  • Tool Augmented Generation
  • Vector Memory Retrieval
  • Prompt Engineering Patterns

📝 总结

核心架构亮点

  • 前后端分离:Next.js + FastAPI 清晰分层
  • Agent 循环:Thought → Action → Observation 经典范式
  • 工具抽象:LangChain BaseTool 标准接口
  • 向量记忆:Pinecone 实现跨会话记忆
  • 实时通信:WebSocket 流式推送
  • 多 LLM:策略模式支持提供商切换

工程实践

  • Docker Compose 一键部署
  • Prisma + PostgreSQL 数据持久化
  • NextAuth.js 安全认证
  • Token 预算自动管理
  • 重试机制 + 优雅降级
  • 并发限制 + 速率控制

AgentGPT 是一个优秀的 AI Agent 框架参考实现,它展示了如何将 LLM 推理、工具调用、长期记忆和 Web UI 有机结合,构建一个可用的智能体平台。

🤖 感谢阅读

AgentGPT Source Code Deep Dive

源码地址
https://github.com/reworkd/AgentGPT

访问链接: https://atcfu.com/ai-articles/agentgpt-browser-agent/