scripts/ 目录中打包可复用脚本。本指南会介绍一次性命令、自包含且自带依赖的脚本,以及如何为 agent 使用场景设计脚本接口。
一次性命令
如果现有包已经能满足你的需求,你可以直接在SKILL.md 指令里引用它,而不一定要单独建立 scripts/ 目录。很多生态都提供了能在运行时自动解析依赖的工具。
- uvx
- pipx
- npx
- bunx
- deno run
- go run
- 固定版本。 例如
npx eslint@9.0.0,这样命令在不同时间运行时行为一致。 - 把前置条件写进
SKILL.md。 例如“Requires Node.js 18+”,不要默认 agent 所在环境已经具备这些条件。对于运行时级别的要求,请使用compatibilityfrontmatter 字段。 - 复杂命令移入脚本。 当你只是带几个 flag 调用一个工具时,一次性命令很适合;但如果命令已经复杂到第一次就不容易写对,那么放进经过测试的
scripts/脚本会更可靠。
从 SKILL.md 引用脚本
引用打包文件时,请使用 相对于 skill 目录根的相对路径。agent 会自动解析这些路径,不需要绝对路径。
在 SKILL.md 中列出有哪些脚本可用,这样 agent 才知道它们存在:
SKILL.md
SKILL.md
这种相对路径约定同样适用于
references/*.md 这类辅助文件。代码块中的脚本执行路径始终是相对于 skill 目录根 的,因为 agent 会从那里执行命令。自包含脚本
如果你需要可复用逻辑,可以在scripts/ 中打包一个脚本,并让它以内联方式声明自身依赖。这样 agent 只用一条命令就能运行脚本,不需要额外的 manifest 文件,也不用提前执行安装步骤。
有几种语言都支持内联依赖声明:
- Python
- Deno
- Bun
- Ruby
为 agent 使用场景设计脚本
当 agent 运行你的脚本时,它会读取 stdout 和 stderr 来决定下一步怎么做。有几个设计选择会显著影响脚本对 agent 是否友好。避免交互式提示
这是 agent 执行环境里的硬性要求。agent 工作在非交互式 shell 中,不能响应 TTY 提示、密码对话框或确认菜单。任何等待交互输入的脚本都会一直挂起。 应当通过命令行 flag、环境变量或 stdin 接收全部输入:用 --help 记录用法
--help 输出是 agent 学习脚本接口的主要方式。请包含简短描述、可用 flag 和使用示例:
编写有帮助的错误消息
当 agent 拿到一个错误时,这条消息会直接影响它下一次尝试怎么改。一个含糊的 “Error: invalid input” 只会浪费一次轮次。更好的方式是:明确说出哪里错了、期望的是什么、下一步应该怎么试。使用结构化输出
优先使用结构化格式,例如 JSON、CSV、TSV,而不是自由文本。结构化格式既便于 agent 消费,也便于标准工具(jq、cut、awk)处理,因此更容易组成流水线。
更多考虑
- 幂等性。 agent 可能会重试命令。“如果不存在则创建”通常比“创建并在重复时报错”更安全。
- 输入约束。 遇到有歧义的输入时,不要猜,直接报一个清晰错误。尽量使用枚举值和封闭集合。
- Dry-run 支持。 对于破坏性或有状态的操作,
--dry-run可以让 agent 先预览将要发生什么。 - 有意义的退出码。 为不同失败类型使用不同退出码(例如未找到、参数非法、鉴权失败),并在
--help输出中记录这些退出码的含义,让 agent 知道该如何解释它们。 - 安全默认值。 需要破坏性操作时,要考虑是否应该要求显式确认 flag(例如
--confirm、--force)或其他与风险级别相匹配的保护措施。 - 可预测的输出规模。 许多 agent 运行环境会在工具输出超过阈值时自动截断(例如 10 到 30K 字符),这可能导致关键内容丢失。如果你的脚本可能输出很多内容,默认就应该返回摘要或合理限制,并支持像
--offset这样的 flag,让 agent 可以按需请求更多内容。另一种做法是:如果输出很大且不适合分页,就要求 agent 显式传入--output,指定输出文件,或传-来明确表示要输出到 stdout。