为什么你的 AI 代理需要一个 Shell(以及如何安全地为它们提供)

发布: (2026年1月11日 GMT+8 18:45)
13 min read
原文: Dev.to

I’m happy to translate the article for you, but I need the actual text of the article in order to do so. Could you please paste the content you’d like translated (excluding the source link you’ve already provided)? Once I have the text, I’ll translate it into Simplified Chinese while preserving the formatting, markdown, and any code blocks or URLs.

Claude Code — 对代理架构的新视角

Claude Code 改变了我对代理架构的看法。它的表现超越了那些装载了 50 个不同 MCP 服务器和自定义集成的代理,并且其内部实现异常简洁:

  • 没有工具蔓延。
  • 没有占用大量上下文的庞大模式定义。
  • 只有文件系统和 Bash。

AI 社区正开始拼凑出 它为何如此有效 的原因,许多人也在重新审视我们在自己的代理上堆砌的复杂性。

两种“默认”方法

当构建需要处理数据的代理时,我们大多数人会默认使用以下三种模式之一:

  1. Prompt stuffing – 将所有内容塞入上下文窗口并寄望于最佳结果。
  2. Tool libraries – 连接 MCP 服务器,定义自定义工具,为代理提供获取所需信息的方式。
  3. Vector search – 对数据进行嵌入,运行语义相似度检索,祈祷检索结果相关。

这些方法可行,但各有权衡:

ApproachProsCons
Prompt stuffing简单,无需额外基础设施很快触及 token 限制
Vector search在语义相似性方面表现出色在处理结构化数据的精确值时表现不佳
Tool libraries解决能力问题每新增一个工具都需要添加模式定义,增加模型需要推理的选项,并扩大故障的潜在范围

第三选项 – 文件系统 + Bash

为什么它有意义

  • 训练数据 – 大型语言模型在数十亿行代码上进行训练,其中包括无数开发者浏览目录、grep 文件以及在复杂代码库中管理状态的示例。
  • 原生原语 – 像 grepcatfindawk 这样的命令是模型的“原生语言”,不需要额外教它们。

Vercel 团队在重建内部代理时发现了这一点。通过用 仅两样东西——文件系统工具和 Bash 工具——替换大多数自定义工具,他们:

  • 将他们的销售通话摘要代理的成本从 ≈ 每通话 $1.00 降至 ≈ Claude Opus 上的 $0.25
  • 提升了输出质量。

Bash 启用的代理可以做什么

  • 连接任何东西curl API、数据库的 CLI 工具、云服务、Kubernetes 等。
  • 存储并检索自身上下文 – 将发现写入文件,暂停,稍后再回来;文件系统成为工作记忆。
  • 精确检索grep -r "pricing objection" transcripts/ 返回精确匹配,而不是相似度分数。
  • 自然的数据层次结构 – 客户记录、工单历史、CRM 导出可以干净地映射到目录。
  • 完整的可调试性 – 你可以看到每个被读取的文件、执行的命令以及写入的输出。

直觉: 如果一个代理能够在代码库中导航以查找错误,它同样可以以相同方式在你的业务数据中导航。如果它能够运行 shell 命令,它就能与几乎所有你已经在使用的系统交互。

Source:

安全 – 对 Bash 访问进行沙箱化

让 AI 代理拥有无限制的 Bash 访问是令人恐惧的。一次幻觉式的 rm -rf 就可能导致灾难。解决方案是沙箱化

  • 在一个隔离的环境中运行代理的命令,防止其触及生产系统。
  • 将代理能够思考的内容(挂载的目录)与它实际能够执行的操作(沙箱执行器)分离。

架构概览

Agent receives task

Explores filesystem (ls, find)

Searches for relevant content (grep, cat)

Sends context + request to LLM

Returns structured output

Bash 执行在隔离的沙箱中进行,让你在没有风险的前提下拥有本地文件系统操作的能力。

沙箱需求

需求描述
进程隔离命令在受限环境中运行,无法突破到宿主机。WebAssembly 运行时是理想选择,因为它们天生提供内存安全的执行。
目录挂载只暴露代理需要的目录(例如,将 /project 挂载为 /workspace)。其他所有内容在代理视角下根本不存在。
会话持久化对于多步骤工作流,保持配置和状态跨命令持续,而不会泄漏到其他会话。
可见执行路径捕获 stdoutstderr 以及完整的命令历史,以便你能够审计到底发生了什么。

安全模型是深度防御:即使代理生成了意外的命令,沙箱也会限制实际能发生的事情。

关于 MCP(模型上下文协议)的简要说明

如果你一直在关注 AI 工具领域,可能已经听说过 MCP。Anthropic 于 2024 年底发布了它,并迅速成为将代理(agent)连接到外部工具和数据的事实标准。

  • MCP 之前:每一对配对(例如,GitHub ↔ agent、Slack ↔ agent、数据库 ↔ agent)都需要定制集成。
  • MCP 之后:你只需为每个工具构建 一个 MCP 服务器,为每个代理构建 一个 MCP 客户端——把 N × M 的集成问题转化为 N + M 的问题。

TL;DR

  • filesystem + Bash 作为面向代理的通用本地工具集。
  • 对 Bash 执行进行 Sandbox,以确保生产环境安全。
  • 利用 MCP 处理所有剩余的外部工具连接需求。

这种方法可以消除工具杂乱,降低成本,并为您提供透明、易于调试且强大的代理架构。

为什么选择 CLI 工具而非 MCP?

当 MCP 的使用规模扩大时,会出现一个严重问题:工具定义会占用 LLM 的上下文窗口。每个工具都带有描述、参数和返回模式。连接数十个 MCP 服务器、上百个工具,你会在代理甚至开始工作之前就耗尽 token。

Unix 哲学的优势

  • 小巧、模块化、可组合 – CLI 工具接受文本输入,输出文本,并且可以串联使用。
  • 经受考验gitgrepcurljq 已经在生产环境中运行了数十年。
  • 稳定且文档完善 – 它们的接口很少改变。

LLM 在训练期间已经见过这些工具数十亿次。它们已经掌握了语法、标志、常见模式和错误信息。这不是“上下文学习”;而是深层、内化的知识。

MCP 与 CLI 的对比

方面MCPCLI
学习曲线代理必须从提供的模式(插件式能力)中学习每个工具。代理已经了解该工具(原生理解)。
可组合性并非真正可管道化;将输出链入输入相当笨拙。简单的管道:grep "error" logs.txt | wc -l – 模型知道如何构造它们。
Token 效率高 – 每个工具定义都会增加 token。低 – 只需要命令文本。
安全性需要为每个服务器定制沙箱。需要对任意 Shell 访问进行沙箱(真正的挑战)。

MCP 在分发和可发现性方面表现出色,尤其适用于非技术用户或高度领域特定的工作流。但就原始能力而言——让代理真正能够执行任务——CLI 工具更胜一筹:它们更省 token、可组合性更强,并且与模型已经擅长的操作相契合。

核心问题:安全的 CLI 访问

允许代理执行任意 shell 命令是极其危险的。我们需要一个沙箱,它能够:

  1. 在 macOS、Linux 和 Windows 上 可移植
  2. 提供 强隔离(WASM 或微型 VM)。
  3. 易于在命令行使用

介绍 Bashlet

Bashlet 是一个开源工具,为 AI 代理提供沙箱化的 Bash 访问。
它根据平台和安全需求,支持多种隔离后端。

后端特性
Wasmer (WASM)跨平台、轻量级沙箱。可在 macOS、Linux、Windows 上运行。启动约 50 ms。
Firecracker (microVM)完整的 Linux VM 隔离,提供硬件级安全。仅限 Linux,需 KVM。启动约 125 ms。

默认情况下,Bashlet 会自动选择最佳可用后端。

  • Linux + KVM → 使用 Firecracker VM。
  • 其他所有平台 → 使用 Wasmer WASM 沙箱。

基本工作流

# 1️⃣ Create a session with a mounted directory
bashlet create --name demo --mount ./src:/workspace

# 2️⃣ Run commands in isolation
bashlet run demo "ls /workspace"
bashlet run demo "grep -r 'TODO' /workspace"

# 3️⃣ Terminate when done
bashlet terminate demo

一次性命令(无会话管理)

bashlet exec --mount ./src:/workspace "ls /workspace"

预设:停止重复设置

许多工作流需要相同的挂载、环境变量和设置命令。只需在 ~/.config/bashlet/config.toml 中定义一次:

[presets.kubectl]
mounts = [
  ["/usr/local/bin/kubectl", "/usr/local/bin/kubectl", true],
  ["~/.kube", "/home/.kube", true]
]
env_vars = [["KUBECONFIG", "/home/.kube/config"]]
setup_commands = ["kubectl version --client"]

[presets.nodejs]
mounts = [["~/.npm", "/home/.npm", false]]
env_vars = [["NODE_ENV", "development"]]
workdir = "/app"

使用预设

# Create a session with a preset
bashlet create --name k8s-env --preset kubectl

# One‑shot command with a preset
bashlet exec --preset kubectl "kubectl get pods"

# Auto‑create session if missing, apply preset, then run
bashlet run dev -C --preset nodejs "npm install"

后端特定预设

想让工作负载始终在 Firecracker 中运行吗?在预设中添加 backend(以及可选的自定义 rootfs_image):

[presets.dev-vm]
backend = "firecracker"
rootfs_image = "~/.bashlet/images/dev.ext4"
env_vars = [["EDITOR", "vim"]]

对 rootfs 的更改会在会话之间持久保留——只需安装一次软件包,即可永久复用。

安装

Bashlet 可在 GitHub 上获取。只需运行一个脚本(包括 Wasmer 和 Linux 上的 Firecracker),约 30 秒即可完成安装:

curl -fsSL https://bashlet.dev/install.sh | sh

更大的图景

随着大型语言模型在编码方面的提升,基于 filesystem primitives 构建的代理也会自动变得更好。通过利用模型训练时使用的工具——而不是与需要持续维护的自定义工具作斗争——我们可以保持代理架构 simple, fast, and secure

Give your agents the tools they were trained on.

Back to Blog

相关文章

阅读更多 »