第1课:用20行Python造出你的第一个AI Agent

系列导读

这是**《12课拆解Claude Code架构》**系列的第 1 课。

整个系列用 12 个递进式 Python 课程,从最小 Agent 循环出发,逐步叠加工具注册、计划系统、子 Agent、技能加载、上下文压缩、任务持久化、后台执行、多 Agent 团队、自治协作,一直到 Worktree 隔离执行------覆盖一个生产级 Agent Harness 的全部核心机制。

第 1 课的格言:

"One loop & Bash is all you need" ------ 一个工具 + 一个循环 = 一个 Agent。

后面 11 个课程,循环本身一行不改。所有新机制都在循环之外叠加。所以这一课,是地基中的地基。


大模型的致命缺陷

Claude、GPT、Gemini,这些大模型能写代码、能分析 bug、能设计架构。但它们有一个致命缺陷:

碰不到真实世界。

不能读文件。不能跑测试。不能看报错。不能创建目录。不能执行任何命令。

你问它 "帮我创建一个 hello.py",它只能回复一段代码文本让你自己去复制粘贴。你问它 "这个测试为什么失败",它只能猜,因为它看不到实际的报错信息。

没有循环的时候,你自己就是那个循环------手动把模型的输出粘贴到终端,把终端的结果粘贴回模型,来来回回,直到任务完成。

Agent Loop 解决的就是这个问题:让模型自己完成这个循环。

核心架构:一张图说清楚

sql 复制代码
+--------+      +-------+      +---------+
|  User  | ---> |  LLM  | ---> |  Tool   |
| prompt |      |       |      | execute |
+--------+      +---+---+      +----+----+
                    ^                |
                    |   tool_result  |
                    +----------------+
                    (循环,直到模型不再调用工具)

整个 Agent 的运转逻辑就这一张图:

markdown 复制代码
1. 用户给一个任务        → 发送给大模型
2. 大模型思考后决定      :要不要调用工具?
3. 如果要调用            → 执行工具,把结果喂回给模型 → 回到第 2 步
4. 如果不调用            → 任务完成,返回最终回复

退出条件只有一个:模型自己决定不再调用工具。

这就是所有 AI Agent 的骨架。Claude Code 是这样,Cursor 是这样,Windsurf 也是这样。不同的只是循环之外叠加的 Harness 机制------工具多少、有无计划系统、能不能多 Agent 协作------但核心循环永远是这一个。

四步拆解:从空白到 Agent

第一步:用户输入变成消息

python 复制代码
messages = [{"role": "user", "content": query}]

Anthropic Messages API 用一个列表管理对话。用户的输入是第一条消息。后面所有的助手回复、工具调用结果,都会追加到这个列表里。

这个列表就是 Agent 的全部记忆。

第二步:把消息和工具定义一起发给 LLM

python 复制代码
response = client.messages.create(
    model=MODEL,
    system=SYSTEM,
    messages=messages,
    tools=TOOLS,
    max_tokens=8000,
)

关键参数是 tools。你告诉模型 "你有一个叫 bash 的工具,可以执行 shell 命令",模型就知道自己有了一双手。

工具定义长这样:

python 复制代码
TOOLS = [{
    "name": "bash",
    "description": "Run a shell command.",
    "input_schema": {
        "type": "object",
        "properties": {"command": {"type": "string"}},
        "required": ["command"],
    },
}]

一个名字,一段描述,一个参数定义。这就是给模型的 "工具说明书"。模型读懂之后,就知道怎么调用这个工具了。

第三步:检查模型要不要调工具

python 复制代码
messages.append({"role": "assistant", "content": response.content})

if response.stop_reason != "tool_use":
    return  # 模型决定不调工具了,任务完成

Anthropic API 返回的 stop_reason 有两种关键值:

  • "tool_use" → 模型想调用工具
  • "end_turn" → 模型觉得说完了

这一个判断就是整个循环的退出条件。模型自己决定什么时候停。

第四步:执行工具,把结果喂回去

python 复制代码
results = []
for block in response.content:
    if block.type == "tool_use":
        output = run_bash(block.input["command"])
        results.append({
            "type": "tool_result",
            "tool_use_id": block.id,
            "content": output,
        })
messages.append({"role": "user", "content": results})

模型说 "我要执行 cat hello.py",你就在本地跑这个命令,把输出结果以 tool_result 的格式追加到消息列表里。然后回到第二步,让模型看到结果后决定下一步。

组装:完整的 Agent Loop

把四步拼在一起,就是整个 Agent:

python 复制代码
def agent_loop(messages: list):
    while True:
        # 发给模型
        response = client.messages.create(
            model=MODEL, system=SYSTEM,
            messages=messages, tools=TOOLS,
            max_tokens=8000,
        )
        # 记录助手回复
        messages.append({"role": "assistant", "content": response.content})

        # 退出条件:模型不再调工具
        if response.stop_reason != "tool_use":
            return

        # 执行工具,收集结果
        results = []
        for block in response.content:
            if block.type == "tool_use":
                output = run_bash(block.input["command"])
                results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": output,
                })
        messages.append({"role": "user", "content": results})

不到 20 行。这就是一个能操作真实世界的 AI Agent。

后面 11 个课程------工具注册、计划系统、子 Agent、上下文压缩、任务持久化、多 Agent 团队------全部都在这个循环之外叠加。循环本身,从第 1 课到第 12 课,一行不改。

实际运行:Agent 是怎么思考的

让我们看一个真实的执行过程。你给 Agent 一个任务:

"创建一个 hello.py,打印 Hello, World!"

Agent 的思考和行动链路:

makefile 复制代码
用户: "创建一个 hello.py,打印 Hello, World!"
  ↓
模型思考: 我需要创建一个文件,用 bash 工具
  ↓
工具调用: bash → echo 'print("Hello, World!")' > hello.py
  ↓
工具结果: (空输出,表示成功)
  ↓
模型思考: 文件创建了,我验证一下
  ↓
工具调用: bash → cat hello.py
  ↓
工具结果: print("Hello, World!")
  ↓
模型思考: 内容正确,任务完成,不需要再调工具了
  ↓
stop_reason = "end_turn"  →  循环退出
  ↓
最终回复: "已创建 hello.py,可以用 python hello.py 运行。"

注意两个关键点:

  1. 模型自己决定要验证 ------没有人告诉它要 cat 文件检查,它自己觉得应该验证。这就是 Agent 的自主性。
  2. 模型自己决定停止------确认文件正确后,它判断任务完成,不再调用工具。循环自然退出。

三个架构决策:为什么这样设计

决策一:为什么只用 Bash 一个工具

Bash 能读文件、写文件、执行程序、管理目录、安装依赖、跑测试、查看日志......几乎能做一切。

任何专门的工具------read_filewrite_filehttp_request------都只是 Bash 已有能力的子集。在第 1 课加更多工具,不会解锁新能力,只会增加模型需要理解的接口数量。

最小可行 Agent:一个工具,一个循环。

这也让一个核心洞见变得显而易见:一个 LLM + 一个 Shell,就已经是一个通用 Agent。后面的课程(s02)会加更多工具,但那是为了效率和安全,不是为了能力。

决策二:为什么没有规划框架

没有 Planner,没有 Task Queue,没有状态机。系统提示词告诉模型如何处理问题,模型根据对话历史自己决定下一步做什么。

这是有意为之的。在这个阶段,加规划层属于过早抽象。 模型的思维链本身就是计划。Agent Loop 只是不断问模型 "下一步做什么",直到模型说 "做完了"。

到第 3 课(TodoWrite),我们才会引入显式的规划系统。但第 1 课证明了:很多任务,隐式的模型推理就够了。

决策三:为什么退出条件这么简单

整个循环只看一个值:stop_reason != "tool_use"

没有超时。没有最大轮次。没有错误计数器。

因为在教学场景下,简单就是正确。生产环境会加安全阈值(超过 N 轮强制停止、检测到危险命令拒绝执行),但核心退出逻辑永远是同一个:模型决定不再调用工具。

这个退出机制的优雅之处在于------你永远不需要预定义任务有几步。 简单任务一步完成,复杂任务十步完成,都是同一个循环。模型自己判断。

安全:最小但必要的防护

即使是教学代码,也不能裸奔。run_bash 函数做了最基本的防护:

python 复制代码
def run_bash(command: str) -> str:
    dangerous = ["rm -rf /", "sudo", "shutdown", "reboot", "> /dev/"]
    if any(d in command for d in dangerous):
        return "Error: Dangerous command blocked"
    try:
        r = subprocess.run(
            command, shell=True, cwd=os.getcwd(),
            capture_output=True, text=True, timeout=120
        )
        out = (r.stdout + r.stderr).strip()
        return out[:50000] if out else "(no output)"
    except subprocess.TimeoutExpired:
        return "Error: Timeout (120s)"

三层防护:

  • 黑名单过滤 :拦截 rm -rf /sudo 等危险命令
  • 超时控制:120 秒没跑完强制终止
  • 输出截断:最多返回 50000 字符,防止上下文爆炸

生产环境需要更完善的沙箱(Docker 容器、文件系统权限隔离),但原则是一样的:让 Agent 能动手,但不能乱来。

五分钟跑起来

bash 复制代码
# 克隆仓库
git clone https://github.com/shareAI-lab/learn-claude-code
cd learn-claude-code

# 安装依赖
pip install -r requirements.txt

# 配置 API Key
cp .env.example .env
# 编辑 .env,填入你的 ANTHROPIC_API_KEY 和 MODEL_ID

# 启动第一课
python agents/s01_agent_loop.py

启动后你会看到一个交互式终端提示符 s01 >>,可以直接输入任务。以下是真实的运行记录:

任务 1:创建文件

perl 复制代码
s01 >> Create a file called hello.py that prints "Hello, World!"
$ cat > hello.py << 'EOF'
print("Hello, World!")
EOF
(no output)
$ python3 hello.py
Hello, World!
`hello.py` has been created and works correctly --- it prints `Hello, World!`.

注意 Agent 不仅创建了文件,还主动运行了一次验证------没有人让它这么做。

任务 2:探索环境

bash 复制代码
s01 >> List all Python files in this directory
$ find . -name "*.py" -type f
./hello.py
./tests/test_agents_smoke.py
./agents/s01_agent_loop.py
...
A total of 21 Python files were found.

任务 3:获取系统信息

css 复制代码
s01 >> What is the current git branch?
$ git branch --show-current
main
The current git branch is main.

一轮调用就结束------Agent 判断信息已经足够,不需要再调工具。

任务 4:多步操作

bash 复制代码
s01 >> Create a directory called test_output and write 3 files in it
$ mkdir -p test_output
(no output)
$ cat > test_output/output1.txt << 'EOF'
This is the first test output file.
EOF
cat > test_output/output2.json << 'EOF'
{"name": "test_output", "file_number": 2, "status": "success"}
EOF
cat > test_output/output3.csv << 'EOF'
id,name,value
1,alpha,100
2,beta,200
EOF
(no output)
$ ls -l test_output/
output1.txt  output2.json  output3.csv
Done! Created the test_output directory with 3 files.

Agent 自主决定了文件格式(txt、json、csv),自主验证了创建结果。你只给了目标,没给步骤。

每一个任务,Agent 都会自主决定执行什么命令、要不要验证结果、什么时候停下来。你不需要告诉它步骤,只需要告诉它目标。

总结:你刚造了什么

组件 之前 之后
Agent 循环 while True + stop_reason
工具 bash(单一工具)
消息管理 累积式消息列表
退出机制 stop_reason != "tool_use"
代码量 0 ~120 行(含安全防护和交互界面)

核心代码不到 20 行,但它已经是一个功能完整的 AI Agent:

  • 感知环境(通过 bash 读取文件、查看状态)
  • 行动(通过 bash 执行命令、创建文件)
  • 自主决策(模型决定下一步、何时停止)
  • 记忆(累积式消息列表保存完整上下文)

这四个能力------感知、行动、决策、记忆------就是 Agent 的定义。

下一课预告

第 1 课只有一个工具 bash。虽然 bash 什么都能做,但让模型每次都拼 shell 命令效率不高,也不够安全。

第 2 课:Tool Use ------ 从 1 个工具扩展到多个。核心模式是一个 dispatch map:工具名映射到处理函数。新增工具只需注册,循环不用碰。

python 复制代码
# 预告:s02 的 dispatch map
TOOL_HANDLERS = {
    "bash": run_bash,
    "read": read_file,
    "write": write_file,
    "edit": edit_file,
}
output = TOOL_HANDLERS[tool_name](**tool_input)

加一个工具,只加一个 handler。循环一行不改。


这是《12课拆解Claude Code架构:从零掌握Agent Harness工程》系列的第 1 课。关注Claw开发者,不错过后续更新。

完整代码和交互式学习平台:github.com/shareAI-lab...

如果这篇文章对你有帮助,欢迎转发给你的技术团队。

系列目录

  • 第1课:用20行Python造出你的第一个AI Agent(本文)
  • 第2课:给Agent加工具 ------ dispatch map模式详解
  • 第3课:TodoWrite ------ 让Agent先想后做:规划系统
  • 第4课:Subagent ------ 拆解大任务,上下文隔离
  • 第5课:按需加载领域知识------Skill机制
  • 第6课:无限对话------上下文压缩三层策略
  • 第7课:任务持久化------文件级DAG任务图
  • 第8课:后台执行------异步任务与通知队列
  • 第9课:Agent Teams------多Agent协作:团队与邮箱系统
  • 第10课:团队协议------状态机驱动的协商
  • 第11课:自治Agent------自组织任务认领
  • 第12课:终极隔离------Worktree并行执行

📌 本文原始链接第1课:用20行Python造出你的第一个AI Agent

🔗 更多 AI Agent 开发实战教程,访问 HuanCode

💻 完整代码仓库:github.com/shareAI-lab...

相关推荐
笨鸟先飞,勤能补拙2 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能3 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂3 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study4 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境4 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境5 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd1235 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy12393102165 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb006 小时前
一个项目带你入门AI应用开发01
python
0566466 小时前
Python康复训练——常用标准库
开发语言·python·学习