> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 构建代码优先的AI智能体
- URL: https://www.hubwiz.com/blog/build-code-first-ai-agents/
- Published: 2026-03-12T12:16:14.000Z
- Updated: 2026-03-12T12:16:14.000Z
- Description: 为什么你的 LLM 应该编写代码，而不是调用工具
- Author: admin
- Tags: AGENT, #Import 2026-10-14 14:41

大多数 AI 智能体框架今天使用工具调用：LLM 输出结构化 JSON，描述调用哪个函数以及使用什么参数。你的应用程序解析此 JSON 并执行函数。

这种方法有效，但它违背了自然的趋势。LLM 是在数十亿行代码上训练的。工具调用是一种返工。

本指南解释了为什么代码生成对于智能体通常是一种更好的架构、何时使用它以及如何安全地实现它。

## 1、使用工具调用的核心问题

工具调用将每个行动视为单独的对话回合。模式看起来像这样：

![工具调用模式](https://www.hubwiz.com/blog/content/images/2026/03/1-blIhWmjd6sFpJdDVt_w3bA-1.png)

1. LLM 接收上下文和可用工具
2. LLM 输出 JSON：`{"tool": "create_event", "args": {"title": "Meeting", "date": "2024-12-19"}}`
3. 你的应用程序解析并执行
4. 结果返回到上下文中
5. LLM 决定下一步
6. 重复

对于多步骤任务，这会产生复合成本。每个步骤都需要对整个对话历史进行一次完整的推理传递。Hugging Face 关于 GAIA 基准的研究发现，使用代码操作的智能体需要比基于 JSON 的工具调用[少 30% 的步骤](https://huggingface.co/blog/smolagents?ref=hubwiz.com)，直接转换为少 30% 的 token 和更低的成本。

差距随着复杂性的扩大而扩大。Cloudflare 的 Code Mode 演示显示，在简单的单步骤任务上节省了 32% 的 token，但在复杂的多步骤任务上节省了 81%（创建 31 个日历事件）。步骤越多，对话性开销累积得越多。

## 2、为什么代码是更好的操作格式

Hugging Face smolagents 库[清楚地阐明了这一点](https://huggingface.co/blog/smolagents?ref=hubwiz.com)：

> *"我们专门制作了我们的编程语言，以擅长表达由计算机执行的操作。如果 JSON 片段是更好的方式，这个包本应以 JSON 片段编写。"*

代码相比工具调用提供了三个结构性优势：

### 2.1 控制流

工具调用是单拍的。代码具有循环、条件和错误处理。

**工具调用方法**（31 个单独的 LLM 回合）：

```
{"tool": "create_event", "args": {"title": "Tech Meetup Day 1", "date": "2026-01-01"}}
{"tool": "create_event", "args": {"title": "Tech Meetup Day 2", "date": "2026-01-02"}}
// ... 29 个更多的回合

```

**代码生成方法**（1 个 LLM 回合）：

```
const topics = ["AI Fundamentals", "MCP Deep Dive", "Data Pipelines", ...];
for (let day = 1; day <= 31; day++) {
  const date = new Date(2026, 0, day);
  await createEvent({
    title: `Tech Meetup: ${topics[day % topics.length]}`,
    date: date.toISOString()
  });
}

```

### 2.2 运行时访问

工具调用参数在生成时是静态的，在生成时定义。代码可以访问运行时信息。

这就是为什么 Cloudflare 的 Code Mode 演示使用工具调用失败但使用代码生成成功。提示是"为今晚创建一个事件"。工具调用智能体产生了一个日期。代码生成智能体调用了 `new Date()` 并获得了实际当前日期。

### 2.3 组合

代码自然地组合。函数调用函数。变量存储中间结果。工具调用强迫 LLM 通过对话在每一步手动编排每一步。

```
# Code 可以定义可重用逻辑

def process_user(user_id):
    profile = fetch_profile(user_id)
    if profile.needs_update:
        enriched = enrich_with_external_data(profile)
        save_profile(enriched)
    return profile

# And组合它

for user_id in active_users:
    process_user(user_id)

```

使用工具调用时，这些操作中的每一个都需要单独的 LLM 回合，并且模型必须在其上下文窗口中跨回合跟踪状态。

## 3、关键要点

在深入实施之前，这里是核心原则：

**工具调用最佳用于** 简单、单步操作

- 高安全环境，需要严格约束
- 当每个步骤的可观察性至关重要时
- 使用工具调用：\*\* 多步骤工作流，需要迭代或条件逻辑
- 当需要运行时信息时
- 大规模的高成本应用

**代码生成最佳用于** 多步骤工作流

- 需要迭代或条件逻辑的任务
- 当需要运行时信息时

在实施之前，这里是核心原则：

**工具调用最佳用于** 简单、单步操作（单个 API 调用）

- 高安全环境，需要严格约束
- 当每个步骤的可观察性至关重要时

**代码生成最佳用于** 多步骤工作流

- 需要迭代或条件逻辑的任务
- 当需要运行时信息时
- 大规模的高成本应用

**使用工具调用时：**

- 简单、原子操作（单个 API 调用）\*
- 高安全环境，需要严格约束
- 当每个步骤的可观察性至关重要时\*
- 使用工具调用：\*\* 多步骤工作流，需要迭代或条件逻辑\*
- 当需要运行时信息时\*
- 成本敏感应用，需要规模

**使用代码生成时：**

- 多步骤工作流\*
- 需要迭代或条件逻辑的任务
- 当需要运行时信息时\*

## 4、实施架构

代码优先的智能体具有三个组件：

```
┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│   LLM       │────▶│   Sandbox    │────▶│   APIs/     │
│ (generates  │     │   (executes    │     │  code)       │     │             │
│  code)      │     │  code)       │     │             │
└─────────────┘     └──────────────┘     └─────────────┘

```

1. **LLM** 基于任务和可用 API 生成代码
2. **沙箱** 在隔离环境中执行该代码
3. **API/服务** 由执行的代码调用

关键部分是沙箱。你正在执行 LLM 生成的代码，这本质上是冒险的。沙箱提供隔离。

### 4.1 沙箱选项

存在几种生产就绪的选项：

> E2B（基于云）

[E2B](https://e2b.dev/?ref=hubwiz.com) 提供在 Firecracker 微型 VM 上构建的云沙箱。每个沙箱在大约 150 毫秒内启动，具有硬件级隔离。

```
import { Sandbox } from '@e2b/code-interpreter';

const sandbox = await Sandbox.create();
const result = await sandbox.runCode(`
  import pandas as pd
  df = pd.read_csv('data.csv')
  df.describe()
`);

```

关键特征：

- \~150 毫秒冷启动
- 完整 Linux 环境
- 默认网络隔离
- Python 和 Node.js 支持

> Cloudflare Workers（基于边缘）

[Cloudflare 的 Dynamic Worker Loader](https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/?ref=hubwiz.com) 在 V8 隔离环境中运行代码。比容器更轻，具有毫秒启动时间。

```
// Parent worker 加载并运行生成的代码
const worker = await env.WORKER_LOADER.get(executionId, {
  code: generatedTypeScript,
  globalOutbound: null // 网络完全禁用
});

const result = await worker.fetch(request);

```

关键特征：

- 毫秒冷启动
- V8 隔离隔离（不是容器）
- 网络可以完全禁用
- 目前仅 TypeScript/JavaScript
- 目前处于封闭测试版

> 本地执行（开发）

对于开发和测试，[smolagents](https://huggingface.co/docs/smolagents/en/tutorials/secure%5Fcode%5Fexecution?ref=hubwiz.com) 提供受限的 Python 解释器：

```
from smolagents import CodeAgent, LocalPythonExecutor

executor = LocalPythonExecutor(
    allowed_imports=["pandas", "numpy"],  # 白名单导入
    max_execution_time=30
)

agent = CodeAgent(tools=[], executor=executor)

```

这使用 AST 解析来限制操作。不像真正的隔离那样安全，但对开发有用。

### 4.2 安全模型

关键洞察：代码生成并不意味着安全性降低。它意味着不同的安全模型。

**工具调用安全性**：信任外部端点，每个端点都有自己的身份验证、权限和攻击面。

**代码生成安全性**：信任 1 沙箱化环境，以及定义明确的约束。

必要的沙箱约束：

| 约束目的                                        | 实现                                                                                      | 网络隔离                                           |
| ------------------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------- |
| 防止数据渗漏，阻止出站请求                               | 在 Code Mode 中，沙箱默认阻止所有网络访问。生成的代码只能通过受控接口与预定义 API 交互。这消除了整个类别的漏洞（凭据泄露、SSRF、数据渗漏）。 文件系统限制 | 仅读或作用域写入访问                                     |
| 沙箱限制文件系统访问。读取文件、创建临时文件、访问受控目录。 资源限制         | CPU、内存、执行时间上限                                                                           | 沙箱强制执行资源限制。这可以防止无限循环或资源耗尽。 导入限制                |
| 沙箱限制可以导入的库。这防止代码导入不受信任的包或使用危险函数。 无 shell 访问 | 防止任意命令执行                                                                                | 沙箱不支持 bash 或 shell 命令。这可以防止任意命令执行或 shell 注入攻击。 |

Cloudflare 的方法是指令性的：在 Code Mode 中，沙箱默认阻止所有网络访问。生成的代码只能通过受控接口与预定义 API 交互。这消除了整个类别的漏洞（凭据泄露、SSRF、数据渗漏）。

### 4.3 实用实现模式

这里是一个最小化的代码优先智能体模式：

```
import openai
from e2b_code_interpreter import Sandbox

SYSTEM_PROMPT = """你是一个代码生成智能体。
给定一个任务，编写 Python 代码来完成它。

你可以访问这些函数：
- fetch_user(user_id) -> dict
- send_email(to, subject, body) -> bool
- query_database(sql) -> list

编写使用这些函数的代码。仅输出代码，不要解释。"""

def run_agent(task: str) -> str:
    # 1. 生成代码
    response = openai.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": task}
        ]
    )
    generated_code = response.choices[0].message.content
    # 2. 在沙箱中执行
    with Sandbox() as sandbox:
        # 注入可用的函数
        sandbox.run_code(FUNCTION_DEFINITIONS)
        # 运行生成的代码
        result = sandbox.run_code(generated_code)
    return result.text

# 用法
result = run_agent("Send 本周内登录的所有用户摘要电子邮件")

```

LLM 生成一次。沙箱执行。

## 5、何时不使用代码生成

代码生成并不总是正确的选择：

**简单的单步操作**：如果你只是调用一个 API，工具调用更简单且足够。

**需要人工审查的高风险操作**：当每个操作都需要人工审查时，单个工具调用的可观察性很有价值。某些合规框架明确要求对每个操作的审计跟踪。工具调用自然地提供了这一点。

**严格受监管的环境**：一些合规框架要求明确的每项操作的审计跟踪。工具调用自然地提供了这一点。

**当沙箱基础设施不可用时**：代码生成需要执行基础设施。如果你无法运行 E2B、Cloudflare Workers 或类似的工具调用，那么它对简单操作有效。

**混合方法**：保持工具调用以进行简单操作，为复杂工作流使用代码生成。测量 token 使用量、延迟和可靠性。

**比较**：测量 token 使用量、延迟和可靠性。

## 6、结束语

行业正在向代码优先的架构移动：

- **OpenAI 的高级数据分析**（前身为 Code Interpreter）生成并执行 Python
- **GitHub Copilot Workspace** 生成代码以完成任务
- **Anthropic 的 Claude** 擅长代码生成并用于像 Devin 这样的编码智能体
- **Hugging Face smolagents** 默认为 JSON 操作选择代码操作

基础设施正在成熟。E2B 提供云沙箱。Cloudflare 正在为 AI 生成的代码构建边缘执行。代码优先智能体所需的执行层正在现在构建中。

工具调用是必要的桥梁。它证明了 LLM 可以与外部系统交互。但 LLM 首先是编码者。最有效和最有能力的智能体将让它们在自己的本机语言中工作。

---

原文链接: [Building Code-First AI Agents](https://kotrotsos.medium.com/building-code-first-ai-agents-bf652be6af3c?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处