让我们一步步构建 Claude Code 的运行框架

@akshay_pachaar
英语6天前 · 2026年7月15日
202K
841
122
29
1.9K

TL;DR

这是一份关于使用 CrewAI 构建编程 Agent 运行框架的综合教程。内容涵盖核心执行循环、层级委派、沙箱执行以及持久化记忆,旨在实现 Claude Code 级别的可靠性。

我们将涵盖构建编码框架的所有内容:Agent 循环、规划、子 Agent、沙盒、记忆和检查点,逐步构建。

如果你曾经尝试构建自己的编码 Agent,你就会知道会发生什么。你把模型连接到文件工具和 Shell 上,把它指向一个真正的代码库,然后它往往在十几个工具调用之内就崩溃了。

它读取错误的文件,在半途中丢失目标,并用不再需要的输出填满自己的上下文。

然后,同样的任务经由 Claude Code 处理,却能干净利落地完成。一个简单的结论是,Anthropic 只是拥有更好的模型,而这个结论忽略了真正发生工作的环节。

区别在于框架。框架是包裹在模型周围的普通代码,它处理规划、工具执行、记忆和安全,而模型只决定下一步动作。

这是完全搭建好的框架画出来的样子:

Akshay 🚀 - inline image

GIF

这张图看起来很复杂,但它可以分解为四个部分:

  • 记忆 为模型提供工作上下文以及跨会话学到的事实。
  • 技能 编码了 Agent 应该如何运作,即它遵循的程序、约束和启发式规则。
  • 协议 将 Agent 连接到用户、工具和其他 Agent。
  • 框架核心 通过子 Agent 编排、沙盒、评估器、审批循环、可观测性和上下文压缩,将所有内容整合在一起。

Anthropic 将这种划分描述为大脑和双手。模型是选择每个动作的大脑,而框架是执行这些动作并保持运行在正轨上的双手。

所以,你的 Agent 和 Claude Code 之间的差距不在于模型,而在于模型周围的机制。

Claude Code 是目前生产环境中能力最强的框架之一,它由该插图中数量少得惊人的层构建而成。为了了解你需要自己构建多少这样的机制,我在 CrewAI(一个用于编排 Agent 的开源框架)中重建了它。

比我预想的更多功能映射到了内置特性上,而其余部分正是真正的工程所在。

让我们逐层构建,从核心循环开始,然后叠加规划、子 Agent、沙盒和记忆。在每一步,我们都会标记出框架的边界,以及你的工作从何开始。

Claude Code 框架的工作原理

Claude Code 的核心是一个简单的 Agent 循环。你向它发送一条消息,模型决定下一步做什么,然后它要么直接响应,要么请求一个工具。如果它请求工具,工具就会运行,结果会返回到对话中,然后模型再次决定。

这个循环会一直重复,直到模型返回一个最终答案,且不再进行任何工具调用。

在这个循环内部,模型会读取文件、编辑代码、运行 Shell 命令和执行测试。这些并不是独立的模式,它们只是同一个循环中的不同工具调用。

然而,仅靠循环本身不足以构建一个可靠的编码 Agent。Claude Code 在其周围添加了规划、文件工具、子 Agent、记忆以及权限和沙盒系统。这些层并不取代循环,而是使其足够安全可靠,以用于实际工作。

Akshay 🚀 - inline image

这就是我们将要重建的架构,首先是核心循环,然后在其上叠加每一层,并将每一层映射到处理它的 CrewAI 特性。

核心 Agent 循环

循环会重复执行相同的序列,直到任务完成:

  1. 要求模型执行任务。
  2. 模型直接响应,或请求一个或多个工具。
  3. 如果请求了工具,则运行它们并将结果返回给模型。
  4. 使用更新后的对话重复第 2 步。
  5. 当模型响应而未请求任何工具时,任务完成。
Akshay 🚀 - inline image
python
1while True:
2 reply = model(messages, tools)
3 calls = [b for b in reply if b.type == "tool_use"]
4 if not calls: # 纯文本,无工具调用:任务完成
5 return reply.text
6 messages += [reply, run_all(calls)]

每个工具调用完成一个步骤,为模型提供新信息,并反馈到下一个决策中。一个简单的问题可能在一个迭代内完成,而修复一个复杂的 bug 或重构一个大型代码库可能需要数十次迭代,模型才能获得足够的信息来生成最终答案。

一旦你创建了 Agent,CrewAI 就会自动提供这个执行循环。你不需要自己实现 while 循环,只需定义 Agent 并为其分配任务。

构建第一个 Agent

让我们创建一个简单的 Bug 修复 Agent。

python
1from crewai import LLM, Agent, Crew, Task
2
3bug_fixer = Agent(
4 role="Bug Fixer",
5 goal="Find and describe the fix for the reported bug in the codebase.",
6 backstory="You read directories and files to build an accurate picture of the code.",
7 llm="claude-sonnet-4-6",
8)
9
10task = Task(
11 description="Find the fix for {objective}.",
12 expected_output="A short description of the fix and which file it belongs in.",
13)
14
15result = Crew(agents=[bug_fixer], tasks=[task]).kickoff(
16 inputs={"objective": "the overdraft bug in account.py"}
17)

这里需要理解三个概念:

  • Agent 定义了谁来做工作,通过其角色、目标、LLM 和工具。
  • Task 描述了任务分配。
  • Crew 将 Agent 和任务结合在一起。调用 kickoff() 会运行上述相同的执行循环,无论底层模型是 Anthropic、OpenAI、Google 还是其他。

为 Agent 提供工具

工具让一个只能生成文本的模型能够真正作用于代码库。它们可以读取文件、写入文件、运行 Shell 命令以及调用外部 API。

CrewAI 原生提供了文件系统工具:

  • FileReadTool 读取文件。
  • DirectoryReadTool 列出目录。
  • FileWriterTool 写入文件。
python
1from crewai_tools import DirectoryReadTool, FileReadTool, FileWriterTool
2
3read_file = FileReadTool()
4write_file = FileWriterTool()
5list_dir = DirectoryReadTool()
6
7filesystem_tools = [read_file, write_file, list_dir]

这些工具也可以充当外部记忆。Agent 不是将大型搜索结果保留在模型的上下文窗口中,而是可以将其写入文件,只保留文件名,并在需要时再读回来。

这保持了上下文窗口更小,模型更专注,Anthropic 称之为上下文工程。

Akshay 🚀 - inline image

内置工具只覆盖常见的工作流程。对于更具体的情况,你可以使用 @tool 装饰器将 Python 函数暴露为工具。

文档字符串充当了使用说明书,告诉模型该工具的作用、何时使用以及期望的输入是什么。

python
1from crewai.tools import tool
2import subprocess
3
4@tool("run_tests")
5def run_tests(path: str = "tests/") -> str:
6 """Run the pytest suite at the given path and return the result."""
7 result = subprocess.run(
8 ["pytest", path, "-q"], capture_output=True, text=True, timeout=120
9 )
10 output = result.stdout + result.stderr
11 return output[-4000:] if len(output) > 4000 else output

规划长时间运行的任务

随着任务变得越来越复杂,一个简单的执行循环开始丢失原始目标。在足够多的工具调用、文件读取和中间结果之后,上下文被填满,目标被后续的一切所淹没。

这种缓慢的退化被称为上下文腐烂。

规划直接解决了这个问题。Agent 在执行任何工作之前会构建一个逐步计划,并在整个执行过程中将该计划保留在上下文中。

计划本身并不执行工作,它是一张路线图,使模型与原始目标保持连接,这与 Claude Code 的待办事项清单功能相同。

Akshay 🚀 - inline image

CrewAI 通过在 Crew 级别设置 planning=True 来添加此功能。它在执行前生成一个计划,并在任务进行过程中保持其可用性。

python
1from crewai import Crew, LLM
2
3crew = Crew(
4 agents=self.agents,
5 tasks=self.tasks,
6 planning=True,
7 planning_llm=LLM(model="gpt-4o-mini"),
8)

注意:默认情况下,CrewAI 使用 gpt-4o-mini 进行规划,你可以为此步骤替换任何你喜欢的 LLM。

单个 Agent 也可以使用 reasoning=True 来推理自己的工作:

python
1from crewai import Agent
2
3bug_fixer = Agent(
4 role="Bug Fixer",
5 goal="Find and describe the fix for the reported bug in the codebase.",
6 backstory="You read directories and files to build an accurate picture of the code.",
7 tools=[FileReadTool()],
8 reasoning=True,
9 max_reasoning_attempts=3 # 可选:设置最大推理尝试次数
10)

规划和推理解决不同的问题。规划为整个任务构建一个高层路线图,而推理则让一个 Agent 在行动前有时间思考自己的方法。

当启用推理时,Agent 会:

  1. 反思任务并起草一个执行计划。
  2. 评估计划是否就绪。
  3. 如果需要,完善计划,直到满意或达到 max_reasoning_attempts。
  4. 在执行前将最终确定的推理计划注入到任务中。
Akshay 🚀 - inline image

它们一起使 Agent 在长时间运行的任务中保持锚定,并减少偏离原始目标的漂移。

使用子 Agent 进行委派

规划让 Agent 保持专注,但并不能减少模型必须处理的信息量。在一个大型代码库上,即使是规划良好的任务也可能超出单个上下文窗口。

找到一个 bug 可能需要读取数十个文件,而主 Agent 不需要记住所有这些文件。

子 Agent 通过委派解决了这个问题。主 Agent 将特定任务交给一个辅助 Agent,该辅助 Agent 在自己的上下文中工作,并返回一个简短摘要。主 Agent 看到的是结论,而不是中间步骤。

Akshay 🚀 - inline image

CrewAI 通过层级工作流支持这一点,其中管理 Agent 将任务委派给专门的 Agent,并组合它们的结果。

在我们之前的设置中,一个 Bug 修复 Agent 完成了所有繁重的工作。让我们将工作拆分给一个管理者和三个专家:

  • Codebase Explorer 探索代码并映射仓库。
  • Software Engineer 实施请求的更改。
  • Test Runner 在沙盒中运行测试并报告通过或失败。
  • Engineering Lead 监督这三个专家。
Akshay 🚀 - inline image
python
1from crewai import Crew, Agent, Task, Process
2
3explorer = Agent(
4 role="Codebase Explorer",
5 goal="Map the repository and surface the files relevant to the task.",
6 backstory="You read directories and files to build a picture of the code.",
7 tools=[read_file, list_dir],
8 llm=llm,
9) # 其他两个专家 Agent 类似
10
11manager = Agent(
12 role="Engineering Lead",
13 goal="Break the request into steps and delegate each to the right specialist.",
14 backstory="You decide who does what, review tests, finish once change is done.",
15 llm=llm,
16 allow_delegation=True,
17)
18
19crew = Crew(
20 agents=[explorer, coder, tester],
21 tasks=[task],
22 manager_agent=manager,
23 process=Process.hierarchical,
24)

需要注意的一点是,allow_delegation 默认是禁用的,因此必须在管理者上显式启用。

沙盒化:保护 Agent 执行

一个具有 Shell 访问权限的 Agent 可以运行破坏性命令,而告诉模型不要做某事并不是一种安全措施。

真正的保护来自两个层面:

  1. 权限系统,要求对敏感操作进行审批。
  2. 沙盒,隔离执行环境,这样即使已批准的命令也无法触及宿主机。

Anthropic 使用了相同的方法。将代码执行移到沙盒中,可以减少用户需要审批操作的频率,同时仍然保护宿主系统。

Akshay 🚀 - inline image

CrewAI 中的沙盒化

在沙盒内而不是在宿主机上执行代码,应用了第二个层面。在这种设置中,代码在 E2B 内部运行,它会为每个会话启动一个全新的虚拟机,并在会话结束后销毁它。

Shell 命令和 Python 完全在这个隔离的环境中运行。

Akshay 🚀 - inline image
python
1from crewai_tools import E2BExecTool, E2BPythonTool
2sandbox_tools = [E2BExecTool(), E2BPythonTool()] # 运行测试 / 运行代码

人机协同审批

在 Task 上设置 human_input=True 会在 Crew 生成答案后暂停。你审查输出,然后批准它或将其发回进行另一次迭代。

当执行到该任务时,CrewAI 会通过标准输入等待你的反馈。

python
1from crewai import Task
2
3task = Task(
4 description=(
5 "In the working directory ./workspace, {objective}. "
6 "Explore the code first, make the change, then run the tests and report."
7 ),
8 expected_output="A summary of the files changed and the final test output.",
9 human_input=True,
10)

如果你的 Crew 在 Web 应用或聊天界面(而不是终端)后面运行,CrewAI 基于 Webhook 的人机协同系统会处理相同的审查步骤。

记忆和检查点

默认情况下,Agent 在运行结束后会忘记一切。如果你第二天回来修复同一个项目中的另一个 bug,它会从零开始。

两种机制允许 Agent 跨运行携带信息,每种机制服务于不同的目的:

  • 检查点 在运行期间保存 Agent 的状态,这样它可以在中断后恢复,或者从同一点沿不同路径继续。
  • 持久记忆 跨独立对话存储事实,包括项目偏好,例如“在完成前始终格式化最终代码”。
Akshay 🚀 - inline image

CrewAI 中的记忆

CrewAI 提供了一个统一的 Memory 接口,而不是单独的短期记忆、长期记忆、实体记忆和外部记忆类型。保存时,它使用 LLM 来识别重要细节、组织它们,并使它们以后可检索。

在 Crew 上设置 memory=True 会为其提供跨运行记忆。在每个任务之后,CrewAI 会从输出中提取有用的事实并存储它们,在未来的运行中,它会检索相关记忆并将它们添加到任务提示中。

Akshay 🚀 - inline image
python
1from crewai import Crew
2
3crew = Crew(
4 agents=[explorer, coder, tester],
5 tasks=[task],
6 memory=True,
7)

Crew 中的所有 Agent 共享其记忆,除非某个 Agent 被赋予了自己的记忆。

CrewAI 中的检查点

检查点是 Agent 进度的快照,包括其配置、任务状态、记忆、中间结果、输入和执行历史。

默认情况下,CrewAI 在每个任务完成时创建一个检查点,允许工作流在中断时从该点恢复。

检查点可以存在于两个内置存储之一:

  • JsonProvider 将每个检查点保存为单独的 JSON 文件,便于手动读取和检查。
  • SqliteProvider 将所有检查点存储在单个 SQLite 数据库中,在频繁检查点和更大工作负载下表现更好。
Akshay 🚀 - inline image
python
1from crewai import Crew
2
3crew = Crew(
4 agents=[explorer, coder, tester],
5 tasks=[task],
6 checkpoint=True,
7)

Crew、Flow 和 Agent 都接受一个 checkpoint 参数,子元素继承父元素的值,除非它们自行设置。

整合在一起

以下是完整的框架在一个任务上的应用,包含了执行循环、工具、规划、子 Agent、沙盒化和记忆:

python
1from crewai import Agent, Crew, LLM, Process, Task
2from crewai.tools import tool
3from crewai_tools import (DirectoryReadTool, FileReadTool, FileWriterTool,
4E2BExecTool, E2BPythonTool)
5
6llm = LLM(model="anthropic/claude-sonnet-4.6")
7
8list_dir = DirectoryReadTool(directory="./workspace")
9filesystem_tools = [FileReadTool(), FileWriterTool(), list_dir]
10sandbox_tools = [exec_tool, E2BPythonTool()]
11
12@tool("run_tests")
13def run_tests(path: str = "tests/") -> str:
14 """Sync ./workspace into the sandbox, then run pytest there."""
15 return E2BExecTool().run(command=sync_and_test_command(path))
16
17explorer = Agent(role="Codebase Explorer", goal="Map repo, surface relevant files.",
18 tools=[read_file, list_dir], llm=llm)
19coder = Agent(role="Software Engineer", goal="Implement requested change.",
20 tools=filesystem_tools, reasoning=True, llm=llm)
21tester = Agent(role="Test Runner", goal="Run tests in sandbox, report pass/fail.",
22 tools=sandbox_tools + [read_file] + [run_tests], llm=llm)
23manager = Agent(role="Engineering Lead", goal="Delegate steps, finish once tests pass.",
24 allow_delegation=True, llm=llm)
25
26task = Task(
27 description="In ./workspace, {objective}. Explore, edit, test, report.",
28 expected_output="Summary of changes and test output.", human_input=True,
29)
30crew = Crew(
31 agents=[explorer, coder, tester], tasks=[task],
32 manager_agent=manager, process=Process.hierarchical,
33 planning=True, memory=True, checkpoint=True,
34)
35result = crew.kickoff(inputs={"objective": "fix failing tests in account.py"})

Agent 框架在成功可以自动检查时最容易评估。测试套件为 Agent 提供了一个具体的目标,因此它可以规划、编辑、测试并重复,直到所有测试通过。

因此,这是针对一个小型代码库进行测试的,一个 BankAccount 类,包含两个真实的 bug 和五个测试,其中三个测试失败。规则是只修复实现,不修改测试。

这反映了 Anthropic 内部评估编码 Agent 的方式。一个已发布的例子是,Claude 针对一个大型失败测试套件重建了 claude.ai 界面的克隆。

在这里,框架将项目从 3 个失败、2 个通过,变成了全部 5 个通过,并且只修改实现的规则关闭了编辑或删除失败测试这一捷径。

Akshay 🚀 - inline image

仍然需要你来做的工作

系统的某些部分不是框架为你构建的:

  • 提示词。 每个 Agent 的行为来自其角色、目标和背景故事。让它们正确工作需要测试和迭代,没有配置标志可以替代。
  • 执行环境。 沙盒,无论是 E2B 还是自管理的虚拟机,都需要设置并连接起来。
  • 工具选择。 每个 Agent 获得哪些工具,以及哪个 Agent 应该拥有什么访问权限,是框架不会替你做出的设计决策。

框架本身也有成本。规划、子 Agent 和循环都会增加 API 调用,因此一个复杂的 Agent 设置最终可能比一个单次模型调用就能直接解决的任务更昂贵。

还有一个值得注意的长期限制。随着模型改进,一些脚手架变得不再必要,因为今天构建到框架中的某些内容,是对今天模型限制的变通办法,而不是永久需求。

Anthropic 最初使用上下文重置来防止 Claude Sonnet 4.5 过早结束任务,而随着能力更强的 Claude Opus 4.5 的出现,这些就不再需要了。

Akshay 🚀 - inline image

总结

这就是全部发现。编码 Agent 的能力主要存在于框架中,而编排框架为你提供的框架组件比你预想的要多。

循环、规划、委派、沙盒化和记忆都以配置项的形式出现,而提示词、执行环境和工具选择则仍然由你负责。

如果你想在自己的代码库上运行这个,CrewAI 的文档涵盖了这里使用的所有特性,并且该框架是完全开源的。

查看 CrewAI 文档 →

在这里找到所有代码 →

感谢阅读!

干杯! :)

一键保存

使用 YouMind AI 深度阅读爆款文章

保存原文、追问细节、总结观点,并在一个 AI 工作空间里把爆款文章沉淀成可复用笔记。

了解 YouMind
写给创作者

把你的 Markdown 变成干净的 𝕏 文章

图片上传、表格、代码块,往 𝕏 上手动重排太痛苦。YouMind 把整篇 Markdown 一键转成干净、可直接发布的 𝕏 文章草稿。

试试 Markdown 转 𝕏

更多可拆解样本

近期爆款文章

探索更多爆款文章