手把手书写你的第一个 AI Agent:当 Skill 有了记忆、角色和主动性

手把手书写你的第一个 AI Agent:当 Skill 有了记忆、角色和主动性

前端 AI Skill 体系 · 第 6 篇(Agent 篇)

上一篇,我们花 15 分钟写了一个日报生成器 Skill。30 行 Markdown,AI 从此不再每天失忆。

但用了一周之后,我发现一个问题:Skill 不会主动干活。

我不说"写日报",它就沉默。我不说"审查代码",它就装死。它像一个只会听指令的实习生------你推一下,它动一下。

我想要的是一个同事:自己记得上下文,自己判断下一步做什么,做完了还会主动告诉我结果。

这就是 Agent。今天这篇,我们从零搭一个。


一、先搞清楚:Agent 和 Skill 到底什么区别

上一篇发布后,评论区问得最多的就是:"Skill 和 Agent 不就是叫法不同吗?"

不是。区别是本质性的。

一句话版本

Skill 是岗位说明书,Agent 是一个活人。

说明书贴在工位上,谁来都照着做。它不会主动思考,不会记住昨天发生了什么,更不会在发现问题时自己去找隔壁部门协调。

Agent 会。

展开说

维度 Skill Agent
本质 一份 Markdown 指令 一个可运行的程序
触发 被动------你说话它才动 主动------自己决定何时行动
记忆 无。每次对话从零开始 有。短期工作记忆 + 长期持久化
工具 描述"应该做什么",AI 自行决定 代码级绑定,确定性执行
决策 线性流程,不会回溯 观察→思考→行动→再观察,循环
协作 独立存在,互不感知 Handoff 给其他 Agent、组队
部署 放项目目录就行 需要 Python/Node 运行时
成本 零(纯文本) API 调用费 / 本地算力

什么时候该用哪个?

我现在的判断标准很简单:

如果任务需要"做完一步,看看结果,再决定下一步"------用 Agent。 如果任务是"输入→固定流程→输出"------用 Skill。

举几个实际例子:

场景 选择 为什么
统一代码风格 Skill 规则固定,不需要决策
生成日报 Skill 流程固定,一次执行完事
自动修 Bug Agent 要观察报错→定位原因→修复→验证→没修好再来
多文件重构 Agent 要规划顺序、跨文件协调、改完一个检查另一个
客服问答 Agent 要记住上下文、查知识库、判断是否需要转人工
代码审查 Skill + Agent Skill 定审查规则,Agent 执行多轮审查

它们不是替代关系,是互补关系。 Skill 定义"怎么做",Agent 决定"什么时候做、找谁做、做完了怎么办"。

我现在的体系里,31 个 Skill 定义规范,3 个 Agent 负责编排和执行。Skill 是法律条文,Agent 是法官。


二、项目目录结构

简单 Agent:5 个文件搞定

bash 复制代码
my-first-agent/
├── agent.py              # Agent 定义(角色 + 指令 + 工具绑定)
├── tools.py              # 工具函数(Agent 的手和脚)
├── main.py               # 运行入口
├── requirements.txt      # 依赖:openai-agents
└── .env                  # API Key(别提交 Git)

就这么多。别一上来就搞 20 个目录。

复杂 Agent:5 层架构

当你的 Agent 从 1 个变成 3 个、5 个,目录就需要分层了:

perl 复制代码
my-agent-system/
│
├── agents/               # 🧠 角色层:谁干什么
│   ├── orchestrator.py   #    编排者------决定任务分配
│   ├── researcher.py     #    研究员------搜索和整理信息
│   ├── coder.py          #    开发者------写代码、修 Bug
│   └── reviewer.py       #    审查者------质量把关
│
├── tools/                # 🔧 能力层:能做什么
│   ├── web_search.py     #    网络搜索
│   ├── file_ops.py       #    文件读写
│   ├── code_exec.py      #    代码执行(沙箱)
│   └── git_ops.py        #    Git 操作
│
├── memory/               # 💾 记忆层:记得什么
│   ├── short_term.py     #    当前对话上下文
│   ├── long_term.py      #    跨会话持久化(SQLite/Redis)
│   └── vector_store.py   #    语义检索(向量数据库)
│
├── config/               # ⚙️ 配置层:用什么模型、什么参数
│   ├── models.py         #    模型配置(可切换 OpenAI/Claude/Ollama)
│   ├── prompts.py        #    System Prompt 模板
│   └── settings.py       #    全局设置(max_iterations、timeout)
│
├── workflows/            # 🔄 编排层:怎么协作
│   ├── code_review.py    #    代码审查流程
│   └── feature_dev.py    #    功能开发流程(含回退重试)
│
├── main.py               # 入口
├── requirements.txt
├── .env.example
└── README.md

各层一句话

一句话 类比
agents/ 定义"谁"------角色、目标、边界 公司组织架构
tools/ 定义"能做什么"------具体能力 员工的工具箱
memory/ 定义"记得什么"------上下文和知识 员工的大脑
config/ 定义"用什么模型" 公司制度
workflows/ 定义"怎么协作" 项目流程

原则:先跑通 5 个文件的简单版,再按需拆层。 别一上来就搭 5 层架构------那是第 3 个 Agent 出现之后才需要的事。


三、5 个我踩过的坑

这些坑我全踩过。每一个都浪费了我至少半天。

坑 1:以为长 Prompt = Agent

我最初的"Agent"就是一个 3000 字的 System Prompt,里面写了"你要先搜索,再分析,再输出"。

它不是 Agent。它是一个带长说明书的 Chatbot

Agent 的核心不是 Prompt 长度,是循环

python 复制代码
# ❌ 这不是 Agent,这是一个函数调用
response = llm.call("帮我调研 xxx")

# ✅ Agent 的核心是这个循环
while not done:
    observation = agent.observe(environment)    # 看到了什么
    thought = agent.think(observation)          # 怎么想的
    action = agent.decide(thought)              # 决定做什么
    result = agent.act(action)                  # 执行
    done = agent.evaluate(result)               # 够了吗?不够就再来

这个循环叫 ReAct(Reasoning + Acting)。没有它,就不是 Agent。

坑 2:给 Agent 接了 30 个工具

"工具越多越强大嘛!"------我当初是这么想的。

结果:Agent 开始"选择困难"。让它搜个东西,它先去读了个文件。让它写代码,它先去搜了个网页。

实测体感

工具数量 任务准确率(体感)
3-5 个 ~90%
10-15 个 ~70%
30+ 个 开始随机调工具,~50%

原则:每个 Agent 最多 5-7 个工具。 需要更多能力?拆成多个 Agent,每个 Agent 只管自己那几把刀。

坑 3:造了一个"全能 Agent"

python 复制代码
# ❌ 我最初写的
agent = Agent(
    name="Everything",
    instructions="你能搜索、写代码、审查代码、部署、写文档、做PPT..."
)

它什么都做,什么都做不好。

后来我拆成了 3 个:Researcher 只管搜、Coder 只管写、Reviewer 只管审。每个 Agent 的 instructions 不超过 200 字。

效果立竿见影:单个 Agent 的输出质量从"勉强能用"变成"基本不用改"。

坑 4:没设最大循环次数

有一天晚上我让 Agent 调研一个技术方案,然后去吃饭了。

回来一看:它还在跑。 搜了 47 次网页,每次都觉得"信息不够充分,再搜一次"。Token 烧了 $3.2。

python 复制代码
# ✅ 必须设上限
result = await Runner.run(
    agent,
    "调研 xxx",
    max_turns=10,  # 最多 10 轮工具调用,超了就停
)

教训:Agent 没有"够了"的概念,你必须替它设。

坑 5:没做 Human-in-the-loop

我让 Agent 帮我"清理项目里的临时文件"。

它很勤快地执行了 rm -rf node_modules .git dist

.git 没了。

python 复制代码
# ✅ 危险操作必须暂停等人确认
from agents import Agent, function_tool

@function_tool(needs_approval=True)  # 关键:执行前暂停等人确认
def delete_file(path: str) -> str:
    """删除指定文件"""
    os.remove(path)
    return f"已删除 {path}"

2026 年了,Agent 仍然需要人类把关。 尤其是:删除操作、金钱相关、权限变更、面向外部的输出。

个人 vs 企业:方向不同

维度 个人开发者(我) 企业团队
起步 OpenAI Agents SDK,单文件 LangGraph / CrewAI + 编排平台
模型 OpenAI / Claude API 私有部署 + API 混合
记忆 本地 SQLite Redis + 向量数据库
部署 本地跑 / 简单脚本 K8s + 监控 + 告警
安全 .env 管 Key Vault + RBAC + 审计日志
月成本 $10-50 预算制,需成本监控
可观测 print + Tracing 面板 LangSmith / 专业 Tracing

如果你是一个人,别搞企业那套。 一个 .py 文件 + 一个 .env,够了。


四、15 分钟:搭一个能搜索、能写文件的 Research Agent

框架选择:OpenAI Agents SDK。 原因:5 行代码跑起来,内置 Tracing,支持 100+ 模型,2026 年社区最活跃。 后面复杂版也用它,不换框架。

Step 1:环境准备(2 分钟)

前置要求 :Python 3.10+(python3 --version 检查)。 前端同学如果没装过 Python:macOS 用 brew install python@3.12,Windows 去 python.org 下载安装。

bash 复制代码
mkdir my-first-agent && cd my-first-agent
python3 -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

pip install openai-agents python-dotenv

# 环境变量(这里用阿里百炼/通义千问,国内直连,不用翻墙)
# 到 https://bailian.console.aliyun.com 开通,免费额度够跑几十次
cat > .env << EOF
OPENAI_API_KEY=sk-xxx          # 百炼的 API Key
OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
TAVILY_API_KEY=tvly-xxx        # 搜索工具用,https://tavily.com 免费注册
EOF

echo ".env" >> .gitignore

为什么用百炼而不是 OpenAI? 三个原因:国内直连不用代理、免费额度够学习用、qwen-plus 的中文能力很强。后面第六章会讲怎么切回 OpenAI 或本地 Ollama。

Step 2:写工具(5 分钟)

工具就是 Agent 的手和脚。没有工具的 Agent 只是一个会说话的嘴。

python 复制代码
# tools.py
import subprocess
from pathlib import Path
from agents import function_tool


@function_tool
def web_search(query: str) -> str:
    """搜索网络获取最新信息。当需要查找实时数据、技术文档、新闻时使用。

    Args:
        query: 搜索关键词,尽量具体。比如"OpenAI Agents SDK 2026 新特性"比"AI框架"好。
    """
    import json, os
    api_key = os.getenv("TAVILY_API_KEY", "")
    if not api_key:
        return "错误:未设置 TAVILY_API_KEY 环境变量。请到 https://tavily.com 免费注册获取。"
    try:
        result = subprocess.run(
            ["curl", "-s", "-X", "POST", "https://api.tavily.com/search",
             "-H", "Content-Type: application/json",
             "-d", json.dumps({"api_key": api_key, "query": query, "max_results": 3})],
            capture_output=True, text=True, timeout=15
        )
        data = json.loads(result.stdout)
        summaries = [f"- {r.get('title', '')}: {r.get('content', '')[:300]}" for r in data.get("results", [])]
        return "\n".join(summaries)[:2000] if summaries else "未找到相关结果"
    except (subprocess.TimeoutExpired, json.JSONDecodeError) as e:
        return f"搜索失败:{e},请换个关键词重试"


@function_tool
def read_file(file_path: str) -> str:
    """读取本地文件内容。当需要查看代码、文档、配置文件时使用。

    Args:
        file_path: 文件的相对或绝对路径
    """
    path = Path(file_path)
    if not path.exists():
        return f"文件不存在:{file_path}"
    if path.stat().st_size > 50_000:
        return f"文件过大({path.stat().st_size} 字节),请指定行号范围"
    return path.read_text(encoding="utf-8")[:5000]


@function_tool
def write_file(file_path: str, content: str) -> str:
    """将内容写入文件。当需要保存研究结果、生成报告时使用。

    Args:
        file_path: 目标文件路径
        content: 要写入的完整内容
    """
    path = Path(file_path)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")
    return f"✅ 已写入 {file_path}({len(content)} 字符)"

3 个细节,都是踩坑后加的

  1. docstring 里写"什么时候用"------Agent 靠这段话决定调不调这个工具
  2. 返回值必须截断[:2000])------不截断,一次搜索就吃掉 50% 上下文
  3. 错误要返回字符串,不要抛异常------Agent 看到错误信息会自己重试

Step 3:定义 Agent(3 分钟)

python 复制代码
# agent.py
from agents import Agent
from tools import web_search, read_file, write_file

research_agent = Agent(
    name="Research Assistant",
    model="qwen-plus",  # 百炼模型名。用 OpenAI 就改成 "gpt-4o"
    instructions="""你是一个研究助理。

## 工作流程
1. 理解用户的研究问题,拆解为 2-3 个子问题
2. 对每个子问题使用 web_search 搜索
3. 评估信息是否充分------不够就换关键词再搜
4. 整理为结构化报告,用 write_file 保存到 reports/ 目录

## 规则
- 每次搜索后问自己:"信息够回答问题了吗?"不够就继续
- 报告必须标注信息来源 URL
- 不确定的信息标注【待验证】
- 最多搜索 5 次。5 次还不够,就如实说"信息有限"
- 报告用中文,技术术语保留英文""",
    tools=[web_search, read_file, write_file],
)

注意 instructions 的写法

  • 有明确的工作流程(不是"你帮我调研一下"这种模糊指令)
  • 有退出条件("最多 5 次")------防止坑 4 的无限循环
  • 有输出规范("标注来源"、"用中文")
  • model 字段指定模型------百炼用 qwen-plus,OpenAI 用 gpt-4o,本地用 llama3.1:8b

Step 4:运行(2 分钟)

python 复制代码
# main.py
from dotenv import load_dotenv
load_dotenv()

import os
os.environ["OPENAI_AGENTS_DISABLE_TRACING"] = "true"

import asyncio
from agents import Runner, set_default_openai_api
from agent import research_agent

# 百炼不支持 Responses API,强制走 Chat Completions API
set_default_openai_api("chat_completions")


async def main():
    user_input = input("请输入你的研究问题(直接回车使用默认问题):\n> ").strip()
    if not user_input:
        user_input = "调研 2026 年主流 AI Agent 框架(OpenAI Agents SDK、LangGraph、CrewAI)的优劣对比"

    result = await Runner.run(
        research_agent,
        input=user_input,
        max_turns=10,
    )
    print(result.final_output)


if __name__ == "__main__":
    asyncio.run(main())
bash 复制代码
python main.py

两行"丑代码",但缺了直接报错

代码 为什么需要 用 OpenAI 时
OPENAI_AGENTS_DISABLE_TRACING=true 百炼不支持 OpenAI 的 Tracing 上报 删掉,享受内置 Tracing
set_default_openai_api("chat_completions") 百炼只支持 Chat Completions API 删掉,SDK 默认即可

Step 5:看它怎么想的(3 分钟)

运行后你会在终端看到 Agent 的完整决策链:

css 复制代码
Turn 1: Agent 思考 → 拆解为 3 个子问题
Turn 2: 调用 web_search("OpenAI Agents SDK features 2026")
Turn 3: 调用 web_search("LangGraph vs CrewAI comparison")
Turn 4: 调用 web_search("AI agent framework benchmark 2026")
Turn 5: Agent 思考 → 信息充分,开始写报告
Turn 6: 调用 write_file("reports/agent-frameworks-2026.md", ...)
Turn 7: 输出最终摘要

如果你用的是 OpenAI 官方 API(没关 Tracing),还可以打开 platform.openai.com/traces 看可视化面板。

这就是 Agent 和 Chatbot 的区别:Chatbot 给你一坨文字,Agent 给你一条可审计的决策链。

最终文件清单

bash 复制代码
my-first-agent/
├── agent.py          # 22 行:Agent 定义
├── tools.py          # 50 行:3 个工具
├── main.py           # 25 行:运行入口
├── requirements.txt  # 2 行:openai-agents + python-dotenv
└── .env              # 3 行:API Key + Base URL + Tavily Key

~100 行代码。一个能搜索、能读写文件、有决策循环的 Agent。国内直连,不用代理。


五、45 分钟:搭一个 3 人协作的开发团队

还是 OpenAI Agents SDK。不换框架。 从 1 个 Agent 到 3 个,核心变化是:Handoff(任务移交)

目标

输入一句需求:"实现一个 React useDebounce Hook"。

3 个 Agent 自动协作:

  1. PM Agent 分析需求 → 输出技术方案
  2. Coder Agent 根据方案写代码 → 输出到 src/
  3. Reviewer Agent 审查代码 → 通过或打回

如果审查不通过,自动打回给 Coder 重写,最多重试 2 次。

环境准备

和第四章一样,需要 Python 3.10+ 环境。如果你已经跑通了第四章,直接复用那个虚拟环境即可------依赖完全相同。

bash 复制代码
# 如果还没装过:
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

本章复用第四章的 tools.pyrequirements.txt,不需要额外安装任何新依赖。

Step 1:定义 3 个 Agent

python 复制代码
# agents.py
from agents import Agent, function_tool
from tools import read_file, write_file

# ---------- PM Agent ----------
pm_agent = Agent(
    name="PM",
    model="qwen-plus",
    instructions="""你是技术产品经理。

## 职责
将用户需求转化为可执行的技术方案。

## 输出格式(严格遵守)
### 功能描述
一句话说明做什么。

### 接口定义
- 输入:参数名、类型、默认值
- 输出:返回值类型
- 用法示例:```tsx 代码块

### 边界条件(至少 3 个)
1. ...
2. ...
3. ...

### 验收标准(可测试的 checklist)
- [ ] ...
- [ ] ...

## 规则
- 先问"用户真正想要什么",不要直接设计
- 如果需求模糊,列出你的假设
- 不写代码,只写方案""",
    tools=[read_file],
)

# ---------- Coder Agent ----------
coder_agent = Agent(
    name="Coder",
    model="qwen-plus",
    instructions="""你是高级前端工程师。

## 职责
根据技术方案编写代码。

## 规则
- 代码写入 src/ 目录(用 write_file 工具)
- 主文件:src/index.ts
- 测试文件:src/index.test.ts
- 所有函数必须有 JSDoc 注释
- 错误处理不能省略
- 如果方案有歧义,在代码注释中标注 // TODO: 方案歧义 - xxx
- 使用 TypeScript strict 模式""",
    tools=[read_file, write_file],
)

# ---------- Reviewer Agent ----------
reviewer_agent = Agent(
    name="Reviewer",
    model="qwen-plus",
    instructions="""你是代码审查专家。

## 审查维度(按优先级)
1. 逻辑正确性------对照技术方案的验收标准逐条检查
2. 边界条件------方案里列的边界条件是否都处理了
3. 错误处理------有没有吞掉异常
4. 类型安全------有没有 any
5. 性能------有没有不必要的重渲染/重复计算

## 输出格式
如果通过:
"LGTM ✅" + 一句话总结亮点

如果不通过:
"NEEDS_REVISION ❌" + 具体问题列表(精确到行号 + 修改建议)

## 规则
- 目标是帮助,不是刁难
- 风格问题(分号、缩进)不提
- 最多提 5 个问题,挑最严重的""",
    tools=[read_file],
)

Step 2:定义 Handoff 和编排

python 复制代码
# workflow.py
from agents import Agent, Runner, handoff
from agents.stream_events import RunItemStreamEvent, AgentUpdatedStreamEvent
from agent import pm_agent, coder_agent, reviewer_agent

# 给 PM 添加 Handoff:分析完交给 Coder
pm_agent.handoffs = [handoff(coder_agent)]

# 给 Coder 添加 Handoff:写完交给 Reviewer
coder_agent.handoffs = [handoff(reviewer_agent)]

# Reviewer 的 Handoff:打回给 Coder(条件触发)
reviewer_agent.handoffs = [handoff(coder_agent)]

def _format_event(event):
    """格式化流式事件为可读输出"""
    if isinstance(event, AgentUpdatedStreamEvent):
        print(f"\n🤖 [{event.new_agent.name}] 接管中...")

    elif isinstance(event, RunItemStreamEvent):
        name = event.name
        item = event.item

        if name == "message_output_created":
            text = getattr(item, 'raw_item', None)
            if text:
                content = getattr(text, 'content', '')
                if isinstance(content, list):
                    for c in content:
                        if hasattr(c, 'text') and c.text:
                            print(f"  💬 {c.text[:200]}")
                elif isinstance(content, str) and content.strip():
                    print(f"  💬 {content[:200]}")

        elif name == "tool_called":
            tool_name = getattr(item, 'name', 'unknown')
            print(f"  🔧 调用工具: {tool_name}")

        elif name == "tool_output":
            print(f"  ✅ 工具执行完成")

        elif name == "handoff_requested":
            print(f"  ➡️  请求交接...")

        elif name == "handoff_occured":
            print(f"  🔀 交接完成")

async def run_dev_team(requirement: str) -> str:
    """运行开发团队,实时展示每个 Agent 的执行过程"""
    result = Runner.run_streamed(
        pm_agent,
        input=f"需求:{requirement}\n\n请分析需求并输出技术方案,然后交给 Coder 实现。",
        max_turns=20,
    )

    async for event in result.stream_events():
        _format_event(event)

    return result.final_output

这里用了 Runner.run_streamed 替代 Runner.run------区别在于你能实时看到每个 Agent 在干什么:谁接管了、调了什么工具、输出了什么。调试多 Agent 协作时,这比等最终结果强太多。

Step 3:加入重试逻辑

python 复制代码
# main.py
from dotenv import load_dotenv
load_dotenv()

import os
os.environ["OPENAI_AGENTS_DISABLE_TRACING"] = "true"

import asyncio
from agents import set_default_openai_api
from workflow import run_dev_team

# 百炼/通义千问不支持 Responses API,强制使用 Chat Completions API
set_default_openai_api("chat_completions")


async def main():
    default_req = "实现一个 React Hook:useDebounce,支持自定义延迟(默认 300ms)、取消、立即执行(flush)"
    user_input = input(f"请输入开发需求(直接回车使用默认需求):\n> ").strip()
    requirement = user_input if user_input else default_req

    max_retries = 2

    for attempt in range(max_retries + 1):
        print(f"\n{'='*50}")
        print(f"🚀 第 {attempt + 1} 轮")
        print(f"{'='*50}")

        result = await run_dev_team(requirement)

        if "LGTM" in result:
            print("\n✅ 审查通过!代码已写入 src/ 目录")
            break
        elif attempt < max_retries:
            print(f"\n❌ 审查未通过,打回重写(剩余 {max_retries - attempt} 次机会)")
            requirement += f"\n\n上一轮审查意见:\n{result}"
        else:
            print("\n⚠️ 重试次数用完,需要人工介入")
            print(result)


if __name__ == "__main__":
    asyncio.run(main())

和第四章一样,三件套不能少:load_dotenv() 加载 .env、禁用 Tracing、强制 Chat Completions API。忘了任何一行都会报错。

Step 4:运行

bash 复制代码
python main.py

你会看到:

csharp 复制代码
==================================================
🚀 第 1 轮
==================================================
[PM] 分析需求...
  → 输出技术方案:接口定义、边界条件、验收标准
  → Handoff to Coder

[Coder] 编写代码...
  → write_file("src/index.ts", ...)
  → write_file("src/index.test.ts", ...)
  → Handoff to Reviewer

[Reviewer] 审查代码...
  → NEEDS_REVISION ❌
  → 问题 1: src/index.ts:23 - flush 后没有清除 timer
  → 问题 2: src/index.test.ts - 缺少 cancel 的测试用例

❌ 审查未通过,打回重写(剩余 2 次机会)

==================================================
🚀 第 2 轮
==================================================
[Coder] 根据审查意见修改...
  → 修复 flush 逻辑
  → 补充 cancel 测试
  → Handoff to Reviewer

[Reviewer] 再次审查...
  → LGTM ✅ 逻辑完整,边界条件全覆盖

✅ 审查通过!代码已写入 src/ 目录

架构图

css 复制代码
┌──────────────────────────────────────────────────────┐
│                  Dev Team Workflow                     │
│                                                       │
│  ┌────────┐  Handoff  ┌────────┐  Handoff  ┌────────┐│
│  │   PM   │─────────▶│ Coder  │─────────▶│Reviewer││
│  │ 需求分析│          │ 编码实现│          │ 代码审查││
│  └────────┘          └────────┘          └───┬────┘│
│                            ▲                  │      │
│                            │  NEEDS_REVISION  │      │
│                            └──────────────────┘      │
│                                                       │
│  外部循环:main.py 控制最多重试 2 次                    │
│  超过 2 次 → 人工介入                                  │
└──────────────────────────────────────────────────────┘

和简单版的区别

维度 简单版(1 Agent) 复杂版(3 Agent)
Agent 数量 1 3
工具分配 1 个 Agent 拿所有工具 每个 Agent 只拿自己需要的
协作方式 Handoff 移交
质量控制 自己检查自己 独立 Reviewer
失败处理 打回重写 + 重试上限

六、换模型:从 OpenAI 到本地 Ollama

前面用的都是云端 API(百炼)。但有些场景你需要换:

  • 隐私:代码不能出公司
  • 成本:高频简单任务,API 费太贵
  • 离线:没网也得跑

方案对比(一张表)

方案 适合谁 月成本 速度 能力
OpenAI API 快速原型、复杂推理 $10-50 200+ tok/s ⭐⭐⭐⭐⭐
Claude API 长文本、代码审查 $10-50 150+ tok/s ⭐⭐⭐⭐⭐
Ollama 本地 隐私、离线、高频简单任务 硬件一次性 20-40 tok/s ⭐⭐⭐
vLLM 自部署 企业私有化、高并发 服务器成本 100+ tok/s 取决于模型
LiteLLM 代理 多模型统一入口 透传 透传 透传

换 Ollama:3 步搞定

bash 复制代码
# 1. 安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh

# 2. 拉模型
ollama pull llama3.1:8b
ollama pull qwen2.5-coder:7b
python 复制代码
# 3. 改 2 行代码
from openai import AsyncOpenAI
from agents import Agent, Runner, set_default_openai_client

local_client = AsyncOpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)
set_default_openai_client(local_client, use_for_tracing=False)

agent = Agent(
    name="Local Agent",
    instructions="你是一个本地运行的助手",
    model="llama3.1:8b",
)

import asyncio
result = asyncio.run(Runner.run(agent, "用 Python 写一个二分查找"))
print(result.final_output)

就这么多。 工具定义不用改,Agent 逻辑不用改,只改模型连接。

换 Claude:通过 LiteLLM 桥接

bash 复制代码
pip install 'openai-agents[litellm]'
python 复制代码
agent = Agent(
    name="Claude Agent",
    instructions="...",
    model="litellm/anthropic/claude-sonnet-4-20250514",
)

企业级:vLLM 部署

bash 复制代码
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --host 0.0.0.0 --port 8000 \
  --max-model-len 8192

接入方式和 Ollama 一样,只是 base_url 换成你的服务器地址。

多模型统一入口:LiteLLM 代理

yaml 复制代码
# litellm_config.yaml
model_list:
  - model_name: fast
    litellm_params:
      model: openai/gpt-4o-mini
  - model_name: smart
    litellm_params:
      model: anthropic/claude-sonnet-4-20250514
  - model_name: private
    litellm_params:
      model: ollama/llama3.1:8b
      api_base: http://localhost:11434
bash 复制代码
litellm --config litellm_config.yaml --port 4000

选型决策树

markdown 复制代码
你的数据敏感吗?
├── 是 → 本地部署
│   ├── 个人用 → Ollama(一行命令搞定)
│   └── 企业用 → vLLM(高并发 + 多 GPU)
└── 不敏感 → 任务复杂吗?
    ├── 复杂推理/代码 → OpenAI / Claude API
    └── 简单/高频 → 本地 Ollama 省钱

我的实际配置 :日常用 gpt-4o-mini(便宜),复杂推理切 gpt-4o,涉及公司代码走本地 Ollama。一个月 $15 左右。


七、Q&A:你们问得最多的 7 个问题

Q1: 我已经有 31 个 Skill 了,还需要 Agent 吗?

看你的痛点:

痛点 解法
AI 不遵守 Skill 里的规则 优化 Skill 本身(不是 Agent 的问题)
每次都要手动触发 Agent(主动性)
跨会话记不住上下文 Agent + Memory
复杂任务需要多步协调 Multi-Agent
想自动化整个开发流程 必须 Agent

Skill 和 Agent 不是替代关系。 我现在的体系:31 个 Skill 定规范,3 个 Agent 做编排。Skill 是法律,Agent 是法官。

Q2: 哪个框架适合新手?

框架 学习曲线 一句话
OpenAI Agents SDK ⭐ 最低 5 行代码跑起来
CrewAI ⭐⭐ 给 Agent 一个"职位"
LangGraph ⭐⭐⭐ Agent 的 Kubernetes
AutoGen ⭐⭐⭐⭐ 学术味最重

新手路径:OpenAI Agents SDK(理解概念)→ CrewAI(多 Agent 角色分工)→ LangGraph(生产级状态机)

Q3: Agent 的 Token 成本怎么控制?

我实测一个 Research Agent 单次任务的消耗:

环节 Token 占比
System Prompt ~500 5%
工具描述 ~300 3%
工具返回结果 ~5000 50%
Agent 推理 ~3000 30%
最终输出 ~1000 10%

大头是工具返回值。 控制策略:

  1. 工具返回必须截断([:2000]
  2. 简单判断用 gpt-4o-mini,复杂推理用 gpt-4o
  3. max_turns 防无限循环
  4. 缓存重复查询

Q4: 本地模型能跑 Agent 吗?

能,但要看模型大小:

模型 内存需求 Agent 能力 适合场景
7B 8GB+ 单工具、简单 ReAct 文件操作、格式转换
13B 16GB+ 多工具、简单规划 代码生成、问答
70B 48GB+ 接近云端 复杂推理

实测体感:7B 模型跑 3 个工具的 Agent,成功率约 60%。同样任务 GPT-4o 是 95%+。

Q5: 多 Agent 之间怎么通信?

三种主流模式:

css 复制代码
模式 1:Handoff 移交(本文用的)
PM → Coder → Reviewer

模式 2:中心调度
       Orchestrator
      /     |      \
  Agent A  Agent B  Agent C

模式 3:群聊协商(AutoGen 风格)
Agent A ←→ Agent B ←→ Agent C

新手从模式 1 开始。模式 2 和 3 等你有 5+ Agent 时再考虑。

Q6: Agent 会"跑飞"怎么办?

7 道防线,按重要性排序:

  1. max_turns:最多 N 轮工具调用,超了强制停
  2. 工具白名单 :不给 rm -rf 的能力
  3. needs_approval=True:危险操作暂停等人确认
  4. Guardrails:输入/输出校验(SDK 内置)
  5. 沙箱执行:代码在隔离环境跑
  6. Tracing:每步有日志,出问题能回溯
  7. 成本熔断:token 超阈值自动终止
python 复制代码
# Guardrails 示例:拦截危险输入
from agents import Agent, input_guardrail, GuardrailFunctionOutput, RunContextWrapper

@input_guardrail
async def block_dangerous(
    ctx: RunContextWrapper, agent: Agent, input: str | list
) -> GuardrailFunctionOutput:
    text = input if isinstance(input, str) else str(input)
    dangerous = ["删除所有", "rm -rf", "drop table", "format c:"]
    is_safe = not any(word in text.lower() for word in dangerous)
    return GuardrailFunctionOutput(
        output_info={"safe": is_safe},
        tripwire_triggered=not is_safe,
    )

agent = Agent(
    name="Safe Agent",
    instructions="你是一个安全的助手",
    input_guardrails=[block_dangerous],
)

Q7: 自定义 GPTs 算 Agent 吗?

算"体验版"。它有 System Prompt(≈ Skill)+ 知识库(≈ RAG)+ 少量工具,但:

  • ❌ 没有自主循环
  • ❌ 没有持久记忆
  • ❌ 没有多 Agent 协作
  • ❌ 没有代码级控制

真正的 Agent 需要代码。自定义 GPTs 是让你体验 Agent 的感觉,但做不到 Agent 的事。


结语

上一篇,我们给 AI 写了一份岗位说明书。 这一篇,我们招了一个人。

arduino 复制代码
Skill:  "你告诉我怎么做,我就怎么做。"
Agent:  "你告诉我目标,我自己想办法。"

82 行代码,一个会搜索、会写文件、会自己判断"够不够"的 Research Agent。

再加 100 行,它有了两个同事:一个写代码,一个审代码。审查不通过,自己打回重写。

这不是科幻。这是 2026 年一个周二下午,我坐在工位上干的事。

OpenAI 做了 Agents SDK。10 万开发者已经在用了。

现在轮到你了。

从那个你每天都要手动协调 3 个步骤才能完成的任务开始。 把它交给一个 Agent。 然后看着它自己跑完。

那种感觉------就像你终于招到了一个不用催的同事。


系列回顾:


参考来源

来源 内容
OpenAI Agents SDK 官方文档 + GitHub README(Agent / Handoff / Guardrails / Tracing)
CrewAI GitHub README(Crews + Flows 双模式)
LangGraph GitHub README(状态机 / 持久执行 / Human-in-the-loop)
AutoGen Microsoft GitHub(Actor 模型 / 事件驱动)
Ollama GitHub README(本地部署 / REST API / OpenAI 兼容接口)
Anthropic Agentic Systems 官方文档
LiteLLM 多模型统一代理
相关推荐
plainGeekDev1 小时前
Agent Prompt 怎么写:三个真实案例讲透
agent·ai编程·claude
不是株2 小时前
Agent Memory 架构
人工智能·agent
@atweiwei2 小时前
用 Rust 构建 Agent 应用的高性能框架:langchainrust 架构全景
人工智能·架构·rust·langchain·llm·agent·ai编程
原则猫2 小时前
设计模式
前端
光影少年2 小时前
react navite环境与工程化
前端·react native·react.js
武子康2 小时前
看不见的 Reasoning State,为什么不能拥有看得见的工具权限
人工智能·llm·agent
PedroQue992 小时前
v2.6.0 新增全局返回守卫与 iOS 侧滑拦截,补齐跨端路由拦截能力
前端·uni-app
lichenyang4532 小时前
从「房间」到「实时通知」:用 NestJS + Socket.IO 实现团队邀请的完整工程实践
前端·后端
蚂蚁集团数据体验技术2 小时前
推荐免费工具,AntV 开源社区出品数据可视化产品 Sive
github·agent·数据可视化