Note

如何设计一个安全的 SiYuan API Agent Skill

复盘 siyuan-api skill 的设计:为什么坚持本地端点、接口白名单、受限 SQL,以及安全边界仍然遗漏了什么。

目录
目录

2026 年 3 月,我开始把 SiYuan 的本地 API 整理成一个可以被不同智能体复用的 skill。项目后来独立发布为 xybio/skill-siyuan-api

它不是一个新的笔记客户端,也不包含代理程序。它是一组面向智能体的操作说明、安全约束、示例和经过筛选的 API 参考。

我想解决的问题

SiYuan 中已经积累了大量项目记录、科研笔记和数据表。如果智能体只能操作界面,批量检索和结构化整理会很低效;如果直接开放整个文件系统或所有 API,风险又太大。

这个 skill 因此只解决一个窄问题:

让智能体在用户明确授权的任务内,通过本地 SiYuan API 操作文档、块、资源和数据库,同时把网络访问、命令执行与广泛文件访问排除在外。

第一层边界:只连接本地服务

skill 默认只允许访问:

  • 127.0.0.1
  • localhost
  • 用户明确确认过的局域网地址

它不能借助 SiYuan 转发请求到第三方网络。API Token 通过环境变量提供,不写入示例、仓库或日志。

这个设计不能阻止同一用户账户下的恶意进程读取环境,但至少避免了把凭据直接硬编码进 skill、脚本和公开仓库。

第二层边界:使用接口白名单

Skill 维护一份经过筛选的 safe-api.md,集中覆盖日常笔记管理所需的接口族:

  • 笔记本和文档树;
  • 文档块;
  • Attribute View 数据库;
  • 资源上传;
  • Markdown 导出;
  • 受限 SQL;
  • SiYuan 工作空间内的少量文件操作。

以下能力被明确排除:

  • 网络代理;
  • 外部命令式转换;
  • 间接执行;
  • 与笔记管理无关的系统管理。

白名单的价值不在于证明其中所有操作都“无风险”,而在于缩小智能体可以调用的能力集合,让审查范围保持可控。

第三层边界:优先结构化 API

当文档 API、块 API 和原始文件读取都能完成任务时,skill 优先使用前两者。

原因很直接:

  • 结构化 API 更接近用户看到的文档模型;
  • 不需要理解 SiYuan 的内部存储细节;
  • 误操作更容易限定在具体文档或块;
  • 操作结果可以通过相同接口重新读取并验证。

原始文件接口只用于明确属于 SiYuan 工作空间的内容和资源,不承担一般文件浏览功能。

SQL 为什么只允许小规模只读查询

SQL 很适合发现文档和检查元数据,例如按关键词找到候选块。但它同时绕过了部分上层语义和保护。

因此 skill 的默认规则是:

  • 优先使用 SELECT
  • 设置较小的 LIMIT
  • 不执行广泛修改;
  • 有文档或块 API 时,不使用 SQL 代替。

Attribute View 数据库则使用 /api/av/* 接口。更新单元格前先读取字段和行,使用实际 itemID 定位目标,再重新读取验证结果。

从接口安全到内容安全

接口权限控制解决“能够访问什么”,内容检查解决“哪些信息可以进入日志、模型上下文和发布流程”。两者需要同时生效:

工具安全控制“能访问哪里、能执行什么”;内容安全还需要判断“读到了什么、允许输出什么”。

完整的迁移流程应加入内容级检查:

  1. 在导出前限定笔记本和文档范围。
  2. 对 token、私钥、账号、内部地址和身份信息做模式检测。
  3. 命中高风险内容时,只报告文档名称和风险类型,不输出原值。
  4. 默认排除配置笔记、合同、联系人和进行中的合作项目。
  5. 在发布前再次扫描生成的 Markdown 和 Git diff。

为什么选择 instruction-only

这个 skill 不包含安装脚本、二进制或代理服务。好处是:

  • 审查对象主要是文字规则和示例;
  • 不引入额外运行时依赖;
  • 可以在支持 SKILL.md 的不同智能体框架间迁移;
  • 使用者能够直接看到允许和禁止的能力。

代价是它依赖智能体正确遵守说明,也需要不同框架自行提供 HTTP 调用能力和凭据环境。

当前适用范围

这个 skill 适合:

  • 只读盘点笔记本和文档;
  • 导出指定文档为 Markdown;
  • 创建和更新明确指定的笔记;
  • 在小范围内检索块;
  • 操作现有 Attribute View 的少量字段。

它不适合成为通用网络代理、系统自动化入口或无限制数据库管理工具。保持边界狭窄,是这个项目最重要的设计选择。

建议阅读

讨论

评论使用 GitHub Discussions。首次加载需要访问 GitHub。