从零拆解 AI 智能体本质:150 行代码实现 pi-agent 核心循环

从零拆解 AI 智能体本质:150 行代码实现 pi-agent 核心循环

AI 智能体不是黑盒——用 100 行代码手写 pi-agent 核心循环,看懂 LLM 如何”思考-行动-迭代”地独立完成任务。

一、智能体的本质:从“聊天”到“做事”

在拆解 pi-agent 之前,先理解一个核心问题:AI 智能体(Agent)和普通聊天机器人(Chatbot)到底有什么区别?

维度 聊天机器人 AI 智能体
工作方式 单轮/多轮对话,模型被动响应 接受目标,自己规划步骤并执行,必要时主动交互
核心能力 理解、生成自然语言 推理、规划、调用工具、维护记忆、迭代执行
任务范围 较窄,通常是信息检索、简答 较广,包括搜索、调用工具、调度流程、持续监控任务进展
工作模式 用户指令 → 生成内容 → 用户执行 用户目标 → Agent规划 → Agent执行 → 结果反馈

简单说:Chatbot 负责“说”,Agent 负责“做” 。而 pi-agent 就是一套开源的“怎么做”的完整实现。


二、pi-agent 架构拆解

pi-agent 是 MIT 协议的开源 AI 编程 Agent,整个核心约 150 行代码,非常精简。按技术栈看,它是 TypeScript 写的 pi-mono monorepo 的一部分,包含 7 个核心包:

pi-mono/
├── pi-ai           # 统一多提供商 LLM API(20+ 提供商)
├── pi-tui          # 终端 UI 库
├── pi-agent-core   # Agent 运行时(循环、状态机)
├── pi-coding-agent # 编程 Agent CLI/SDK(内置工具、扩展系统)
├── pi-web-ui       # Web UI 组件
├── pi-mom          # Slack 机器人
└── pi-pods         # GPU Pod 管理器

其核心架构可以这样理解:

┌─────────────────────────────────────────────────────────────┐
│                   用户(CLI / Web)                         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│              Agent Loop(~150行核心)                       │
│         ReAct 循环:思考 → 行动 → 观察 → 重复              │
└─────────────────────────────────────────────────────────────┘
              │                              │
              ▼                              ▼
┌─────────────────────────┐   ┌─────────────────────────────┐
│    LLM Providers        │   │    Tools 系统               │
│ Claude · GPT · Groq ·   │   │ read_file · write_file ·    │
│ Gemini · Ollama · ...   │   │ grep · run_command · git ·  │
│ (20+ 统一接口)        │   │ web_fetch · analyze_data ·  │
└─────────────────────────┘   │ make_slides · delegate ·    │
                              │ update_plan · remember      │
                              └─────────────────────────────┘

三、智能体的灵魂:Agent Loop(核心循环)

pi-agent 最核心的部分就是 Agent Loop,这也是所有 AI Agent 的本质:一个迭代执行的“推理-行动-观察”闭环

在 pi-agent 中,这个循环大致是:

用户输入 Prompt
       ↓
┌──────────────────────────────────────┐
│  1. LLM 推理(规划下一步)           │
│     → 决定调用哪个工具               │
│     → 生成 tool_calls               │
├──────────────────────────────────────┤
│  2. 执行工具                         │
│     → 读文件 / 写代码 / 运行命令     │
│     → 返回执行结果                   │
├──────────────────────────────────────┤
│  3. 观察结果                         │
│     → 将结果追加到对话上下文         │
│     → LLM 判断:完成还是继续?       │
└──────────────────────────────────────┘
       ↓ 重复直到目标达成
   输出最终结果

这就是 ReAct(Reasoning + Acting)模式:LLM 不再是“一次性生成答案”,而是在循环中交替思考和使用工具,每一步都基于上一步的观察结果来做决策。


四、代码演示:用 ~100 行实现最小 Agent

为了理解本质,我们可以自己实现一个极简版 pi-agent 风格的 Agent。这里用 Python 来演示核心逻辑(pi-agent 本身是 TypeScript,但核心思想完全一致):

"""
极简 ReAct Agent 实现 —— 演示智能体本质
对标 pi-agent 的核心循环 (~150行)
"""

import json
from typing import List, Dict, Any, Callable
from openai import OpenAI  # 可替换为任意 LLM 接口

# ============================================================
# 1. 工具定义(对应 pi-agent 的 tools/ 目录)
# ============================================================

class Tool:
    """工具基类,对应 pi-agent 的 Tool spec"""
    def __init__(self, name: str, description: str, func: Callable):
        self.name = name
        self.description = description
        self.func = func

    def to_openai_schema(self) -> Dict:
        """转为 OpenAI function calling 格式"""
        return {
            "type": "function",
            "function": {
                "name": self.name,
                "description": self.description,
                "parameters": {"type": "object", "properties": {}}
            }
        }

    def execute(self, **kwargs) -> str:
        return str(self.func(**kwargs))


# 定义几个 pi-agent 风格的工具
def read_file(path: str) -> str:
    """对应 pi-agent 的 read_file tool"""
    try:
        with open(path, 'r') as f:
            return f.read()[:500] + "..."  # 截断防爆
    except Exception as e:
        return f"Error: {e}"

def write_file(path: str, content: str) -> str:
    """对应 pi-agent 的 write_file tool"""
    try:
        with open(path, 'w') as f:
            f.write(content)
        return f"Successfully wrote to {path}"
    except Exception as e:
        return f"Error: {e}"

def run_command(cmd: str) -> str:
    """对应 pi-agent 的 run_command(沙箱版)"""
    import subprocess
    try:
        # ⚠️ 实际生产需要沙箱隔离,这里做简化演示
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10)
        return result.stdout or result.stderr or "(no output)"
    except Exception as e:
        return f"Error: {e}"

def list_dir(path: str = ".") -> str:
    """对应 pi-agent 的 list_dir tool"""
    import os
    try:
        items = os.listdir(path)
        return "\n".join(items[:20])
    except Exception as e:
        return f"Error: {e}"


# ============================================================
# 2. Agent 核心循环(对应 pi-agent 的 agent.py)
# ============================================================

class MinimalAgent:
    """
    极简 ReAct Agent
    对应 pi-agent 的 agent.py 核心逻辑:provider-neutral transcript + loop
    """

    def __init__(self, model: str = "gpt-4", system_prompt: str = None):
        self.client = OpenAI()
        self.model = model
        self.messages: List[Dict[str, str]] = []
        self.tools: Dict[str, Tool] = {}

        # 系统提示(对应 pi-agent 的 config.py system prompt)
        self.system_prompt = system_prompt or """你是 pi-agent,一个自主的 AI 编程助手。
你可以使用工具来读写文件、运行命令、列出目录。
请按 ReAct 模式工作:思考需要做什么,调用工具,观察结果,然后决定下一步。
当任务完成时,给出最终答案。"""

        self.messages.append({"role": "system", "content": self.system_prompt})

    def register_tool(self, tool: Tool):
        """注册工具(对应 pi-agent 的 tools/registry.py)"""
        self.tools[tool.name] = tool

    def get_tool_schemas(self) -> List[Dict]:
        return [t.to_openai_schema() for t in self.tools.values()]

    def run(self, user_prompt: str, max_iterations: int = 10) -> str:
        """
        Agent 主循环 —— 这就是智能体的本质!
        对应 pi-agent 的 tool-use loop
        """
        # 添加用户消息
        self.messages.append({"role": "user", "content": user_prompt})

        iteration = 0
        while iteration < max_iterations:
            iteration += 1
            print(f"\n🔄 [Iteration {iteration}] 思考中...")

            # -------- 步骤 1: 调用 LLM(推理 + 决策) --------
            response = self.client.chat.completions.create(
                model=self.model,
                messages=self.messages,
                tools=self.get_tool_schemas() if self.tools else None,
                tool_choice="auto",
            )

            message = response.choices[0].message
            self.messages.append(message.model_dump())  # 保存助手消息

            # -------- 步骤 2: 检查是否有工具调用 --------
            if not message.tool_calls:
                # 没有工具调用 → 任务完成,返回最终答案
                print("✅ 任务完成,无更多工具调用")
                return message.content or "(无输出)"

            # -------- 步骤 3: 执行工具(Action) --------
            for tool_call in message.tool_calls:
                tool_name = tool_call.function.name
                tool_args = json.loads(tool_call.function.arguments)

                print(f"🔧 调用工具: {tool_name}({tool_args})")

                # 查找并执行工具
                if tool_name in self.tools:
                    try:
                        result = self.tools[tool_name].execute(**tool_args)
                    except Exception as e:
                        result = f"工具执行异常: {e}"
                else:
                    result = f"未知工具: {tool_name}"

                print(f"📋 观察结果: {result[:200]}...")

                # -------- 步骤 4: 将工具结果追加到消息(Observation) --------
                self.messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": result
                })

            # 🔁 循环继续 —— 带着新观察结果再次调用 LLM

        return "⚠️ 达到最大迭代次数,任务可能未完成"


# ============================================================
# 3. 使用示例:Agent 自主完成任务
# ============================================================

if __name__ == "__main__":
    # 创建 Agent(对应 pi-agent 的 repl.py 入口)
    agent = MinimalAgent(model="gpt-4")

    # 注册工具(对应 pi-agent 内置 12+ 工具)
    agent.register_tool(Tool("read_file", "读取文件内容", read_file))
    agent.register_tool(Tool("write_file", "写入文件", write_file))
    agent.register_tool(Tool("run_command", "执行 shell 命令", run_command))
    agent.register_tool(Tool("list_dir", "列出目录内容", list_dir))

    # 给 Agent 一个目标 —— 它会自主规划并执行
    result = agent.run("""
    请帮我:
    1. 查看当前目录下有什么文件
    2. 找一个名为 test.txt 的文件,如果不存在就创建一个
    3. 在 test.txt 中写入 "Hello from pi-agent!"
    4. 确认写入成功
    """)

    print(f"\n📌 最终结果:\n{result}")

五、这段代码揭示的 Agent 本质

运行这段代码,你能看到典型的 ReAct 循环输出:

🔄 [Iteration 1] 思考中...
🔧 调用工具: list_dir({})
📋 观察结果: README.md  test.py  ...

🔄 [Iteration 2] 思考中...
🔧 调用工具: read_file({"path": "test.txt"})
📋 观察结果: Error: [Errno 2] No such file...

🔄 [Iteration 3] 思考中...
🔧 调用工具: write_file({"path": "test.txt", "content": "Hello from pi-agent!"})
📋 观察结果: Successfully wrote to test.txt

🔄 [Iteration 4] 思考中...
🔧 调用工具: read_file({"path": "test.txt"})
📋 观察结果: Hello from pi-agent!

✅ 任务完成,无更多工具调用

这个简单的循环,恰恰揭示了智能体的本质:

  1. 推理与规划(用 LLM 作为“大脑”)—— 每一步 LLM 都在思考:当前状态是什么?下一步该做什么?
  2. 工具使用(让 LLM 长出“手脚”)—— 通过调用外部工具(文件读写、命令执行等),Agent 能够影响真实世界
  3. 观察与迭代(闭环反馈)—— 每步执行结果都作为新信息进入下一轮推理,形成不断优化的循环
  4. 目标驱动(而非问题驱动)—— Agent 接受的是一个“目标”,自己分解步骤,直到达成目标才停止

这也就是为什么 pi-agent 的 slogan 是:“Minimal and transparent: the whole core fits in your head”——因为智能体的核心逻辑,真的就这么简单。


六、延伸:pi-agent 的进阶能力

理解了本质后,再看 pi-agent 的其他特性就更容易理解了:

  • 多 Provider 支持pi-ai 包把各厂商 API 统一为“中立 Transcript”,所以 Agent 核心不用关心背后是 Claude 还是 GPT
  • 持久记忆remember 工具将关键信息写入 .pi/memory.md,下次会话自动加载
  • 子 Agent 委托delegate 工具把复杂子任务交给子 Agent 执行,实现任务分层
  • 技能系统SKILL.md 文件内联到系统提示,让 Agent 知道“怎么做某件事”,无需每次从零学习
  • MCP 协议支持:通过标准配置连接 GitHub、Postgres、Slack 等 MCP 服务器,工具变成 mcp__server__tool 格式,零依赖扩展

七、进一步学习的资源

如果你想深入拆解 pi-agent 源码,以下资源非常有用:

  1. 官方 PyPI 文档:详细介绍了所有工具和架构设计
  2. how-pi-agent-works 教程:从零到一实现教学版 Agent,包含 4 个渐进式 Demo
  3. dg-ai-notes 10 章拆解:从三层架构到会话管理,提供 TypeScript/Python 双版本对照
  4. Agent Cracker 项目:8 维度横向对比 pi-agent 与 aider、codex-cli 等 11 个 Agent
  5. 微软 AI Agent 教程:系统讲解 Agent 的定义、能力和何时使用

最终,理解智能体最有效的方式,就是跑通上面的代码,亲眼看到 LLM 在循环中如何“思考-行动-观察”。你可能会发现:智能体并不神秘,它只是一个 基于 LLM 的、带工具和记忆的、迭代执行的自动化系统


tags:AI智能体, Agent本质, pi-agent, ReAct模式, LLM应用开发,
工具调用, Function Calling, 开源项目拆解, AI编程助手,
大模型应用, 自动化AI, 技术教程, 源码分析, AI工程化