2026年被称为「AI Agent 元年」。从年初 Manus 的大火到开源方案遍地开花,AI 已经不满足于只陪你聊天了——它能帮你干活。今天从零构建一个能浏览网页、写代码、发邮件的 AI Agent。
什么是 AI Agent?
先厘清一个概念:
| 概念 | ChatBot(聊天机器人) | AI Agent(智能体) |
|---|---|---|
| 能力边界 | 只能对话 | 能执行任务 |
| 交互方式 | 你问它答 | 自主规划和执行 |
| 工具使用 | 无 | 调用浏览器、API、终端 |
| 决策能力 | 无 | 多步推理,自主选择 |
| 典型代表 | ChatGPT、文心一言 | Manus、OpenClaw、AutoGPT |
一句话总结:ChatBot 是嘴,Agent 是手和脑。 ChatBot 只能告诉你怎么做,Agent 能直接帮你做完。
AI Agent 的核心技术栈
┌─────────────────────────────────────────┐
│ 用户指令 │
│ 「帮我查一下今天的新闻」 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 大模型(大脑) │
│ DeepSeek V4 / GPT-5.4 / Claude │
│ 理解意图 → 规划步骤 → 调用工具 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 工具层(双手) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 浏览器 │ │ 代码执行 │ │ 邮件 │ │
│ │ 网页抓取 │ │ Python │ │ SMTP │ │
│ │ 表单填写 │ │ Shell │ │ API │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────┘
核心原理其实不复杂:Function Calling + 循环执行。大模型决定调用哪个工具,执行后把结果返回给大模型,大模型再决定下一步做什么——如此循环直到任务完成。
方案一:从零用 Python 构建 Agent(最灵活)
先实现一个最小可用的 Agent 框架,理解核心原理后再上复杂方案。
1. 定义工具
# agent/tools.py
import requests
from bs4 import BeautifulSoup
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import subprocess
import json
class ToolRegistry:
"""工具注册器:管理所有 Agent 可用的工具"""
def __init__(self):
self.tools = {}
def register(self, name, description, parameters, handler):
"""注册一个工具"""
self.tools[name] = {
"description": description,
"parameters": parameters,
"handler": handler
}
def get_openai_tools(self):
"""转换为 OpenAI Function Calling 格式"""
return [
{
"type": "function",
"function": {
"name": name,
"description": tool["description"],
"parameters": tool["parameters"]
}
}
for name, tool in self.tools.items()
]
def call(self, name, arguments):
"""调用指定工具"""
if name not in self.tools:
return f"错误:未知工具 {name}"
return self.tools[name]["handler"](**arguments)
# ========== 创建工具实例 ==========
registry = ToolRegistry()
# 工具1:浏览网页
def browse_web(url: str, extract_type: str = "text") -> str:
"""抓取网页内容"""
try:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
resp = requests.get(url, headers=headers, timeout=10)
resp.raise_for_status()
resp.encoding = resp.apparent_encoding
soup = BeautifulSoup(resp.text, "html.parser")
if extract_type == "text":
# 去除脚本和样式,提取纯文本
for tag in soup(["script", "style", "nav", "footer"]):
tag.decompose()
text = soup.get_text(separator="\n", strip=True)
return text[:3000] # 限制长度,避免超过上下文窗口
elif extract_type == "links":
links = [f"{a.get_text(strip=True)}: {a['href']}"
for a in soup.find_all("a", href=True)[:20]]
return "\n".join(links)
elif extract_type == "title":
return soup.title.string if soup.title else "无标题"
except Exception as e:
return f"抓取失败:{str(e)}"
registry.register(
name="browse_web",
description="浏览指定URL的网页,提取文本内容、链接或标题",
parameters={
"type": "object",
"properties": {
"url": {"type": "string", "description": "要访问的网址"},
"extract_type": {
"type": "string",
"enum": ["text", "links", "title"],
"description": "提取类型:text=正文, links=链接列表, title=标题"
}
},
"required": ["url"]
},
handler=browse_web
)
# 工具2:搜索网页
def search_web(query: str) -> str:
"""通过DuckDuckGo搜索"""
try:
resp = requests.get(
"https://html.duckduckgo.com/html/",
params={"q": query},
headers={"User-Agent": "Mozilla/5.0"},
timeout=10
)
soup = BeautifulSoup(resp.text, "html.parser")
results = []
for item in soup.select(".result")[:5]:
title = item.select_one(".result__title")
snippet = item.select_one(".result__snippet")
if title and snippet:
results.append(f"标题:{title.get_text(strip=True)}\n摘要:{snippet.get_text(strip=True)}")
return "\n\n".join(results) if results else "未找到相关结果"
except Exception as e:
return f"搜索失败:{str(e)}"
registry.register(
name="search_web",
description="使用搜索引擎搜索信息",
parameters={
"type": "object",
"properties": {
"query": {"type": "string", "description": "搜索关键词"}
},
"required": ["query"]
},
handler=search_web
)
# 工具3:发送邮件
def send_email(
to: str,
subject: str,
body: str,
smtp_host: str = "smtp.qq.com",
smtp_port: int = 465,
smtp_user: str = None,
smtp_pass: str = None
) -> str:
"""发送邮件(需要配置SMTP信息)"""
try:
msg = MIMEMultipart()
msg["From"] = smtp_user
msg["To"] = to
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain", "utf-8"))
with smtplib.SMTP_SSL(smtp_host, smtp_port) as server:
server.login(smtp_user, smtp_pass)
server.send_message(msg)
return f"邮件已成功发送至 {to}"
except Exception as e:
return f"发送失败:{str(e)}"
registry.register(
name="send_email",
description="发送电子邮件",
parameters={
"type": "object",
"properties": {
"to": {"type": "string", "description": "收件人邮箱"},
"subject": {"type": "string", "description": "邮件主题"},
"body": {"type": "string", "description": "邮件正文"}
},
"required": ["to", "subject", "body"]
},
handler=send_email
)
# 工具4:执行代码
def run_python_code(code: str) -> str:
"""在安全沙箱中执行Python代码"""
try:
# 限制可用的内置函数
safe_globals = {"__builtins__": {
"print": print, "len": len, "range": range,
"int": int, "float": float, "str": str, "list": list,
"dict": dict, "sum": sum, "max": max, "min": min,
"sorted": sorted, "enumerate": enumerate, "zip": zip
}}
local_vars = {}
exec(code, safe_globals, local_vars)
return "执行成功"
except Exception as e:
return f"代码执行错误:{str(e)}"
registry.register(
name="run_python_code",
description="执行Python代码并返回结果,可用于数据分析、计算等任务",
parameters={
"type": "object",
"properties": {
"code": {"type": "string", "description": "要执行的Python代码"}
},
"required": ["code"]
},
handler=run_python_code
)
2. 实现 Agent 核心循环
# agent/core.py
from openai import OpenAI
from agent.tools import registry
import json
class Agent:
"""AI Agent 核心类"""
def __init__(self, model="deepseek-v4", base_url=None, api_key=None):
self.client = OpenAI(
base_url=base_url or "https://api.deepseek.com/v1",
api_key=api_key or "your-api-key"
)
self.model = model
self.messages = [
{
"role": "system",
"content": """你是一个AI Agent,可以自主使用工具完成任务。
你需要:
1. 分析用户需求
2. 规划执行步骤
3. 调用合适的工具
4. 根据工具返回结果决定下一步
5. 最终给出完整答案
记住:一次只调用一个工具,不要同时调用多个。"""
}
]
self.max_steps = 10 # 防止无限循环
def run(self, user_input: str) -> str:
"""执行用户指令"""
self.messages.append({"role": "user", "content": user_input})
for step in range(self.max_steps):
print(f"\n--- 步骤 {step + 1} ---")
# 调用大模型
response = self.client.chat.completions.create(
model=self.model,
messages=self.messages,
tools=registry.get_openai_tools(),
tool_choice="auto"
)
msg = response.choices[0].message
# 如果没有调用工具,说明任务完成
if not msg.tool_calls:
print("任务完成!")
self.messages.append(msg)
return msg.content
# 处理工具调用
self.messages.append(msg)
for tool_call in msg.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"调用工具:{func_name}")
print(f"参数:{json.dumps(func_args, ensure_ascii=False, indent=2)}")
# 执行工具
result = registry.call(func_name, func_args)
print(f"结果:{result[:200]}...")
# 将工具结果返回给大模型
self.messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
return "达到最大步骤限制,任务未完成。"
# ========== 使用示例 ==========
if __name__ == "__main__":
agent = Agent(model="deepseek-v4")
# 示例1:自动浏览网页并总结
result = agent.run("帮我打开 https://news.ycombinator.com,总结今天排名前5的热门话题")
print(result)
# 示例2:搜索+分析+发邮件
result = agent.run("""
1. 搜索「2026年 Python 最新版本」
2. 总结主要更新内容
3. 写一封邮件把总结发给 team@example.com,主题是「Python最新版本更新摘要」
""")
print(result)
这个最小 Agent 框架的核心就是 大模型 + 工具 + 循环,总共不到 100 行核心代码。但它已经能完成相当复杂的任务。
方案二:OpenClaw —— 开箱即用的全能 Agent
如果你不想自己写代码,OpenClaw 是目前最火的开源 AI Agent 框架,GitHub 27 天获得 43,000 Star。
安装(3分钟)
# 方式一:一键安装(推荐)
curl -fsSL https://openclaw.ai/install.sh | sh
# 方式二:pip 安装
pip install openclaw
# 方式三:Docker 部署
docker run -d -v ~/.openclaw:/root/.openclaw -p 3000:3000 openclaw/openclaw
配置大模型
# ~/.openclaw/config.yaml
model:
provider: deepseek # 支持 openai / claude / deepseek / qwen
api_key: sk-xxx # 你的 API Key
model: deepseek-v4 # 模型名称
# 或者用本地 Ollama
model:
provider: ollama
base_url: http://localhost:11434
model: deepseek-r1:14b
内置能力
OpenClaw 开箱即用的能力包括:
| 能力 | 说明 | 典型场景 |
|---|---|---|
| 🔍 网页浏览 | 自动打开浏览器、抓取内容 | 信息收集、竞品调研 |
| 📧 邮件管理 | 读写、发送邮件 | 自动回复、日报生成 |
| 📁 文件管理 | 读写本地文件 | 整理文档、批量处理 |
| 💻 代码执行 | 运行 Python/Shell | 数据分析、自动化脚本 |
| 🗓️ 日历管理 | 创建/查询日程 | 会议安排、提醒 |
| 🔗 API调用 | 调用任意HTTP API | 集成第三方服务 |
实战:自动收集行业资讯并发送日报
# ~/.openclaw/workflows/daily-news.yaml
name: "每日行业资讯汇总"
description: "自动抓取AI行业新闻,生成摘要,发送邮件"
triggers:
- schedule: "0 9 * * 1-5" # 工作日早9点
steps:
- name: "搜索AI行业新闻"
tool: browse_web
params:
url: "https://news.ycombinator.com"
extract_type: "text"
- name: "搜索36氪AI频道"
tool: browse_web
params:
url: "https://36kr.com/information/AI/"
extract_type: "text"
- name: "生成资讯摘要"
tool: llm
params:
prompt: |
根据以上抓取的内容,整理出今日5条最重要的AI行业资讯。
格式:序号. 标题 —— 一句话摘要(来源)
- name: "发送邮件"
tool: send_email
params:
to: "team@company.com"
subject: "📰 AI行业日报 - {{date}}"
body: "{{steps.生成资讯摘要.result}}"
# 手动执行一次
openclaw run daily-news
# 查看执行日志
openclaw logs daily-news
方案三:Page Agent —— 给任何网页加 AI 能力
阿里开源的 Page Agent 项目,只需要一行 JS 代码,就能把任何网页变成 AI Agent:
<!-- 在任意网页的控制台执行,或作为Chrome扩展注入 -->
<script src="https://cdn.jsdelivr.net/npm/page-agent/dist/page-agent.min.js"></script>
<script>
PageAgent.init({
model: "deepseek-v4",
apiKey: "sk-xxx",
// 可以让AI操作当前网页
capabilities: ["click", "input", "scroll", "extract", "navigate"]
});
</script>
执行后,页面右下角会出现一个 AI 助手浮窗,你可以用自然语言让 AI 操作当前网页:
你:「帮我把这个表单填写一下,姓名张三,邮箱 zhangsan@example.com」
AI:[自动找到表单字段并填入]
你:「把这个页面上所有价格提取出来,做个对比表格」
AI:[自动抓取页面数据并生成表格]
适用场景:
- 🛒 电商比价:自动抓取多个平台的价格
- 📊 数据录入:自动填写重复性表单
- 🔍 信息提取:从网页中提取结构化数据
Agent 开发的 5 个踩坑经验
经过实际项目踩坑,总结出以下关键经验:
1. 一定要设最大步骤限制
# ✅ 正确:限制最大循环次数
self.max_steps = 10
# ❌ 错误:不加限制,Agent 可能无限循环
while True:
response = model.generate(...)
真实案例:我第一次跑 Agent 时,让它「搜索某个话题」,结果它一直在搜索-总结-再搜索之间循环了 47 次,烧了 2 万 token。
2. 工具描述要清晰具体
# ❌ 模糊描述:大模型可能误用
"description": "获取网页信息"
# ✅ 清晰描述:明确工具的能力边界
"description": "抓取指定URL的网页正文内容,返回纯文本格式。不支持JavaScript渲染的页面。返回内容限制在3000字以内。"
3. 错误处理要到位
# ✅ 每个工具都要有 try-except
def browse_web(url: str):
try:
resp = requests.get(url, timeout=10)
resp.raise_for_status()
# ...处理逻辑
except requests.Timeout:
return "错误:网页访问超时,请检查URL是否正确"
except requests.ConnectionError:
return "错误:无法连接到该网站"
except Exception as e:
return f"未知错误:{str(e)}"
工具出错后,错误信息会返回给大模型,让它决定是重试还是换策略。如果错误信息不够清晰,Agent 会陷入混乱。
4. 结果要做截断
大模型的上下文窗口是有限的。工具返回的内容如果太长(比如一整个网页的全文),会快速耗尽上下文。
# ✅ 截断过长的结果
result = scraper.get_content(url)
if len(result) > 3000:
result = result[:3000] + "\n...(内容已截断)"
5. 敏感操作需要人类确认
# 发邮件、删除文件等危险操作,加确认步骤
DANGEROUS_TOOLS = {"send_email", "delete_file", "execute_shell"}
if func_name in DANGEROUS_TOOLS:
confirm = input(f"Agent 想要执行 {func_name},参数:{func_args}。确认执行?(y/n): ")
if confirm.lower() != "y":
result = "用户取消了此操作"
2026 AI Agent 方案对比
| 方案 | 上手难度 | 灵活性 | 适用场景 | 成本 |
|---|---|---|---|---|
| 自研 Python Agent | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 需要高度定制 | API 费用 |
| OpenClaw | ⭐ | ⭐⭐⭐ | 个人助手、自动化 | API 费用 |
| Dify + Agent | ⭐⭐ | ⭐⭐⭐⭐ | 企业级应用 | 开源免费/云版 |
| Page Agent | ⭐ | ⭐⭐ | 网页自动化 | API 费用 |
| Hermes Agent | ⭐⭐ | ⭐⭐⭐ | 多模型编排 | 开源免费 |
总结
AI Agent 不是什么玄学,本质上就是 大模型 + Function Calling + 循环执行。理解了这个核心模式,你可以用任何编程语言、任何大模型构建自己的 Agent。
2026 年的 AI Agent 生态已经非常成熟:
- 想省事:用 OpenClaw,3 分钟部署,开箱即用
- 想定制:自研 Python Agent,100 行核心代码搞定
- 想企业级:Dify + Agent,拖拽式编排,支持团队协作
重要的是动手开始。从一个最简单的「搜索+总结」Agent 开始,逐步添加工具,逐步提升复杂度。你会发现,AI Agent 给生产力带来的提升,远比你想象的要大。
关于作者
长期关注大模型应用落地与云服务器实战,专注技术在企业场景中的落地实践。
个人博客:yunduancloud.icu —— 持续更新云计算、AI大模型实战教程,欢迎访问交流。