从0到0.1一个简易Agent的诞生
1. 开篇:我为什么想做一个简易 Agent
-
我想验证什么?
我想真正弄清楚:AI 模型是如何调用工具,又是如何接收并利用工具执行结果。相比只停留在概念层面,我更想亲手把这条调用链路跑通,把它背后的实现步骤看清楚。 -
我为什么不想一开始就上复杂框架?
因为欲速则不达。我的目标不是为了重复造轮子,而是想通过“造轮子”这个过程,真正理解 Agent 是怎么运作的。与其一上来就依赖复杂框架,不如先从最简单的部分做起,再逐步把能力扩展开。 -
我心里对“简易 Agent”的定义是什么?
在当前这个阶段,我给“简易 Agent”的定义很朴素:一个支持多轮问答,并且能够执行 bash 命令行工具的 Demo。
2026 年初,我开始频繁接触到 Agent 这个词。虽然以前也接触过不少 AI 相关概念,但大多停留在“一知半解”的状态。借着这次机会,我希望把原本只是“知道”的东西,变成自己真正能够理解的知识。
我之所以选择从 Agent 入手,也是因为自己对 AI 的整体认知一直有些模糊。AI 模型、DeepSeek、千问、豆包、元宝、Agent、OpenClaw、Claude Code……这些概念经常一起出现,但它们之间到底是什么关系、各自解决什么问题,我其实并没有真正理清楚。
后来在自己动手搭了一个 OpenClaw 之后,我对 AI 的理解和能力被再次刷新了。以前我理解的 AI,更像是“你问它答”的一问一答;而现在我看到的 AI,则更像是“你说,它做”,能够一步一步地完成任务。也正是从那时起,我心里开始冒出一个问题:OpenClaw 这样的 Agent,到底是怎么做到这些事情的?
带着这个问题,我先去梳理了一些基础概念,比如 LLM、训练与推理、量化、Agent 等等。
在我当前的理解里,Agent 是一种具备操作能力的 AI 程序。它连接 AI 模型,负责调用工具,再把工具的执行结果返回给模型,作为后续推理的依据。在一次会话中,模型可能会多次调用不同工具,汇总执行结果之后,再给用户一个最终回答。而 Agent,正是连接“模型推理”和“工具执行”的那层中介。
对这些基础概念有了初步理解之后,我开始进一步思考:我能不能自己实现一个类似 OpenClaw 的 Agent?
既然凡事都该从易到难,那边先用 Python 做一个简单的、多轮互动的 Agent Demo。
2. 简单的多轮互动的 Agent 包含哪些功能
做之前,先确定简单的多轮互动 Agent 包含哪些功能,一个最基础的 Agent 至少可以拆成三个部分:
- 第一部分:它首先是一个能够记住上下文的多轮对话程序
- 第二部分:它开始能够根据任务决定是否调用工具
- 第三部分:它会把工具执行结果重新纳入上下文,继续完成任务
把这三部分整合起来,这个 Agent 就可以理解为:
一个能够进行多轮对话、协助 AI 模型调用工具,并将工具执行结果返回给模型继续处理的程序。
这一定义不复杂,但足够支撑我做出一个最小可运行的 Demo。先把这三个部分想清楚,比急着追求更复杂的能力更重要。
3. 简易 Agent 的基本框架
从用户输入开始,到调用 AI 模型 API,再到工具参与、返回结果,最后生成结论,这整个过程可以看作一次完整对话。
而当这个过程能够持续循环、反复进行时,就构成了 Agent 的基本框架。
换句话说,Agent 本质上就是一个能够维持对话、调用工具、再把结果接回对话中的循环程序。因此先关注两个最基础的问题:
- AI 模型 API 调用
- 用户输入文本与 AI 模型调用工具的执行和结果反馈

4. 实现 Agent Demo 代码
Demo 的实现代码:
import os
import logging
import subprocess
import json
from openai import OpenAI
from dotenv import load_dotenv
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
force=True,
)
load_dotenv(override=True)
DEEPSEEK_BASE_URL = os.environ.get('DEEPSEEK_BASE_URL', 'https://api.deepseek.com')
DEEPSEEK_API_KEY = os.environ.get('DEEPSEEK_API_KEY', 'YOUR_API_KEY')
DEFAULT_MODEL = os.environ.get('DEFAULT_MODEL', 'deepseek-v4-flash')
MODELS = [
'deepseek-v4-flash',
'deepseek-v4-pro'
]
TOOLS = [
{
"type": "function",
"function": {
"name": "powershell",
"description": "Windows PowerShell Command",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "可在Windows 10环境中运行的命令"
}
},
"required": ["command"]
}
}
}
]
client = OpenAI(
api_key = DEEPSEEK_API_KEY,
base_url = DEEPSEEK_BASE_URL
)
def run_powershell(arg: str) -> str:
result = subprocess.run(["powershell", "-Command", arg], capture_output=True, text=True)
return result.stdout
def llm_session(messages, model=DEFAULT_MODEL):
response = client.chat.completions.create(
model=model,
messages=messages,
tools=TOOLS,
stream=False
)
return response.choices[0].message
# 退出指令判断
def exit_check(s):
if s == '/exit':
return True
if s == '/quit':
return True
return False
system_prompt = "你是一个AI助手,用户程序运行在Windows 10环境,对话保持简洁,禁止“好的”之类无用的词语。"
messages = []
def main():
user_input = input("你 > ")
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": user_input})
while(exit_check(user_input) == False):
message = llm_session(messages)
messages.append(message)
logger.debug(message)
# 检查AI是否调用工具及限制AI单次对话中调用工具次数
if message.tool_calls is not None:
tool = message.tool_calls[0]
logger.debug(tool)
func_args = tool.function.arguments
exec_command = json.loads(func_args)["command"]
tool_result = run_powershell(exec_command)
print("tool > " + tool_result)
messages.append({"role": "tool", "tool_call_id": tool.id, "content": tool_result})
else:
print("AI > " + message.content)
user_input = input("你 > ")
messages.append({"role": "user", "content": user_input})
if __name__ == "__main__":
main()
运行程序后的效果如下:
你 > 今天星期几
tool > Saturday
AI > 今天是星期六。
你 > 是什么日期?
tool > 2026年5月9日
AI > 2026年5月9日。
你 > 明天是什么时候?
tool > 2026年5月10日
AI > 明天是2026年5月10日,星期日。
你 > 星期日是什么日子?
tool > 5月第一个星期日: 2026-05-03
5月第二个星期日: 2026-05-10
是母亲节
AI > 是**母亲节**(5月第二个星期日)。
你 > 母亲节是中国的传统节日吗?
AI > 不是。母亲节起源于美国,20世纪80年代才传入中国,属于**西方舶来节日**,并非中国传统节日。
中国的传统节日如春节、清明节、端午节、中秋节、重阳节等,才是本土文化传承。
从这个 Demo 可以看到 AI模型能够在对话中调用工具,并基于工具结果继续回答,整个程序的行为就已经和普通的一问一答不一样了。
5. 对 Agent 的理解
完成这个 Agent Demo 之后,我对 Agent 又多了一层更具体的理解。如果用一个更直观的比喻来描述:
- AI 模型更像是大脑
- Agent为 AI 提供了行动的躯体
- 工具则像是 Agent 伸向外部世界的触角
模型负责理解、判断和生成;Agent 负责衔接流程、组织上下文、调用工具;而工具的丰富程度和可用程度,则直接决定了 Agent 能做多复杂的事。
也正因为如此,我对 Agent 的认识:Agent 的能力边界,本质上不是由“会不会聊天”决定的,而是由它能不能稳定地连接模型、调用工具并处理结果决定的。
6. 遇到的问题
在实现过程中,我最先遇到的一个问题是:如果不限制 AI 调用工具的次数,就可能出现 AI 反复调用工具、甚至陷入循环的问题。
因此,在工具调用这一步,必须增加一个最大调用次数的判断,用来避免程序失控。
第二个问题是:工具执行过程中的报错和异常,如果不处理,会直接导致 Agent 意外中断。
而且一旦 Agent 中断退出,AI 模型也拿不到工具执行失败时的错误信息,自然也就无法根据报错内容自行修正下一次调用参数。
所以这个 Demo 后续还需要补充下面几项能力:
- 收集工具执行时的错误输出(
stderr) - 捕获并处理工具调用过程中的异常
- 尽量保证 Agent 在工具失败时依然能够继续运行,而不是直接退出
说到底,Agent 的关键不只是“能不能调用工具”,还包括调用失败之后,系统能不能继续运行。 这背后体现的,其实就是程序的健壮性。
附:参考资料
- Learn Claude Code:
https://learn.shareai.run/zh/ - DeepSeek API 文档:
https://api-docs.deepseek.com/zh-cn/guides/tool_calls
本文来自博客园,作者:吾AI科技,转载请注明原文链接:https://www.cnblogs.com/ilovetech/p/20007413

浙公网安备 33010602011771号