Skip to main content

Restricted file-operation workspace for AI agents (Python bindings over the Rust core)

Project description

Agent Workspace (ws)

基于 Rust 的受限文件操作 CLI,供 Agent 在指定工作目录内安全地读写文件。所有路径均相对于配置的工作区解析,无法越界访问宿主机其他路径。

特性

  • 双后端:本地文件(file)或 MySQL(mysql),通过 config.yaml 切换
  • 路径隔离(file 后端):读写操作限制在 workspace_dir 内,含符号链接逃逸检测
  • 元数据:file 后端使用 *.meta.yaml sidecar;mysql 后端将元数据存入数据库
  • 并发安全:file 后端使用 advisory 文件锁;mysql 后端使用 InnoDB 行锁
  • 按行操作:支持按行区间读取或局部替换写入
  • 内容 Hook(可选):config.yaml 可配置 read/write 外部命令,在逻辑内容与物理存储之间转换
  • 本地 MCP 服务ws mcp 通过 stdio 暴露 JSON-RPC(MCP 协议)工具,供 MCP 客户端调用工作区读写列删操作

安装

需要 Rust 工具链。

# 克隆或进入项目目录后
cd rust && cargo build --release

# 安装到 ~/.cargo/bin
cargo install --path rust

构建产物位于 rust/target/release/ws。安装后可直接在终端运行 ws

初始化

使用 init 命令创建新的工作区(生成 config.yaml,file 后端还会创建 data/ 目录):

# 在当前目录初始化(默认 file 后端)
ws init

# 在指定目录初始化(不存在则自动创建)
ws init ./my-agent-workspace
ws init /path/to/workspace

# 使用 MySQL 后端(生成 mysql 配置模板并自动建库建表)
ws init --backend mysql
ws init ./my-agent-workspace --backend mysql

--backend mysql 会写入 MySQL 连接配置模板,并尝试连接数据库、创建库(若不存在)及 workspace_files 表。请编辑 config.yaml 中的 hostuserpassworddatabase 后再使用其他命令。

初始化完成后,进入该目录即可使用其他命令。若目录下已存在 config.yaml,会报错以避免覆盖。

配置

破坏性变更:旧版顶层 workspace_dir / metadata_suffix 已移除。请改用 backend 块,见下方示例。

在项目根目录(或任意启动目录)放置 config.yaml

File 后端(默认)

backend:
  type: file
  workspace_dir: ./data         # 相对 config 文件所在目录解析
  metadata_suffix: ".meta.yaml" # 可省略(默认值)

启动时会校验 workspace_dir 存在且可写。

MySQL 后端

backend:
  type: mysql
  host: localhost
  port: 3306                    # 可省略(默认 3306)
  user: ws_user
  password: change_me
  database: agent_workspace

连接时会自动确保数据库和 workspace_files 表存在。元数据(创建者、描述、时间戳、SHA256)与文件内容存储在同一张表中,不再使用 sidecar 文件。

内容 Hook(可选)

backend 块之外,可声明顶层 hooks,为当前配置文件绑定一套全局 read / write 外部命令。磁盘/数据库中存的是物理内容;CLI、MCP、Python 默认看到逻辑内容(经 read hook 转换后)。

backend:
  type: file
  workspace_dir: ./data

hooks:
  read:
    command: ["python", "hooks/decode.py"]
    timeout_ms: 10000   # 可选,默认 30000
  write:
    command: ["python", "hooks/encode.py"]

命令协议

约定
command 非空 argv 数组(不经 shell)
输入 完整内容经 stdin 传入(UTF-8)
输出 stdout 全文作为结果(不 trim)
工作目录 config.yaml 所在目录
环境变量 WS_HOOK=read|writeWS_PATH=<相对路径>
失败 非零退出或超时 → 操作失败,不部分写入

未配置 hooks 时行为与无 hook 版本完全一致。仅配置单侧 hook 时启动会打印 warning。

跳过 Hookread / write 支持 --no-hooks(MCP/Python:skip_hooks: true),直接读写物理存储内容。调试或手工修复时,应对 read/write 一致使用该选项,避免破坏存储格式。

加载顺序

init 外,其余命令均通过配置文件加载后端。可按以下优先级指定配置文件:

  1. 命令行 --config /path/to/config.yaml
  2. 环境变量 AGENT_WORKSPACE_CONFIG
  3. 当前工作目录下的 config.yaml

init 会生成新的 config.yaml,不使用上述加载逻辑;传入的 --config 对其无效。

路径规则

所有命令的路径参数均为工作区相对路径,例如 docs/foo.txt

路径会按 POSIX 语义归一化,且不能逃出工作区根目录:

输入 归一化结果
docs/foo.txt docs/foo.txt
/docs/foo.txt docs/foo.txt
../docs/foo.txt docs/foo.txt
foo/../bar bar
../etc/passwd etc/passwd(访问的是工作区内的 etc/passwd,不是系统 /etc/passwd

元数据文件(如 foo.txt.meta.yaml)在 read / remove 中视为不存在,不会泄露其内容。

命令

所有需加载配置的命令均支持全局 --config 选项,例如:

ws --config /path/to/config.yaml read docs/foo.txt
ws read docs/foo.txt --config /path/to/config.yaml

两种写法等价;未指定时按上文「加载顺序」解析。

init — 初始化工作区

ws init
ws init ./my-agent-workspace
ws init --backend mysql
ws init ./my-agent-workspace --backend mysql
参数 说明
[path] 可选,目标目录;省略则在当前工作目录初始化
--backend 后端类型:file(默认)或 mysql

read — 读取文件

ws read docs/foo.txt
ws read docs/foo.txt --human
ws read docs/foo.txt --ranges 1-10,20-30
选项 说明
--human 首行输出路径,每行前加行号(如 12 | content
--ranges 1-indexed 行区间,逗号分隔;human 模式下仍显示真实行号
--no-hooks 跳过配置的 read hook,返回物理存储内容

默认输出文件原文(raw)。

write — 写入文件

--content--created-by--desc 均为必选参数:

ws write docs/foo.txt --content "hello\n" --created-by agent-x --desc "需求草稿"

按行区间局部替换(删除 START..END 行,在该位置插入新内容):

ws write docs/foo.txt --ranges 2-5 --content "替换内容\n" --created-by agent-x --desc "局部更新"
选项 说明
--content 写入内容(必选)
--created-by 写入元数据,首次创建时记录(必选)
--desc 文件描述(必选)
--ranges START-END 1-indexed,含端点;省略则整文件覆盖
--no-hooks 跳过配置的 read/write hook,直接读写物理存储内容

更新已有文件时,元数据中的 created_by / created_at 会保留,其余字段更新。

list — 列出文件

ws list                  # 列出工作区全部文件
ws list docs             # 只列出 docs/ 下文件
ws list --json
ws list docs --json

默认输出人类可读表格;--json 输出结构化 JSON(含 scopefile_counttotal_size_bytesfiles)。

remove — 删除文件

ws remove docs/foo.txt

同时删除数据文件及对应元数据 sidecar。

mcp — 本地 MCP 服务

Model Context Protocol 服务运行,通过 stdio 收发换行分隔的 JSON-RPC 2.0 消息。MCP 客户端将 ws mcp 作为子进程启动后,即可调用工作区工具。

ws mcp
ws mcp --config /path/to/config.yaml

进程读取 stdin 直到 EOF,所有协议输出写入 stdout(因此该模式下命令本身不向 stdout 打印其他内容)。后端与作用域规则由配置文件决定。

支持的方法:initializetools/listtools/callping,以及忽略的 notifications/*

暴露的工具(每次调用可选 user_id / session_id 进行作用域隔离):

工具 必选参数 可选参数 说明
read path rangesskip_hooks 读取文件,可按 1-indexed 行区间过滤
write pathcontentcreated_bydesc ranges(单个 START-END)、skip_hooks 写入或局部替换
list path 列出文件,返回 JSON 报告
remove path 删除文件及元数据

工具执行失败(如路径越界、未找到)按 MCP 约定返回 isError: true 的结果而非 JSON-RPC 协议错误;仅调用格式本身非法(缺少工具名、未知工具)才返回协议错误。

示例(手动喂入请求):

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05"}}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"write","arguments":{"path":"a.txt","content":"hello\n","created_by":"agent","desc":"demo"}}}' \
  | ws mcp

在 MCP 客户端中的典型配置(以可执行路径启动):

{
  "mcpServers": {
    "agent-workspace": {
      "command": "/path/to/ws",
      "args": ["mcp", "--config", "/path/to/config.yaml"]
    }
  }
}

也可通过环境变量 AGENT_WORKSPACE_CONFIG 指定配置(省略 --config 时生效):

{
  "mcpServers": {
    "agent-workspace": {
      "command": "/path/to/ws",
      "args": ["mcp"],
      "env": { "AGENT_WORKSPACE_CONFIG": "/path/to/config.yaml" }
    }
  }
}

启动目录、--configAGENT_WORKSPACE_CONFIG 需指向有效的 config.yaml,否则服务无法加载后端。

元数据

每个数据文件对应一个 sidecar,命名规则:foo.txtfoo.txt.meta.yaml

示例:

relative_path: docs/foo.txt
created_by: agent-x
desc: 需求文档草稿
created_at: 2026-06-13T13:00:00+08:00
updated_at: 2026-06-13T13:35:00+08:00
size_bytes: 1024
sha256: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

退出码

含义
0 成功
1 一般错误
2 路径非法 / 越界
3 未找到(含元数据保护触发)
4 锁冲突

错误信息输出到 stderr。

并发说明

File 后端

文件锁为进程级 advisory lock,仅对同样使用本工具的进程有效。同一文件的并发 write 会串行化;write 在独占锁下同时更新数据文件和元数据 sidecar,保证一致性。

MySQL 后端

write / remove 在事务内对目标行执行 SELECT ... FOR UPDATE,依赖 InnoDB 行锁串行化并发写入。锁等待超时或死锁时返回退出码 4LockConflict),与 file 后端的锁冲突行为一致。read 为普通 SELECT,不加行锁。

开发

cd rust
cargo test          # 单元测试 + 集成测试(不含需 MySQL 的 ignored 测试)
cargo run -- list   # 开发模式运行

Python 绑定(在 python/ 目录):

cd python
uv sync
uv run maturin develop

项目结构

仓库按语言拆分,Rust 核心与 Python 绑定分目录维护:

rust/               Rust crate(CLI、库、MCP、PyO3 绑定)
├── src/
│   ├── main.rs       仅 fn main(),调用 cli::run()
│   ├── lib.rs        模块声明
│   ├── error.rs      错误类型与退出码
│   ├── lock.rs       file 后端的 advisory 文件锁
│   ├── cli.rs        Cli/Commands 定义、命令分发、按作用域打开后端
│   ├── scoping.rs    SessionScope(user/session 作用域解析)
│   ├── ranges.rs     行区间解析、写入替换、过滤
│   ├── metadata.rs   FileMetadata、sidecar 读写、SHA256/时间戳
│   ├── paths/        路径领域
│   │   ├── normalize.rs     工作区相对路径归一化
│   │   ├── resolve.rs       路径解析与越界校验
│   │   ├── metadata_name.rs sidecar 命名与识别
│   │   └── scope_prefix.rs  list 作用域前缀匹配
│   ├── config/       配置领域
│   │   ├── mod.rs       Config / BackendConfig
│   │   ├── raw.rs       反序列化 DTO 与默认值
│   │   ├── load.rs      配置发现、加载、校验
│   │   └── templates.rs init 写出的配置模板
│   ├── storage/      存储领域
│   │   ├── mod.rs       WorkspaceBackend trait + ListReport
│   │   ├── handle.rs    BackendHandle 枚举与工厂
│   │   ├── file.rs      file 后端
│   │   ├── scoped.rs    带作用域的 mysql 后端包装
│   │   └── mysql/       mysql 后端(connection 连接层 + mod CRUD 实现)
│   ├── mcp/          本地 MCP 服务
│   │   ├── mod.rs       模块入口
│   │   ├── protocol.rs  JSON-RPC 2.0 消息类型与错误码
│   │   ├── server.rs    stdio 同步循环与方法分发
│   │   └── tools.rs     工具定义与执行(映射到 WorkspaceBackend)
│   └── commands/     各子命令实现(init/read/write/list/remove)
└── tests/            集成测试

python/             Python 包与构建配置
├── pyproject.toml     maturin/uv(`manifest-path` → ../rust/)
├── uv.lock            uv 依赖锁(可选)
└── agent_workspace/
    ├── __init__.py      公开 API 重导出
    └── py.typed         PEP 561 类型标记

MySQL 集成测试(可选)

需要本地或 CI 中可访问的 MySQL 实例。设置 MYSQL_TEST_URL 后运行 ignored 测试:

export MYSQL_TEST_URL='mysql://user:pass@localhost:3306/agent_workspace_test'
cd rust && cargo test --test mysql_integration -- --ignored

未设置 MYSQL_TEST_URL 时,cargo test 会跳过这些测试,不影响常规 CI。

快速上手

# 新建工作区
ws init ./my-workspace
cd my-workspace

# 写入、读取、列出、删除
ws write docs/readme.md --content "# 标题\n" --created-by me --desc "示例文件"
ws read docs/readme.md --human
ws list
ws remove docs/readme.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_workspace-2026.6.16a1.tar.gz (63.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

agent_workspace-2026.6.16a1-cp39-abi3-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.9+Windows x86-64

agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

agent_workspace-2026.6.16a1-cp39-abi3-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

agent_workspace-2026.6.16a1-cp39-abi3-macosx_10_12_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file agent_workspace-2026.6.16a1.tar.gz.

File metadata

  • Download URL: agent_workspace-2026.6.16a1.tar.gz
  • Upload date:
  • Size: 63.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for agent_workspace-2026.6.16a1.tar.gz
Algorithm Hash digest
SHA256 d0389d6ec86814eef78c120d123d755e94dd44a23e4f035dfd30df4df74753ab
MD5 b8489705cea18413dcec3e827066009b
BLAKE2b-256 cd03d8b0317b6ce034f50bcb38ec5200f7e69976709c79c1e0f033c5be30a936

See more details on using hashes here.

File details

Details for the file agent_workspace-2026.6.16a1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: agent_workspace-2026.6.16a1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for agent_workspace-2026.6.16a1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 b7b5e9c2e198546300fc2e564ca284cc7846793bb50863468a5667b772139ff0
MD5 04aee18152d4c24b70b12aab805d08f0
BLAKE2b-256 cb8dff4e63e348a814c5a9d7083b4b37cf5155410f2b1836b613fe1e6f38fc40

See more details on using hashes here.

File details

Details for the file agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a1b3864b07211a668a7adbddb5c7ee28686f7a3806114c5afb0a047613d715af
MD5 ff155006bb027142437e1852b758c8c4
BLAKE2b-256 3b43c8f64c9a0b5f2a2ac1fec7a5b827a9ac719eee767e7a7df299af8ea69b39

See more details on using hashes here.

File details

Details for the file agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for agent_workspace-2026.6.16a1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5dce5cfc405a59a2a480733721193dba9eb882b2ab41afc36777af4a286f00d6
MD5 66b7db798f4253d2bce53145457b2d70
BLAKE2b-256 a2691faa8a96120bd7da3ef80d6090ff66df8023e8b084eeb345e31b821e5bd2

See more details on using hashes here.

File details

Details for the file agent_workspace-2026.6.16a1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: agent_workspace-2026.6.16a1-cp39-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.9+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for agent_workspace-2026.6.16a1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 65d6ed56ff5c702576527876da57abb7ec1284ad1b7fd21c9085fec113c2f6c6
MD5 43a334a9a91b619e320d4e08ca55c956
BLAKE2b-256 3f314e605bb67cb4ae8dba2614da9881acc9316000d0fd0b8eb9aa272832c106

See more details on using hashes here.

File details

Details for the file agent_workspace-2026.6.16a1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: agent_workspace-2026.6.16a1-cp39-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.9+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for agent_workspace-2026.6.16a1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8a0a8c6df73be7af6e9dad0c3b83ea9312764fa6cfceb5fa3d4f8fca3d1a6c07
MD5 7e71d636e6570230b06ee29ef031b6f7
BLAKE2b-256 fa19804e47e11ff85a96f748fec8a2bdd2c647044e71fe3a5e9e8eb19d837066

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page