在技能中使用脚本#

如何在技能中运行命令并捆绑可执行脚本。

Skill 可以指示 Agent 运行 Shell 命令,并在 scripts/ 目录中包含可重用的脚本。本指南涵盖了一次性命令、带有自身依赖项的自包含脚本,以及如何为 Agent 设计脚本接口。

一次性命令#

当现有的软件包已经能满足你的需求时,你可以直接在 SKILL.md 指令中引用它,而无需 scripts/ 目录。许多生态系统都提供了在运行时自动解析依赖项的工具。

  • uvx: 随 uv 一起发布。在隔离环境中运行 Python 包,具有强大的缓存功能。
    uvx ruff@0.8.0 check .
    uvx black@24.10.0 .
  • pipx: 在隔离环境中运行 Python 包。可通过 OS 包管理器安装。
    pipx run 'black==24.10.0' .
    pipx run 'ruff==0.8.0' check .
  • npx: 运行 npm 包,按需下载。随 npm(及 Node.js)一起发布。
    npx eslint@9 --fix .
    npx create-vite@6 my-app
  • bunx: Bun 版本的 npx
  • deno run: 直接从 URL 或标识符运行脚本。需要权限标志(如 --allow-read)。
  • go run: 直接编译并运行 Go 包。内置于 go 命令中。

针对 Skill 中一次性命令的建议:

  • 固定版本(例如 npx eslint@9.0.0),以确保命令的行为随时间推移保持一致。
  • SKILL.md说明前提条件(例如“需要 Node.js 18+”),而不是假设 Agent 环境中已有这些条件。对于运行时级别的要求,请使用 compatibility Frontmatter 字段
  • 将复杂命令移至脚本中。当命令包含过多的标志且难以一次性写对时,在 scripts/ 中放一个经过测试的脚本会更可靠。

SKILL.md 中引用脚本#

使用相对于 Skill 目录根路径的相对路径来引用绑定的文件。Agent 会自动解析这些路径 —— 无需绝对路径。

SKILL.md 中列出可用脚本,以便 Agent 知道它们的存在:

## 可用脚本

- **`scripts/validate.sh`** — 验证配置文件
- **`scripts/process.py`** — 处理输入数据

然后指示 Agent 运行它们:

## 工作流

1. 运行验证脚本:
   ```bash
   bash scripts/validate.sh "$INPUT_FILE"
   ```
  1. 处理结果:
    python3 scripts/process.py --input results.json

> [!NOTE]
> 同样的相对路径约定也适用于 `references/*.md` 等支持文件 —— 脚本执行路径(在代码块中)是相对于 **Skill 目录根目录** 的,因为 Agent 是从那里运行命令的。

## 自包含脚本

当你需要可重用的逻辑时,在 `scripts/` 中绑定一个声明了自身依赖项的脚本。Agent 只需一条命令即可运行该脚本 —— 无需单独的清单文件或安装步骤。

几种语言支持内联依赖声明:

### Python (PEP 723)
[PEP 723](https://peps.python.org/pep-0723/) 定义了内联脚本元数据的标准格式。在 `# ///` 标记内的 TOML 块中声明依赖项:

```python
# /// script
# dependencies = [
#   "beautifulsoup4",
# ]
# ///

from bs4 import BeautifulSoup

html = '<html><body><h1>Welcome</h1><p class="info">This is a test.</p></body></html>'
print(BeautifulSoup(html, "html.parser").select_one("p.info").get_text())

使用 uv 运行(推荐):

uv run scripts/extract.py

Deno#

Deno 的 npm:jsr: 导入说明符使每个脚本默认都是自包含的:

#!/usr/bin/env -S deno run

import * as cheerio from "npm:cheerio@1.0.0";

const html = `<html><body><h1>Welcome</h1><p class="info">This is a test.</p></body></html>`;
const $ = cheerio.load(html);
console.log($("p.info").text());

Bun#

当没有发现 node_modules 目录时,Bun 会在运行时自动安装缺失的包。直接在导入路径中固定版本:

#!/usr/bin/env bun

import * as cheerio from "cheerio@1.0.0";

const html = `<html><body><h1>Welcome</h1><p class="info">This is a test.</p></body></html>`;
const $ = cheerio.load(html);
console.log($("p.info").text());

Ruby#

Bundler 自 2.6 版本起随 Ruby 一起发布。使用 bundler/inline 直接在脚本中声明 gem:

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'nokogiri'
end

html = '<html><body><h1>Welcome</h1><p class="info">This is a test.</p></body></html>'
doc = Nokogiri::HTML(html)
puts doc.at_css('p.info').text

为 Agent 环境设计脚本#

当 Agent 运行你的脚本时,它会读取 stdout 和 stderr 来决定下一步该做什么。一些设计选择可以使脚本更易于 Agent 使用。

避免交互式提示#

这是 Agent 执行环境的一个强制要求。Agent 在非交互式 Shell 中操作 —— 它们无法响应 TTY 提示、密码对话框或确认菜单。一个阻塞在交互式输入上的脚本将无限期挂起。

请通过命令行标志、环境变量或 stdin 接受所有输入。