保姆级教程:从零搭建你的第一个AI Agent

保姆级教程:从零搭建你的第一个AI Agent
在这里插入图片描述

保姆级教程:从零搭建你的第一个 AI Agent(附完整可运行代码)

手把手教你,用 Python 在 2 小时内构建一个能自主规划、调用工具、完成任务的 AI Agent

预计完成时间:
2 小时
所需技能: 基础 Python、会用命令行
适合人群: 想入门 AI Agent 开发的同学,不限工作年限

前言:为什么 2026 年你必须懂 Agent?

如果说 2024 年是大模型的元年,那 2026 年就是 AI Agent 的爆发年

现在的 AI 已经不只是"聊天机器人"了——它开始接管我们的 IDE、终端、浏览器,甚至整个工作流。GitHub 上 AI 相关仓库突破 430 万,其中 Agent 框架类项目增速最猛。

但很多人对 Agent 的理解还停留在"就是 ChatGPT 加了几个插件"的阶段。

这篇文章要做的,就是把 Agent 的底层逻辑彻底讲清楚,并带你从零写出一个真正能用的 Agent。

不是调用现成框架的那种"Hello World",而是理解每一行代码在做什么,搞清楚 Agent 的核心机制,以后遇到任何 Agent 框架都能快速上手。


一、先搞清楚:AI Agent 到底是什么?

很多教程上来就贴代码,但如果你不理解 Agent 的核心思想,代码写完了也是一头雾水。

1.1 普通 LLM 调用 vs Agent

普通 LLM 调用是这样的:

用户输入 → 大模型 → 输出结果 

一问一答,模型不会主动做任何事,你问什么它答什么,仅此而已。

AI Agent 是这样的:

用户给目标 → Agent 自主规划步骤 → 调用工具执行 → 观察结果 → 继续规划 → ... → 完成目标 

Agent 的核心在于一个循环:思考(Think)→ 行动(Act)→ 观察(Observe),不断迭代,直到任务完成。

这个循环有个专业名字,叫 ReAct(Reasoning + Acting),是目前最主流的 Agent 范式。

1.2 Agent 的三个核心组件

一个完整的 Agent 由三部分组成:

组件作用类比
大脑(LLM)负责推理、规划、决策人的大脑
工具(Tools)执行具体操作(搜索、计算、读写文件等)人的双手
记忆(Memory)存储历史对话和中间结果人的记忆

理解了这三个组件,你就理解了 Agent 的本质。

1.3 我们要做什么?

本教程将带你从零构建一个任务助手 Agent,它能够:

  • ✅ 接收自然语言任务描述
  • ✅ 自主拆解任务步骤
  • ✅ 调用工具(计算器、文件读写、网络请求)
  • ✅ 根据工具返回结果调整计划
  • ✅ 最终输出完整的任务结果

第一阶段:环境准备(15 分钟)

第 1 步:安装依赖

# 创建虚拟环境(强烈推荐,避免依赖冲突) python -m venv agent-env source agent-env/bin/activate # Linux/macOS agent-env\Scripts\activate # Windows# 安装核心依赖 pip install openai python-dotenv requests colorama # 验证安装 python -c"import openai; print('OpenAI SDK 安装成功')"
💡 没有 OpenAI API Key? 可以用国内的兼容接口(如 DeepSeek、智谱 GLM),只需修改 base_url 即可,后面会说。

第 2 步:项目结构初始化

mkdir my-agent &&cd my-agent # 创建目录结构mkdir-p src/{tools,memory,core}mkdir-p tests mkdir-p logs # 创建文件touch src/__init__.py touch src/tools/__init__.py touch src/memory/__init__.py touch src/core/__init__.py touch .env touch main.py 

最终目录结构如下:

my-agent/ ├── src/ │ ├── core/ │ │ ├── __init__.py │ │ ├── agent.py # Agent 核心逻辑 │ │ └── llm_client.py # LLM 调用封装 │ ├── tools/ │ │ ├── __init__.py │ │ ├── calculator.py # 计算器工具 │ │ ├── file_tool.py # 文件读写工具 │ │ └── web_tool.py # 网络请求工具 │ └── memory/ │ ├── __init__.py │ └── conversation.py # 对话记忆 ├── tests/ ├── logs/ ├── .env # API Key 配置 └── main.py # 入口文件 

第 3 步:配置 API Key

编辑 .env 文件:

# OpenAI 官方OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx OPENAI_BASE_URL=https://api.openai.com/v1 MODEL_NAME=gpt-4o-mini # 或者使用 DeepSeek(国内更稳定,价格更低)# OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx# OPENAI_BASE_URL=https://api.deepseek.com/v1# MODEL_NAME=deepseek-chat# 或者使用智谱 GLM# OPENAI_API_KEY=xxxxxxxxxxxxxxxx# OPENAI_BASE_URL=https://open.bigmodel.cn/api/paas/v4# MODEL_NAME=glm-4-flash
推荐新手用 DeepSeek:价格极低(约 OpenAI 的 1/20),API 完全兼容 OpenAI 格式,国内访问稳定。

第二阶段:构建核心组件(50 分钟)

第 4 步:封装 LLM 客户端

新建 src/core/llm_client.py

""" LLM 客户端封装 统一管理大模型调用,支持多种 API 提供商 """import os from openai import OpenAI from dotenv import load_dotenv load_dotenv()classLLMClient:"""大模型调用客户端"""def__init__(self): self.client = OpenAI( api_key=os.getenv("OPENAI_API_KEY"), base_url=os.getenv("OPENAI_BASE_URL","https://api.openai.com/v1"),) self.model = os.getenv("MODEL_NAME","gpt-4o-mini") self.total_tokens =0# 统计 token 消耗defchat(self, messages:list, temperature:float=0.7)->str:""" 发送对话请求 Args: messages: 对话历史,格式为 [{"role": "user/assistant/system", "content": "..."}] temperature: 温度参数,越高越随机(0~2) Returns: 模型回复的文本内容 """ response = self.client.chat.completions.create( model=self.model, messages=messages, temperature=temperature,)# 统计 token 消耗 self.total_tokens += response.usage.total_tokens return response.choices[0].message.content defget_token_usage(self)->dict:"""获取 token 使用统计"""return{"total_tokens": self.total_tokens,"model": self.model,}# 使用示例if __name__ =="__main__": client = LLMClient() messages =[{"role":"system","content":"你是一个有帮助的助手。"},{"role":"user","content":"你好,请用一句话介绍自己。"},] reply = client.chat(messages)print(f"模型回复:{reply}")print(f"Token 消耗:{client.get_token_usage()}")

第 5 步:构建工具系统

Agent 的能力来自工具。我们先实现三个最常用的工具。

工具一:计算器src/tools/calculator.py

""" 计算器工具 让 Agent 能够执行数学计算,避免大模型的计算幻觉 """import math classCalculatorTool:"""安全的数学计算工具""" name ="calculator" description =("执行数学计算。输入一个数学表达式字符串,返回计算结果。""支持:加减乘除、幂运算、开方、三角函数等。""示例输入:'2 + 3 * 4'、'sqrt(16)'、'sin(3.14/2)'")# 允许使用的安全函数白名单 SAFE_FUNCTIONS ={"abs":abs,"round":round,"sqrt": math.sqrt,"pow": math.pow,"sin": math.sin,"cos": math.cos,"tan": math.tan,"log": math.log,"log10": math.log10,"log2": math.log2,"pi": math.pi,"e": math.e,"ceil": math.ceil,"floor": math.floor,}defrun(self, expression:str)->str:""" 执行数学计算 Args: expression: 数学表达式字符串 Returns: 计算结果字符串,或错误信息 """try:# 安全求值:只允许白名单中的函数 result =eval(expression,{"__builtins__":{}}, self.SAFE_FUNCTIONS)returnf"计算结果:{expression} = {result}"except ZeroDivisionError:return"错误:除数不能为零"except Exception as e:returnf"计算错误:{str(e)},请检查表达式格式"# 测试if __name__ =="__main__": calc = CalculatorTool()print(calc.run("2 + 3 * 4"))# 14print(calc.run("sqrt(144)"))# 12.0print(calc.run("sin(pi/2)"))# 1.0print(calc.run("log(e)"))# 1.0

工具二:文件读写src/tools/file_tool.py

""" 文件读写工具 让 Agent 能够读取和写入本地文件 """import os classFileTool:"""文件操作工具""" name ="file_tool" description =("读取或写入本地文件。""操作类型:'read'(读取文件内容)或 'write'(写入内容到文件)。""输入格式:'read:文件路径' 或 'write:文件路径:文件内容'")# 限制可操作的目录(安全沙箱) ALLOWED_DIR ="./workspace"def__init__(self):# 确保工作目录存在 os.makedirs(self.ALLOWED_DIR, exist_ok=True)defrun(self, command:str)->str:""" 执行文件操作 Args: command: 操作命令,格式见 description Returns: 操作结果字符串 """ parts = command.split(":",2)iflen(parts)<2:return"错误:命令格式不正确,请使用 'read:路径' 或 'write:路径:内容'" action = parts[0].strip().lower() file_path = os.path.join(self.ALLOWED_DIR, parts[1].strip())# 安全检查:防止路径穿越攻击ifnot os.path.abspath(file_path).startswith( os.path.abspath(self.ALLOWED_DIR)):return"错误:不允许访问工作目录以外的文件"if action =="read":return self._read_file(file_path)elif action =="write":iflen(parts)<3:return"错误:写入操作需要提供文件内容" content = parts[2]return self._write_file(file_path, content)else:returnf"错误:不支持的操作类型 '{action}',请使用 'read' 或 'write'"def_read_file(self, path:str)->str:"""读取文件"""ifnot os.path.exists(path):returnf"错误:文件 '{path}' 不存在"try:withopen(path,"r", encoding="utf-8")as f: content = f.read()returnf"文件内容:\n{content}"except Exception as e:returnf"读取失败:{str(e)}"def_write_file(self, path:str, content:str)->str:"""写入文件"""try: os.makedirs(os.path.dirname(path), exist_ok=True)withopen(path,"w", encoding="utf-8")as f: f.write(content)returnf"成功写入文件:{path}({len(content)} 字符)"except Exception as e:returnf"写入失败:{str(e)}"# 测试if __name__ =="__main__": tool = FileTool()print(tool.run("write:test.txt:Hello, Agent World!"))print(tool.run("read:test.txt"))

工具三:网络请求src/tools/web_tool.py

""" 网络请求工具 让 Agent 能够获取网页内容(简化版) """import requests from urllib.parse import urlparse classWebTool:"""网络请求工具""" name ="web_tool" description =("获取指定 URL 的网页文本内容。""输入一个完整的 URL(需包含 http:// 或 https://),""返回页面的纯文本内容(前 2000 字符)。""示例:'https://example.com'") TIMEOUT =10# 请求超时时间(秒) MAX_CONTENT_LENGTH =2000# 最大返回内容长度defrun(self, url:str)->str:""" 获取网页内容 Args: url: 目标 URL Returns: 网页文本内容或错误信息 """# 验证 URL 格式 parsed = urlparse(url.strip())if parsed.scheme notin("http","https"):return"错误:URL 必须以 http:// 或 https:// 开头"try: headers ={"User-Agent":("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ""AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36")} response = requests.get(url, headers=headers, timeout=self.TIMEOUT) response.raise_for_status() response.encoding = response.apparent_encoding # 简单提取文本(去除 HTML 标签) text = self._strip_html(response.text) truncated = text[: self.MAX_CONTENT_LENGTH]returnf"网页内容(前{self.MAX_CONTENT_LENGTH}字符):\n{truncated}"except requests.exceptions.Timeout:returnf"错误:请求超时(>{self.TIMEOUT}秒)"except requests.exceptions.HTTPError as e:returnf"错误:HTTP 请求失败,状态码 {e.response.status_code}"except Exception as e:returnf"请求失败:{str(e)}"def_strip_html(self, html:str)->str:"""简单去除 HTML 标签"""import re # 去除 script 和 style 标签及其内容 html = re.sub(r"<(script|style)[^>]*>.*?</\1>","", html, flags=re.DOTALL)# 去除所有 HTML 标签 html = re.sub(r"<[^>]+>"," ", html)# 合并多余空白 html = re.sub(r"\s+"," ", html).strip()return html 

第 6 步:构建对话记忆

新建 src/memory/conversation.py

""" 对话记忆模块 管理 Agent 的上下文历史,支持长度限制和摘要压缩 """classConversationMemory:"""对话历史管理"""def__init__(self, max_turns:int=20, system_prompt:str=""):""" Args: max_turns: 最大保留的对话轮数(超出后自动裁剪旧记录) system_prompt: 系统提示词 """ self.max_turns = max_turns self.system_prompt = system_prompt self._history:list[dict]=[]defadd_message(self, role:str, content:str):""" 添加一条消息到历史 Args: role: 角色,'user' / 'assistant' / 'system' content: 消息内容 """ self._history.append({"role": role,"content": content})# 超出最大轮数时,裁剪最早的记录(保留 system 消息) non_system =[m for m in self._history if m["role"]!="system"]iflen(non_system)> self.max_turns *2:# 删除最早的一轮(user + assistant 各一条)for i, msg inenumerate(self._history):if msg["role"]=="user": self._history.pop(i)if i <len(self._history)and self._history[i]["role"]=="assistant": self._history.pop(i)breakdefget_messages(self)->list[dict]:""" 获取完整的消息列表(包含 system prompt) Returns: 适合直接传给 LLM 的消息列表 """ messages =[]if self.system_prompt: messages.append({"role":"system","content": self.system_prompt}) messages.extend(self._history)return messages defclear(self):"""清空对话历史""" self._history.clear()def__len__(self)->int:returnlen(self._history)def__repr__(self)->str:returnf"ConversationMemory(turns={len(self._history)//2}, max={self.max_turns})"

第三阶段:实现 Agent 核心逻辑(40 分钟)

这是整个教程最关键的部分。

第 7 步:实现 ReAct Agent

新建 src/core/agent.py

""" ReAct Agent 核心实现 思路:Thought(思考)→ Action(行动)→ Observation(观察)→ 循环 """import re import json from colorama import Fore, Style, init from src.core.llm_client import LLMClient from src.memory.conversation import ConversationMemory from src.tools.calculator import CalculatorTool from src.tools.file_tool import FileTool from src.tools.web_tool import WebTool # 初始化彩色输出 init(autoreset=True)# ── Agent 系统提示词 ────────────────────────────────────────────────────────── SYSTEM_PROMPT ="""你是一个智能任务助手,能够通过调用工具来完成用户交给你的任务。 ## 你拥有以下工具:{tool_descriptions}## 工作流程(严格遵守): 每次回复必须按照以下格式,直到任务完成: 

Thought: [分析当前情况,思考下一步该做什么]
Action: [工具名称]
Action Input: [工具的输入参数]

 当工具返回结果后,你会收到: 

Observation: [工具返回的结果]

 然后继续思考,直到任务完成,最后输出: 

Thought: [最终思考,确认任务已完成]
Final Answer: [给用户的最终回答]

 ## 重要规则: 1. 每次只能调用一个工具 2. 如果不需要工具,直接输出 Final Answer 3. 遇到计算问题,必须使用 calculator 工具,不要自己心算 4. Action 字段只能填写工具名称,不能有其他内容 5. 如果工具返回错误,分析原因并尝试修正后重试 """ class ReActAgent: """ 基于 ReAct 范式的 AI Agent ReAct = Reasoning(推理)+ Acting(行动) 核心循环:Thought → Action → Observation → Thought → ... """ MAX_ITERATIONS = 10 # 最大迭代次数,防止死循环 def __init__(self): # 初始化工具 self.tools = { "calculator": CalculatorTool(), "file_tool": FileTool(), "web_tool": WebTool(), } # 构建工具描述(注入到 system prompt) tool_descriptions = "\n".join( f"- **{name}**:{tool.description}" for name, tool in self.tools.items() ) # 初始化 LLM 和记忆 self.llm = LLMClient() self.memory = ConversationMemory( max_turns=20, system_prompt=SYSTEM_PROMPT.format(tool_descriptions=tool_descriptions), ) def run(self, task: str) -> str: """ 执行一个任务 Args: task: 用户的任务描述(自然语言) Returns: Agent 的最终回答 """ print(f"\n{Fore.CYAN}{'='*60}") print(f"🤖 任务开始:{task}") print(f"{'='*60}{Style.RESET_ALL}\n") # 将任务加入记忆 self.memory.add_message("user", task) # ReAct 主循环 for iteration in range(1, self.MAX_ITERATIONS + 1): print(f"{Fore.YELLOW}── 第 {iteration} 轮迭代 ──{Style.RESET_ALL}") # 调用 LLM 获取下一步决策 response = self.llm.chat(self.memory.get_messages()) print(f"{Fore.GREEN}LLM 输出:\n{response}{Style.RESET_ALL}\n") # 解析 LLM 输出 parsed = self._parse_response(response) # 情况一:任务完成,返回最终答案 if parsed["type"] == "final_answer": self.memory.add_message("assistant", response) final = parsed["content"] print(f"\n{Fore.CYAN}{'='*60}") print(f"✅ 任务完成!") print(f"最终答案:{final}") print(f"Token 消耗:{self.llm.get_token_usage()}") print(f"{'='*60}{Style.RESET_ALL}\n") return final # 情况二:需要调用工具 elif parsed["type"] == "action": tool_name = parsed["tool"] tool_input = parsed["input"] print(f"{Fore.MAGENTA}🔧 调用工具:{tool_name}") print(f" 输入:{tool_input}{Style.RESET_ALL}") # 执行工具 observation = self._execute_tool(tool_name, tool_input) print(f"{Fore.BLUE}📋 工具返回:{observation}{Style.RESET_ALL}\n") # 将 LLM 输出和工具结果都加入记忆 self.memory.add_message("assistant", response) self.memory.add_message( "user", f"Observation: {observation}" ) # 情况三:解析失败,提示 LLM 修正格式 else: print(f"{Fore.RED}⚠️ 输出格式解析失败,提示 LLM 修正{Style.RESET_ALL}") self.memory.add_message("assistant", response) self.memory.add_message( "user", "你的输出格式不正确。请严格按照 Thought/Action/Action Input 或 Final Answer 格式回复。", ) # 超出最大迭代次数 return "任务未能在规定步骤内完成,请尝试简化任务描述。" def _parse_response(self, response: str) -> dict: """ 解析 LLM 的输出,提取 Action 或 Final Answer Returns: {"type": "action", "tool": "...", "input": "..."} {"type": "final_answer", "content": "..."} {"type": "unknown"} """ # 检查是否有 Final Answer final_match = re.search( r"Final Answer:\s*(.+?)(?:\n|$)", response, re.DOTALL ) if final_match: return {"type": "final_answer", "content": final_match.group(1).strip()} # 检查是否有 Action action_match = re.search(r"Action:\s*(\w+)", response) input_match = re.search( r"Action Input:\s*(.+?)(?:\nThought|\nAction|\nObservation|$)", response, re.DOTALL, ) if action_match and input_match: return { "type": "action", "tool": action_match.group(1).strip(), "input": input_match.group(1).strip(), } return {"type": "unknown"} def _execute_tool(self, tool_name: str, tool_input: str) -> str: """ 执行指定工具 Args: tool_name: 工具名称 tool_input: 工具输入 Returns: 工具执行结果 """ if tool_name not in self.tools: available = ", ".join(self.tools.keys()) return f"错误:工具 '{tool_name}' 不存在。可用工具:{available}" try: return self.tools[tool_name].run(tool_input) except Exception as e: return f"工具执行异常:{str(e)}" def reset(self): """重置 Agent 状态(清空对话历史)""" self.memory.clear() print("Agent 状态已重置") 

第四阶段:组装并运行(20 分钟)

第 8 步:创建入口文件

新建 main.py

""" AI Agent 入口文件 """from src.core.agent import ReActAgent defmain(): agent = ReActAgent()print("="*60)print("🤖 AI Agent 已启动!输入 'quit' 退出,'reset' 重置对话")print("="*60)whileTrue:try: task =input("\n📝 请输入任务:").strip()except(KeyboardInterrupt, EOFError):print("\n\n👋 再见!")breakifnot task:continueif task.lower()=="quit":print("👋 再见!")breakif task.lower()=="reset": agent.reset()continue# 执行任务 agent.run(task)if __name__ =="__main__": main()

第 9 步:运行!

python main.py 

你会看到类似这样的输出:

============================================================ 🤖 AI Agent 已启动!输入 'quit' 退出,'reset' 重置对话 ============================================================ 📝 请输入任务:计算 (123 + 456) * 789 的结果,然后把结果写入 result.txt 文件 ============================================================ 🤖 任务开始:计算 (123 + 456) * 789 的结果,然后把结果写入 result.txt 文件 ============================================================ ── 第 1 轮迭代 ── LLM 输出: Thought: 用户需要我先计算数学表达式,再把结果写入文件。先用计算器工具计算。 Action: calculator Action Input: (123 + 456) * 789 🔧 调用工具:calculator 输入:(123 + 456) * 789 📋 工具返回:计算结果:(123 + 456) * 789 = 466731 ── 第 2 轮迭代 ── LLM 输出: Thought: 计算结果是 466731,现在把这个结果写入 result.txt 文件。 Action: file_tool Action Input: write:result.txt:计算结果:(123 + 456) * 789 = 466731 🔧 调用工具:file_tool 输入:write:result.txt:计算结果:(123 + 456) * 789 = 466731 📋 工具返回:成功写入文件:./workspace/result.txt(26 字符) ── 第 3 轮迭代 ── LLM 输出: Thought: 两个任务都完成了,可以给出最终答案。 Final Answer: 计算结果为 466731,已成功写入 result.txt 文件。 ============================================================ ✅ 任务完成! 最终答案:计算结果为 466731,已成功写入 result.txt 文件。 Token 消耗:{'total_tokens': 847, 'model': 'gpt-4o-mini'} ============================================================ 

第五阶段:扩展与优化(自选)

第 10 步:添加更多工具

工具系统是 Agent 能力的上限。你可以轻松扩展更多工具:

# 示例:添加一个"当前时间"工具classTimeTool: name ="get_time" description ="获取当前的日期和时间。无需输入参数,直接调用即可。"defrun(self,_:str="")->str:from datetime import datetime now = datetime.now()returnf"当前时间:{now.strftime('%Y年%m月%d日 %H:%M:%S')}"# 示例:添加一个"天气查询"工具classWeatherTool: name ="get_weather" description ="查询指定城市的天气。输入城市名称(中文),返回天气信息。"defrun(self, city:str)->str:import requests try: url =f"https://wttr.in/{city}?format=3&lang=zh" resp = requests.get(url, timeout=5)returnf"天气信息:{resp.text.strip()}"except Exception as e:returnf"天气查询失败:{str(e)}"

把新工具注册到 Agent 中:

# 在 ReActAgent.__init__ 中添加 self.tools["get_time"]= TimeTool() self.tools["get_weather"]= WeatherTool()

就这么简单,Agent 立刻获得了新能力。

第 11 步:添加流式输出

让 Agent 的思考过程实时显示,体验更好:

defchat_stream(self, messages:list):"""流式输出版本""" stream = self.client.chat.completions.create( model=self.model, messages=messages, stream=True,# 开启流式) full_response =""for chunk in stream: delta = chunk.choices[0].delta.content or""print(delta, end="", flush=True) full_response += delta print()# 换行return full_response 

第 12 步:持久化对话历史

让 Agent 在重启后还能记住之前的对话:

import json import os classPersistentMemory(ConversationMemory):"""支持持久化的对话记忆"""def__init__(self, save_path:str="./logs/memory.json",**kwargs):super().__init__(**kwargs) self.save_path = save_path self._load()# 启动时自动加载历史defadd_message(self, role:str, content:str):super().add_message(role, content) self._save()# 每次添加消息后自动保存def_save(self): os.makedirs(os.path.dirname(self.save_path), exist_ok=True)withopen(self.save_path,"w", encoding="utf-8")as f: json.dump(self._history, f, ensure_ascii=False, indent=2)def_load(self):if os.path.exists(self.save_path):withopen(self.save_path,"r", encoding="utf-8")as f: self._history = json.load(f)print(f"已加载 {len(self._history)} 条历史记录")

六、常见问题 & 排错指南

Q:运行报错 AuthenticationError

检查 .env 文件中的 API Key 是否正确,注意不要有多余的空格或引号。 

Q:Agent 陷入死循环,一直调用同一个工具?

通常是 system prompt 写得不够清晰,或者工具描述有歧义。 可以在 system prompt 中加一条: "如果同一个工具连续调用 3 次仍然失败,请直接输出 Final Answer 说明原因。" 

Q:LLM 输出格式不对,解析总是失败?

换用更强的模型(如 gpt-4o 替代 gpt-4o-mini), 或者在 system prompt 中加入更多格式示例(few-shot)。 

Q:工具调用很慢,怎么优化?

1. 对工具结果加缓存(相同输入直接返回缓存结果) 2. 对不依赖顺序的工具调用,改为并行执行 3. 减少 MAX_ITERATIONS,强制 Agent 更高效地规划 

Q:想用本地模型(Ollama)怎么接入?

# Ollama 完全兼容 OpenAI API 格式,只需修改 .env: OPENAI_API_KEY=ollama # 随便填,Ollama 不验证 OPENAI_BASE_URL=http://localhost:11434/v1 MODEL_NAME=qwen2.5:7b # 你本地拉取的模型名

七、完整代码汇总

所有代码已整理到以下结构,可直接克隆使用:

my-agent/ ├── src/ │ ├── core/ │ │ ├── agent.py ✅ ReAct Agent 核心 │ │ └── llm_client.py ✅ LLM 客户端 │ ├── tools/ │ │ ├── calculator.py ✅ 计算器 │ │ ├── file_tool.py ✅ 文件读写 │ │ └── web_tool.py ✅ 网络请求 │ └── memory/ │ └── conversation.py ✅ 对话记忆 ├── .env ✅ API 配置 └── main.py ✅ 入口文件 

八、总结

恭喜你!完成这个教程后,你已经掌握了:

知识点掌握程度
AI Agent 的核心概念(LLM + Tools + Memory)
ReAct 范式(Thought → Action → Observation)
如何封装 LLM 调用客户端
如何设计和实现工具系统
如何管理对话上下文记忆
如何解析 LLM 的结构化输出
如何扩展 Agent 能力(添加新工具)

下一步可以探索的方向:

  • 🔍 RAG(检索增强生成):给 Agent 接入知识库,让它能回答私有文档的问题
  • 🤝 Multi-Agent:多个 Agent 协作完成复杂任务
  • 🧠 长期记忆:用向量数据库存储历史,让 Agent 真正"记住"你
  • 🌐 Web Agent:给 Agent 接入浏览器控制能力,自动操作网页
  • 异步 Agent:用 asyncio 实现并发工具调用,大幅提升效率

Read more

飞书/钉钉/QQ 机器人一站式搞定!OpenClaw Docker 部署教程

飞书/钉钉/QQ 机器人一站式搞定!OpenClaw Docker 部署教程

一、概述 OpenClaw-Docker-CN-IM(OpenClaw 中国IM平台整合Docker版本)是一款容器化应用,旨在提供集成中国主流IM平台的AI机器人网关解决方案。该镜像预装并配置了飞书、钉钉、QQ机器人、企业微信等插件,支持通过环境变量灵活配置,实现快速部署与数据持久化。 同时集成了OpenCode AI代码助手、Playwright浏览器自动化工具及中文TTS语音合成功能,适用于需要构建多平台IM机器人的开发者与科研用户。 本指南将详细介绍其Docker部署流程,包括环境准备、镜像拉取、容器配置、功能测试及生产环境优化建议,帮助用户快速实现服务部署与应用。 二、项目简介与核心特性 2.1 项目简介 OpenClaw 中国 IM 插件整合版 Docker 镜像,预装并配置了飞书、钉钉、QQ机器人、企业微信等主流中国 IM 平台插件,让您可以快速部署一个支持多个中国 IM 平台的 AI 机器人网关。 官方项目地址: https://github.com/justlovemaki/

智能家居安防系统(有完整资料)

智能家居安防系统(有完整资料)

资料查找方式: 特纳斯电子(电子校园网):搜索下面编号即可 编号: HJJ-32-2021-006 设计简介: 本设计是基于单片机的智能家居安防系统,主要实现以下功能: 主机: * 显示从机一样一氧化碳值 * 控制从机窗户开关以及是否有人在家 * 从机报警时,显示报警的从机号 从机: * 实时监测一氧化碳,且一氧化碳值过高打开窗户、报警 * 实时监测火焰,且检测到火焰打开喷淋、报警 * 家中无人时人体红外检测到人报警 * 报警时,通过GSM模块向手机发送短信 * 窗户、喷淋均可通过按键控制 标签:STM32单片机、zigbee、家居安防 题目扩展:智能安防系统、智能家居 1. 中控部分 * 核心控制器:采用STM32F1032单片机,负责获取输入数据、进行数据处理,并控制输出部分的操作。 * 功能:实现智能家居安防系统的逻辑控制,包括火焰检测、一氧化碳浓度检测、人体红外检测、窗户开关控制、报警等功能。 2. 输入部分 主机输入:

Trae x Vizro:低代码构建专业数据可视化仪表板的高效方案

Trae x Vizro:低代码构建专业数据可视化仪表板的高效方案

声明:文章为本人真实测评博客,非广告,并没有推广该平台 ,为用户体验文章 目录 * 前言 * 一.核心工具与优势解析 * 低代码高效开发 * 专业视觉设计 * 高度灵活可定制 * AI赋能创新 * 二.操作步骤:从安装到生成效果 * 第一步. 获取MCP配置代码 * 第二步:下载 * 第三步:在 Trae 中导入 MCP 配置并建立连接 * 三. 实战:用Vizro MCP快速构建仪表板 * 1. 提出需求 * 2.智能体生成代码 * 3.查看运行结果 * 4.优化与部署 * 四.Vizro MCP核心功能解析 * get_vizro_chart_or_dashboard_plan * get_model_json_

从零开始使用ISSACLAB训练自己的机器人行走

从零开始使用ISSACLAB训练自己的机器人行走

ISAACLAB入门教程 作者:陈维耀 1. 环境配置 1.1 推荐配置 * 操作系统: Ubuntu 22.04 LTS * 显卡: NVIDIA RTX 4080或以上 1.2 ubuntu 22.04 LTS安装 参考ZEEKLOG的Ubuntu 16.04 LTS安装教程,将其中的ubuntu 16.04镜像文件替换为ubuntu 22.04镜像文件,其他步骤保持不变,建议/home与/usr的硬盘容量均不少于200G。 1.3 安装NVIDIA驱动 根据自身显卡型号与操作系统,选择对应的显卡驱动,建议选择550.xxx.xxx版本的显卡驱动,按照教程进行安装即可,安装完成后在终端输入nvidia-smi,若出现以下信息则表示驱动安装成功: Thu Jun 5