Local Agent

Shell 与沙箱

配置 Agent 的本地命令执行、沙箱和审批流程

Shell 与沙箱

Agent 使用 @downcity/shell 执行本地命令、管理沙箱运行环境、处理交互式审批。

安装

pnpm add @downcity/shell

Shell

Shell 类管理命令执行和交互式审批运行时。应用层审批归属具体 Session,通过 Session API 处理。

最小示例

import { Shell } from "@downcity/shell";
import { Agent } from "@downcity/agent";

const shell = new Shell();

const agent = new Agent({
  id: "demo",
  path: process.cwd(),
  shell,
});

通过 Agent 装配时不需要传入路径;Agent 会把自己的项目根目录和运行时上下文配置给 Shell。独立使用 Shell 时可以传入 root_path

方法

  • shell.dispose() — 释放 shell 资源

审批请求会在 session.subscribe((mutation) => {}) 中表现为 approval-required Tool Part。应用层从 mutation.part.approval 读取完整请求,再使用 session.resolve_approval(...) 提交用户决定;重连后可通过 session.approvals() 恢复 pending 请求。不要直接调用 Shell Runtime 的内部审批方法。

模型工具

传给 Agent 的 Shell 会提供:

工具用途
shell_exec执行一次性非交互命令
shell_session管理长运行或交互式 PTY 命令
grep底层直接使用 ripgrep 搜索项目文件内容
find使用 POSIX glob 模式发现项目文件
read按行分页读取文本,并把图片注入模型输入
write创建 UTF-8 文件,或在 overwrite: true 时原子覆盖
edit使用唯一、非重叠的 old_text 精确编辑一个文件

read 默认最多返回 500 行,单次最多 2,000 行或 256KB。结果中的 truncatednext_offset 用于继续读取。write 单次最多写入 1MB,并自动创建父目录。

对于 PNG、JPEG、GIF、WebP 和 BMP 文件,read 会返回图片元数据和 data URL,Agent 再把该 data URL 作为临时 user image part 注入下一个模型 step。其他二进制文件只返回元数据。

edit 一次最多接受 10 个修改,所有修改都基于原始文件匹配并且全部成功后才写入。可以把 read.sha256 传给 edit.expected_sha256,防止覆盖并发修改。

grep 不经过 shell,直接执行 rg --json。它默认使用不区分大小写的字面量搜索;设为 literal: false 可使用正则表达式,设为 case_sensitive: true 可区分大小写,glob 用于限制候选文件。

find 接受 POSIX glob pattern,包含 dotfile、遵守 .gitignore,且不会跟随符号链接。两个搜索工具默认最多返回 200 项,max_results 最大为 2,000。

所有文件和搜索工具都固定限制在项目根目录内,并拒绝符号链接逃逸。它们不会申请 unrestricted 权限。

沙箱

Shell 命令默认使用 safe sandbox。沙箱后端会根据宿主平台自动选择:

  • macos-seatbelt — macOS 沙箱
  • linux-bubblewrap — Linux 沙箱
  • unrestricted-host — 不启用沙箱

SDK 内部的沙箱运行器负责 shell 子进程创建、平台后端调用和一次性命令执行。通常不需要直接使用。

Env

shell_execshell_session 使用当前 Session step 已生效的 Agent env 构造子进程环境。宿主可以通过 agent.setEnv(next)agent.patchEnv(patch) 动态更新 configured env;已有 Session 会在下一个 step 检查点提交该修改,当前 provider 请求及其工具调用继续使用原 env。如果当前 Session turn 没有后续 step,则在下一个 Session turn 开始时提交。

safe sandbox 只会导出两类环境变量:

  • shell 运行所需的最小基础变量,例如 PATHLANGSHELL
  • 当前 Agent env 中显式存在的 key

这意味着 .env、构造参数 env 和运行时 agent.patchEnv() 写入的 key 可以被 sandbox 内命令读取,但 SDK 不会把完整宿主 process.env 暴露给 sandbox。

agent.patchEnv({
  GITHUB_TOKEN: token,
});

await agent.tools.shell_exec.execute(
  {
    cmd: 'printf "%s\\n" "$GITHUB_TOKEN"',
    sandbox: "safe",
  },
  { toolCallId: "example" },
);

ConfigResolver

SandboxConfigResolver 根据 Agent 项目根目录生成固定的 safe sandbox 边界。

SandboxPreflight 执行沙箱前置检查,验证沙箱环境是否就绪。