local-skills

Load local SKILL.md files and run controlled command-capable agents in self-hosted n8n workflows

Documentation

n8n-nodes-local-skills

面向自托管 n8n 的社区节点:从管理员指定的本地目录发现、加载、校验并应用 SKILL.md,也可以把 Skill 作为本地 Agent 的系统能力,通过模型规划、命令调用和结果反馈完成任务。

项目不下载远程 Skill,也不会自动执行 Skill 文件本身。只有 Local Skill Agent 处于 Execute Commands 模式、管理员显式开启命令能力,并且命令同时出现在全局与 Skill 白名单时,才会启动子进程。

功能

  • List Skills:递归发现技能目录,并输出名称、版本、路径和校验状态。
  • Load Skill:读取一个 SKILL.md,可同时加载 references/ 下的文本资料。
  • Validate Skill:检查文档结构、内容警告和可选 SHA-256 内容哈希。
  • Apply Skill:将输入数据和节点变量填入 {{variable}},输出可直接交给模型的指令上下文。
  • Local Skill Agent:运行 OpenAI 兼容模型的 Agent 循环,根据 Skill 受控调用本地命令,并输出完整执行轨迹。
  • 限制目录深度、单文件大小和引用文件总大小。
  • 拒绝绝对路径、目录穿越和逃逸出技能根目录的符号链接。

环境要求

  • 自托管 n8n
  • Node.js 22.22 或更高版本(开发和构建)
  • 一个由 n8n 进程可读的本地 Skills 目录

n8n Cloud 无法挂载用户本地目录,因此不适合这个节点。

开发安装

npm install
export N8N_SKILLS_ROOT=/absolute/path/to/skills
npm run dev

构建后,也可以把该包安装到 n8n 的自定义节点目录:

npm run build
npm pack
cd ~/.n8n/nodes
npm install /absolute/path/to/n8n-nodes-local-skills-0.2.0.tgz

重启 n8n 后,在节点选择器中可以搜索 Local Skills 和 Local Skill Agent。

Skills 目录结构

/srv/n8n/skills/
  video-director/
    SKILL.md
    references/
      shot-rules.md
  copywriter/
    SKILL.md

SKILL.md 示例:

---
name: Video Director
description: 将故事拆成可生成的视频镜头
version: 1.0.0
inputs:
  story:
    type: text
    required: true
    description: 原始故事
  duration:
    type: number
    default: 30
---

请把下面的故事拆成连续镜头:

{{story}}

总时长约 {{duration}} 秒。输出严格 JSON。

当前只读取 references/ 中的 .md、.txt、.json、.yaml 和 .yml 文件。其他文件和符号链接会被忽略。

Apply Skill 输出

节点保留原始输入字段,并增加:

{
  "skillContext": {
    "skill": {
      "name": "Video Director",
      "version": "1.0.0",
      "relativePath": "video-director",
      "contentHash": "..."
    },
    "instruction": "渲染变量后的完整指令",
    "variables": {},
    "references": [],
    "warnings": []
  }
}

在后续 AI 节点中可使用表达式:

{{ $json.skillContext.instruction }}

如果模型还需要参考资料,可把 skillContext.references 序列化后放入模型上下文。推荐先用普通 Code/Set 节点筛选必要资料,避免无关内容占用 token。

推荐工作流

flowchart LR
  A[Webhook / Form] --> B[Local Skills: Apply Skill]
  B --> C[AI Agent / LLM Chain]
  C --> D[Structured Output Parser]
  D --> E[后续业务节点]

Variables 会覆盖同名的输入字段。因此可让工作流数据提供动态值,只在节点配置中固定模型角色、输出格式等少量参数。

Local Skill Agent

这个节点提供类似本地代码 Agent 的基础闭环:

  1. 加载并渲染用户选择的 Skill。
  2. 将 Skill 指令、references 和任务交给 OpenAI 兼容模型。
  3. 模型通过 execute_command 工具请求命令。
  4. 节点校验命令与工作区后执行,将 stdout、stderr 和退出码回传模型。
  5. 重复以上过程,直到模型给出最终答案或达到最大步数。

它不会模拟终端字符串,也不会使用 shell。模型必须分别给出可执行文件名与参数数组,因此 &&、管道、重定向和命令替换不会生效。

需要在 Skill Frontmatter 中声明命令:

tools:
  commands:
    - rg
    - git

最终可用命令是 Skill 声明和管理员环境变量的交集。仅在 Skill 中写入命令不会获得权限。

在 n8n 中创建 Local Skill Agent API 凭证,填写 OpenAI 兼容服务的 Base URL 和 API Key。执行模式要求模型服务兼容 Chat Completions 的 tools / tool_calls 协议;Plan Only 模式不要求模型调用工具。Claude 模型可以通过支持 OpenAI 协议转换的网关接入,当前版本尚未直接实现 Anthropic Messages API。

推荐把自动化拆为“规划—审批—执行”两条路径:

flowchart LR
  A[任务输入] --> B[Local Skill Agent: Plan Only]
  B --> C[人工审批 / 策略检查]
  C --> D[Local Skill Agent: Execute Commands]
  D --> E[保存执行轨迹与结果]

执行输出位于 agent.answer,完成状态位于 agent.completed,审计轨迹位于 agent.trace。轨迹包括模型步骤、token 用量、命令、参数、相对工作目录、退出码、耗时、outputTruncated 状态和截断后的 stdout/stderr。被策略拒绝的调用也会记录错误并返回模型,使其可以修正参数。

Local Media Preview

Local Media Preview 把 Skill 或命令在工作区生成的图片、音频和视频转换为规范的 n8n Binary 输出。节点执行后,在 Output → Binary → data 中即可查看媒体;图片可直接预览,音频和视频的打开或播放方式取决于当前 n8n 与浏览器版本。

推荐让生成媒体的上游节点返回相对于 N8N_LOCAL_SKILLS_WORKSPACE_ROOT 的路径,例如:

{
  "mediaPath": "outputs/chapter-01.mp4"
}

然后连接 Local Media Preview,保持默认的 File Path 表达式 {{ $json.mediaPath }}。节点会根据扩展名设置 MIME 类型,也可以手动覆盖。支持常见的 PNG、JPEG、GIF、WebP、SVG、MP3、WAV、M4A、OGG、MP4、WebM、MOV 和 MKV 文件。

该节点只允许读取工作区内的相对路径,并通过真实路径检查阻止 .. 和符号链接逃逸。它生成的是 n8n 原生 Binary 数据,不会修改 n8n 编辑器前端,因此媒体不会直接嵌入工作流画布上的节点卡片。

Docker

将 Skills 目录只读挂载,并给每个 n8n 主进程和 worker 配置相同路径:

services:
  n8n:
    image: n8nio/n8n:latest
    environment:
      N8N_SKILLS_ROOT: /skills
      N8N_LOCAL_SKILLS_COMMANDS_ENABLED: "true"
      N8N_LOCAL_SKILLS_ALLOWED_COMMANDS: rg,git
      N8N_LOCAL_SKILLS_WORKSPACE_ROOT: /workspace
      N8N_LOCAL_SKILLS_MAX_COMMAND_TIMEOUT_MS: "30000"
      N8N_LOCAL_SKILLS_MAX_COMMAND_OUTPUT_BYTES: "65536"
    volumes:
      - ./skills:/skills:ro
      - ./workspace:/workspace
      - n8n_data:/home/node/.n8n

社区节点包仍需安装进镜像或持久化的 n8n 节点目录。队列模式下,每个实际执行任务的 worker 都必须安装同一版本的节点包,挂载同一版本的 Skills 目录,并拥有对应工作区。命令在实际执行任务的 n8n 容器或 worker 中运行,不会自动进入 Docker 宿主机。

生产建议

  • 用只读挂载管理 Skills,修改后通过发布流程整体替换。
  • 在节点中填写 Expected SHA-256 锁定内容;哈希包含 SKILL.md 和本次选择加载的引用文件。
  • 生产工作流启用 Strict Mode,缺少必填变量或存在未解析占位符时立即失败。
  • 只向 Skills 目录授予 n8n 服务账号读取权限,不要挂载用户主目录、密钥目录或源码仓库根目录。
  • Skill 内容仍属于提示词输入。下游模型节点应继续使用结构化输出、工具白名单和权限隔离,不能把 Skill 当成可信可执行代码。
  • 命令白名单不是操作系统沙箱。 即使不使用 shell,某些解释器、包管理器或 Git 子命令仍可能启动其他进程或访问网络。生产环境应在独立、低权限、无宿主机密钥的容器或 worker 中运行,并只开放真正需要的窄命令集。
  • 不建议将 sh、bash、zsh、node、python、npm、npx 等通用解释器直接加入白名单;它们会显著削弱参数和命令限制。
  • 工作区参数拒绝绝对路径和 .. 路径,但真正的文件系统边界仍应由容器挂载、只读卷、Linux 用户权限和网络策略提供。

开发命令

npm run dev
npm run lint
npm test
npm run build

项目骨架遵循 n8n 官方社区节点工具链。发布前请在 package.json 中补充真实的 repository 地址,并按 n8n 社区节点要求完成 npm 包信息与验证。

License

MIT

Discussion