Расширение скриптов навыков

Помимо написания инструкций в SKILL.md, вы также можете добавить исполняемый код в навык через каталог scripts.

В этом разделе вы узнаете, как использовать скрипты для расширения функциональности навыка.


Зачем использовать скрипты

Использование скриптов позволяет:

  • Инкапсулировать сложную логику и избежать написания большого объёма кода в SKILL.md
  • Предоставлять проверенные, надёжные реализации
  • Позволять агентам повторно использовать одни и те же инструменты и функции
  • Обрабатывать более сложные операции ввода/вывода

Совет: когда вы замечаете, что агент многократно реализует одну и ту же логику при разных выполнениях, это часто хороший момент, чтобы создать скрипт.


Структура каталога скриптов

Скрипты следует размещать в подкаталоге scripts/ каталога навыка:

Структура каталогов

my-skill/
├── SKILL.md
└── scripts/
    ├── script1.py
    ├── script2.sh
    └── helper.js

Руководство по написанию скриптов

1. Самодостаточность

Скрипты должны быть настолько самодостаточными, насколько это возможно, или чётко документировать свои зависимости.

Пример самодостаточного скрипта

#!/usr/bin/env python3
"""
Скрипт извлечения текста из PDF

Зависимость: pip install pdfplumber
Запуск: python scripts/extract_pdf.py input.pdf
"""


import sys
import pdfplumber

def extract_text_from_pdf(pdf_path):
    """Извлечь текст из PDF-файла"""
    with pdfplumber.open(pdf_path) as pdf:
        text = ""
        for page in pdf.pages:
            text += page.extract_text() or ""
    return text

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Использование: python extract_pdf.py <pdf-файл>")
        sys.exit(1)

    pdf_path = sys.argv[1]
    text = extract_text_from_pdf(pdf_path)
    print(text)

2. Понятная обработка ошибок

Скрипты должны предоставлять полезные сообщения об ошибках, помогающие агентам понять, что пошло не так.

Пример обработки ошибок

import sys

def main():
    if len(sys.argv) < 2:
        print("Ошибка: отсутствует обязательный аргумент", file=sys.stderr)
        print("Использование: python script.py <входной файл> [выходной файл]", file=sys.stderr)
        sys.exit(1)

    input_file = sys.argv[1]

    try:
        # Выполнить основную логику
        process_file(input_file)
    except FileNotFoundError:
        print(f"Ошибка: файл {input_file} не найден", file=sys.stderr)
        sys.exit(1)
    except PermissionError:
        print(f"Ошибка: нет прав на чтение файла {input_file}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"Ошибка: при обработке файла произошла неизвестная ошибка: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()

3. Обработка граничных случаев

Скрипты должны корректно обрабатывать различные граничные случаи, а не аварийно завершаться.

Пример обработки граничных случаев

def validate_input(text):
    """Проверить, допустимы ли входные данные"""
    if not text:
        return False, "Ввод не может быть пустым"

    if len(text) > 10000:
        return False, "Длина входных данных превышает предел (макс. 10000 символов)"

    return True, ""

# Использование проверки
is_valid, error_msg = validate_input(user_input)
if not is_valid:
    print(f"Проверка не удалась: {error_msg}")
    sys.exit(1)

Ссылки на скрипты в SKILL.md

Когда навыку нужно выполнить скрипт, опишите в SKILL.md, как его вызывать.

Ссылки на скрипты:

## PDF 文本提取

使用脚本提取 PDF 中的文本:

```bash
python scripts/extract_pdf.py input.pdf
```

脚本会从 input.pdf 提取所有文本并输出到标准输出。

如果需要将结果保存到文件:

```bash
python scripts/extract_pdf.py input.pdf > output.txt
```

Примечание: при ссылке на скрипты используйте пути относительно корневого каталога навыка.


Поддерживаемые языки скриптов

Поддерживаемые языки сценариев зависят от используемой вами реализации агента. Распространённые варианты включают:

Язык Описание
Python Самый часто используемый вариант, мощный и простой для написания
Bash Подходит для системных операций и инструментов командной строки
JavaScript Подходит для задач, связанных с Web

Совет: при выборе языка сценариев учитывайте среду выполнения целевого пользователя. Если сомневаетесь, Python — самый безопасный выбор.


Полный пример: навык обработки PDF

Давайте рассмотрим полный пример, показывающий, как объединить SKILL.md и сценарии:

Структура навыка

pdf-tool/
├── SKILL.md
└── scripts/
    ├── extract.py
    ├── fill_form.py
    └── merge.py

Содержимое SKILL.md:

---
name: pdf-tool
description: 处理 PDF 文件,包括提取文本、填写表单、合并文件。使用场景:处理 PDF、提取文本、填写表单、合并 PDF.
---

## 提取 PDF 文本

从 PDF 文件中提取文本内容:

```bash
python scripts/extract.py input.pdf
```

输出是提取的纯文本内容。

## 填写 PDF 表单

使用 JSON 数据填写 PDF 表单:

```bash
python scripts/fill_form.py input.pdf data.json output.pdf
```

data.json 格式:
```json
{
  "field_name": "字段值",
  "another_field": "另一个值"
}
```

## 合并 PDF

将多个 PDF 文件合并为一个:

```bash
python scripts/merge.py output.pdf input1.pdf input2.pdf input3.pdf
```

## 依赖安装

需要安装 pdfplumber 和 PyPDF2:

```bash
pip install pdfplumber PyPDF2
```

Два режима использования

Существует два способа использования кода в Skill:

Метод Применимый сценарий Нужен ли каталог scripts/
Одноразовая команда Нужно только вызвать существующие инструменты, пользовательская логика не требуется Не требуется
Самодостаточный скрипт Сложная логика, которую нужно переиспользовать Необходимы

Одноразовые команды

Когда существующие инструменты менеджера пакетов уже удовлетворяют требованиям, вы можете напрямую ссылаться на них в инструкциях SKILL.md, не создавая каталог scripts/.

Ниже приведены распространённые способы выполнения в каждой языковой экосистеме:

uvx(Python)

uvx — это команда для запуска инструментов, входящая в состав uv. Она запускает пакеты Python в изолированной среде, а благодаря агрессивному кэшированию повторные запуски происходят почти мгновенно.

Пример

# Запустить указанную версию ruff для проверки кода
uvx ruff@0.8.0 check .

# Запустить указанную версию black для форматирования кода
uvx black@24.10.0 .

pipx(Python)

pipx — зрелая альтернатива uvx, которую можно установить через системные менеджеры пакетов (например,brew install pipx)。

Пример

# Запустить указанную версию black
pipx run 'black==24.10.0' .

# Запустить указанную версию ruff
pipx run '[email protected]' check .

npx(Node.js)

npx поставляется с npm и скачивает и запускает npm-пакеты по требованию.

Пример

# Запустить проверку ESLint
npx eslint@9 --fix .

# Создать проект с Vite
npx create-vite@6 my-app

go run(Go)

Встроенная в Go команда запуска инструментов компилирует и запускает удалённые пакеты напрямую.

Пример

# Запустить goimports для форматирования импортов
go run golang.org/x/tools/cmd/goimports@v0.28.0 .

# Запустить проверку golangci-lint
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 run

Рекомендации по написанию одноразовых команд: фиксируйте номера версий (например,npx [email protected]) чтобы обеспечить единообразное поведение; объявляйте предварительные требования в SKILL.md (например, "Требуется Node.js 18+"); когда команды становятся сложными, выносите их в каталог scripts/.


Ссылки на скрипты в SKILL.md

Используйте пути, начинающиеся от корня каталога Skill,относительные пути, для ссылок на упакованные файлы.

Агент автоматически разрешит эти пути; нет необходимости использовать абсолютные пути.

Сначала перечислите доступные скрипты в SKILL.md:

Пример

## Доступные скрипты

- **`scripts/validate.sh`** — Проверка файлов конфигурации
- **`scripts/process.py`** — Обработка входных данных
- **`scripts/report.py`** — Генерация отчётов об анализе

Затем ссылайтесь на них в шагах операции:

Пример

## Рабочий процесс операции

1. Запустите скрипт проверки:
   ```bash
   bash scripts/validate.sh "$INPUT_FILE"
   ```

2. Обработка данных:
   ```bash
   python3 scripts/process.py --input results.json
   ```

Пути выполнения скриптов указываются относительно корневого каталога Skill, поскольку Агент запускает команды из каталога Skill. Это также относится к вспомогательным файлам, таким как references/*.md.


Самодостаточные скрипты

Когда вам нужна логика для повторного использования, вы можете упаковать скрипты вscripts/каталог и объявить зависимости внутри скрипта.

Агент может запустить его одной командой, без дополнительных шагов установки.

Самодостаточный скрипт Python (PEP 723)

PEP 723 определяет стандартный формат объявления зависимостей внутри скриптов Python.

Используйте# ///маркеры для оборачивания объявления зависимостей в формате TOML:

Пример: самодостаточный скрипт Python

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

from bs4 import BeautifulSoup

# Пример HTML-контента
html = '<html><body><h1>Welcome</h1><p class="info">EXAMPLE Test</p></body></html>'

# Разбор HTML с помощью BeautifulSoup
soup = BeautifulSoup(html, "html.parser")

# Извлечение текста абзаца с class="info"
info_text = soup.select_one("p.info").get_text()
print(info_text)

Как запустить:

Пример

# Запуск с uv (рекомендуется)
uv run scripts/extract.py

# Запуск с pipx
pipx run scripts/extract.py
EXAMPLE 测试

Самодостаточный скрипт Deno

Deno используетnpm:иjsr:спецификаторы import для достижения самодостаточности:

Пример: Самодостаточный скрипт Deno

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

import * as cheerio from "npm:[email protected]";

const html = `<html><body><h1>Добро пожаловать</h1><p class="info">ПРИМЕР Тест</p></body></html>`;
const $ = cheerio.load(html);
console.log($("p.info").text());

Пример

deno run scripts/extract.ts

Самодостаточный скрипт Bun

Когда у Bun нетnode_modulesкаталога, он автоматически устанавливает отсутствующие пакеты:

Пример: Самодостаточный скрипт Bun

#!/usr/bin/env bun

import * as cheerio from "[email protected]";

const html = `<html><body><h1>Добро пожаловать</h1><p class="info">ПРИМЕР Тест</p></body></html>`;
const $ = cheerio.load(html);
console.log($("p.info").text());

Пример

bun run scripts/extract.ts

Самодостаточный скрипт Ruby

Ruby используетbundler/inlineчтобы объявить зависимости gem в скрипте:

Пример: Самодостаточный скрипт Ruby

require 'bundler/inline'

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

html = '<html><body><h1>Welcome</h1><p class="info">EXAMPLE Test</p></body></html>'
doc = Nokogiri::HTML(html)
puts doc.at_css('p.info').text

Пример

ruby scripts/extract.rb

Ключевые моменты проектирования скриптов для агентов

Агент определяет свои следующие действия, читая stdout и stderr, поэтому при проектировании скрипта следует учитывать особенности использования агентом.

Избегайте интерактивных запросов

Это жёсткое требование. Агент работает в неинтерактивной оболочке и не может отвечать на TTY-приглашения, диалоги ввода пароля или меню подтверждения.

Все входные данные должны передаваться через аргументы командной строки, переменные окружения или stdin.

Пример: неправильный подход в сравнении с правильным подходом

# Неправильно: зависнет в ожидании ввода
$ python scripts/deploy.py
Целевая среда: _

# Правильно: понятное сообщение об ошибке и указания
$ python scripts/deploy.py
Ошибка: --env обязателен. Варианты: development, staging, production.
Использование: python scripts/deploy.py --env staging --tag v1.2.3

Предоставьте документацию --help

--helpВывод — основной способ для Агента понять интерфейс скрипта.

Включите краткое описание, доступные параметры и примеры использования:

Пример: хороший вывод --help

Использование: scripts/process.py [ПАРАМЕТРЫ] INPUT_FILE

Обработать входные данные и сформировать сводный отчёт.

Параметры:
  --formatFORMAT Формат вывода: json, csv, table(По умолчанию: json)
  --outputFILE Записывать вывод в файл вместо stdout
  --verboseВыводить информацию о ходе выполнения в stderr

Примеры:
  scripts/process.py data.csv
  scripts/process.py --format csv --output report.csv data.csv

Пишите полезные сообщения об ошибках

Когда Агент видит сообщение об ошибке, он соответствующим образом корректирует свою стратегию; чем конкретнее сообщение, тем легче Агенту самостоятельно исправиться.

Пример

# Плохое сообщение об ошибке
Ошибка: неверный ввод

# Хорошее сообщение об ошибке
Ошибка: --format должен быть одним из: json, csv, table.
       Получено: "xml"

Используйте структурированный вывод

Предпочитайте структурированные форматы, такие как JSON, CSV и TSV, для вывода, а не произвольный текст.

Структурированные форматы могут обрабатываться как Агентом, так и стандартными инструментами (jq, cut, awk), что упрощает их комбинирование.

Пример

# Не рекомендуется: выровненный текст сложно разбирать программно
ИМЯ СТАТУС СОЗДАНО
my-service работает   2025-01-15

# Рекомендуется: формат JSON с чёткими границами полей
{"name": "my-service", "status": "running", "created": "2025-01-15"}

Выводите структурированные данные в stdout, а сообщения о ходе выполнения и диагностическую информацию — в stderr. Так Агент получает чистый, легко разбираемый вывод и при необходимости может просматривать диагностическую информацию.


Дополнительные рекомендации по проектированию скриптов

Рекомендация Описание
Идемпотентность Агент может повторять команды. "Создавать, если не существует" безопаснее, чем "создавать и выдавать ошибку при дубликатах"
Ограничения входных данных Отклоняйте неоднозначный ввод с понятной ошибкой, а не пытайтесь угадать намерение пользователя
Поддержка пробного запуска Для деструктивных или изменяющих состояние операций предусмотрите--dry-runфлаг, позволяющий Агенту предварительно просмотреть операцию
Осмысленные коды выхода Используйте разные коды выхода для разных типов сбоев (не найдено, неверный аргумент, ошибка аутентификации и т. д.)
Предсказуемый размер вывода По умолчанию выводите сводку и предоставьте--offsetдругие параметры, чтобы Агент мог при необходимости получить больше информации.
Безопасные значения по умолчанию Деструктивные операции должны требовать явный флаг подтверждения (--confirm、--force)

Полный пример скрипта навыка

Ниже приведена полная структура каталога навыка со скриптами:

Пример

csv-analyzer/
├── SKILL.md              # Основной файл инструкций
├── scripts/
│ ├── overview.py       # Скрипт обзора данных
│ ├── summary.py        # Скрипт статистической сводки
│ └── validate.py       # Скрипт проверки данных
├── references/
│ └── api-errors.md     # Справочник по ошибкам API
└── assets/
    └── report-template.md  # Шаблон отчёта

Соответствующее содержимое SKILL.md:

Пример

---
name: csv-analyzer
description: >
Анализируйте файлы CSV и табличные данные. Когда у пользователя есть файлы CSV, TSV или Excel
и он хочет исследовать, преобразовывать или визуализировать данные, используйте это.
---

# Анализ данных CSV

## Доступные скрипты

- **`scripts/overview.py`** — Отображает обзор данных (количество строк, имена столбцов, типы)
- **`scripts/summary.py`** — Генерирует статистическую сводку
- **`scripts/validate.py`** — Проверяет качество данных

## Рабочий процесс

1. Сначала запустите скрипт overview, чтобы понять структуру данных:
   ```bash
   uv run scripts/overview.py input.csv
   ```

2. Сгенерируйте статистическую сводку:
   ```bash
   uv run scripts/summary.py input.csv --output summary.json
   ```

3. Проверьте качество данных:
   ```bash
   uv run scripts/validate.py input.csv
   ```

## Примечания

- Для больших файлов используйте параметр `--chunk-size` для обработки по частям
- Для китайских CSV-файлов попробуйте параметр `--encoding gbk`

Распространение скриптов и зависимости

Если вашим скриптам нужны внешние зависимости, у вас есть несколько вариантов:

1. Документируйте зависимости в SKILL.md

Самый простой способ — записать необходимые зависимости в SKILL.md.

2. Используйте виртуальные окружения

Для сложных проектов можно создать виртуальное окружение.

3. Используйте Docker

Если требуется полноценная среда выполнения, можно использовать контейнер Docker.

Примечание: убедитесь, что скрипты могут запускаться в целевой среде. Прежде чем писать скрипты, разберитесь в среде выполнения целевого пользователя.


Итог

В этом разделе мы узнали, как использовать скрипты для расширения функциональности Skill:

  • Поместите скрипты в каталог scripts/
  • Скрипты должны быть самодостаточными и иметь чёткую обработку ошибок
  • Используйте относительные пути при ссылке на скрипты в SKILL.md
  • Убедитесь, что скрипты могут запускаться в целевой среде
Другие расширения