第二篇:Agent Loop ------ 一切从那个 while 循环开始
"One loop & Bash is all you need." ------ 一个工具 + 一个循环 = 一个 Agent。
先讲个恐怖故事
想象一下这个场景。
你是个顶级程序员,但有个诡异的规定:你不允许自己碰键盘。你要写代码,得把想做的事情口述给一个实习生,由他来打字。他打完字,把结果念给你听。
你:"帮我看看那个 bug 在哪行。"
实习生敲了几下键盘,然后:"报错在第 42 行。"
你:"好的,把第 42 行改成 return result。"
实习生改了,然后:"改好了。"
你:"跑一下测试。"
实习生跑完:"测试过了。"
你:"行了,提交吧。"
实习生:"好的,提交了。"
这不是项目管理的 horror story,这是没有循环的 LLM 。每次你想让模型干点啥,你得手动把它的输出 copy-paste 回去。你就是那个实习生。
10 行代码解决的事
这个 repo 的 s01 干了什么?其实就是一句话:让模型自己把工具调用的结果送回去。
看这 10 行核心逻辑:
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
看懂了吗?
这里的关键不是 API 调用------API 调用谁都会写。关键是那个 while True。
- 模型回答,附带工具调用 → 追加到 messages
- 执行工具 → 结果追加到 messages
- 再次调用 API → 模型看到工具结果
- 重复,直到模型的
stop_reason不再是"tool_use"
那个退出条件是全部精华所在:
python
if response.stop_reason != "tool_use":
return
模型说"我没要调用工具" → 循环结束。模型说"我要再跑个命令" → 循环继续。模型决定何时停止,Harness 决定何时继续。
一条命令的旅程
让我们用一个具体的例子,看看当你说"帮我统计一下这个目录的代码行数"时,s01 里面发生了什么。
你输入:
python
query = "帮我统计一下这个目录的代码行数"
第 1 轮: messages 变成了 [{"role": "user", "content": "帮我统计一下这个目录的代码行数"}]
模型思考后决定调用 bash:
json
{
"name": "bash",
"input": {"command": "find . -name '*.py' | xargs wc -l"}
}
s01 执行命令:
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)"
第 2 轮: 模型不需要再调工具了,直接回复:"这个目录下有 7245 行 Python 代码。"
stop_reason 不是 "tool_use" → 循环结束。
为什么 s01 只有一个 bash 工具?
python
TOOLS = [{
"name": "bash",
"description": "Run a shell command.",
"input_schema": {
"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"],
},
}]
就一个。Bash。没了。
这就是作者说的 "One loop & Bash is all you need" 。Bash 是万能工具------你可以用 cat 读文件,用 echo 写文件,用 sed 编辑文件,用 curl 请求网络。
Agent Loop 的通用性
| 场景 | 工具集 | Harness |
|---|---|---|
| 编程 Agent | bash, read, write, edit | IDE + 终端 |
| 数据 Agent | SQL, python, viz | 数据库 + Notebook |
| 运维 Agent | kubectl, ssh, curl | K8s + 监控 |
| 客服 Agent | search, ticket, email | 知识库 + CRM |
工具可以换,循环不用改。
s01 的边界
- 没有多工具 ------ 只有 bash
- 没有规划能力 ------ 做着做着就迷失方向
- 上下文会爆炸 ------ messages 列表无限膨胀
- 没有权限层级 ------ dangerous list 形同虚设
- 没有持久化 ------ 关掉程序,一切归零
每一个问题,就是一个后面的 Session。
但所有这一切,都建立在这个不到 100 行的 Agent Loop 之上。
回头来看
python
while True:
response = call_llm(messages, tools)
messages.append(response)
if response.stop_reason != "tool_use":
break
results = execute_tools(response)
messages.append(results)
12 行 Python,定义了 AI Agent 最基本的架构。循环本身不需要改变。你只需要给模型更好的工具、更干净的记忆、更多的能力。然后------get out of the way。