Интеграция навыков и инструментальной цепочки
Благодаря интеграции с внешними инструментальными цепочками навыки могут выполнять задачи, которые Claude не может выполнить в одиночку.
В этой статье рассказывается, как вызывать инструменты командной строки, системные инструменты и сторонние библиотеки в Навыке, а также приводится полный пример интеграции.
Типы инструментов, которые могут вызывать навыки
| Тип инструмента | Пример | Метод вызова |
|---|---|---|
| Системные команды | ls、cp、find、wc | subprocess.run() |
| Среда выполнения языка | python、node、bash | subprocess.run() |
| Инструменты обработки документов | pandoc、pdflatex | subprocess.run() |
| Инструменты обработки медиа | ffmpeg、imagemagick | subprocess.run() |
| Библиотеки Python | pandas、openpyxl、pypdf | Вызов напрямую после импорта |
| Инструменты Node.js | prettier、eslint | Вызов через npx |
Перед вызовом внешних инструментов убедитесь, что инструменты установлены в среде выполнения. Обычные инструменты (python3, pip, node, npm) предустановлены в песочнице Claude, но pandoc, ffmpeg и т. д. нужно устанавливать отдельно.
Вызов внешних команд в скриптах
Модульsubprocess`subprocess` из Python — стандартный способ вызова внешних команд. Рекомендуется единообразно оборачивать его в переиспользуемые служебные функции.
Пример
import subprocess
import sys
import json
def run_command(cmd: list, timeout: int = 60) -> dict:
"""
Запустить внешнюю команду и перехватить вывод
Параметры:
cmd: список команд, например, ["pandoc", "--version"]
timeout: тайм-аут в секундах, по умолчанию 60
Возвращает:
словарь, содержащий success, stdout, stderr, returncode
"""
try:
result = subprocess.run(
cmd,
capture_output=True, # Захватить и stdout, и stderr
text=True, # Вернуть как строку, а не байты
timeout=timeout
)
return {
"success": result.returncode == 0,
"returncode": result.returncode,
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip()
}
except FileNotFoundError:
return {
"success": False,
"returncode": -1,
"stdout": "",
"stderr": f"Команда не найдена: {cmd
}
except subprocess.TimeoutExpired:
return {
"success": False,
"returncode": -1,
"stdout": "",
"stderr": f"Время выполнения команды истекло (превышено {timeout} секунд)"
}
# Пример: использование pandoc для преобразования Markdown в HTML
if __name__ == "__main__":
result = run_command([
"pandoc",
"/mnt/user-data/uploads/readme.md",
"-o", "/mnt/user-data/outputs/readme.html",
"--standalone"
])
if result["success"]:
print("Преобразование выполнено успешно")
else:
print(f"Преобразование не удалось: {result['stderr']}")
sys.exit(1)
Проверка доступности инструмента
Проверка того, установлены ли необходимые инструменты, перед выполнением Skill обеспечивает четкую обратную связь до того, как задача потерпит неудачу на полпути.
Пример
import shutil
import sys
REQUIRED_TOOLS = [
("pandoc", "sudo apt-get install pandoc"),
("ffmpeg", "sudo apt-get install ffmpeg"),
("convert", "sudo apt-get install imagemagick"),
]
def check_tools(tools: list) -> bool:
"""Проверить список инструментов, вернуть True, если все готовы"""
all_ok = True
for tool, install_cmd in tools:
path = shutil.which(tool) # Найти путь к инструменту в PATH
if path:
print(f" Установлено: {tool} → {path}")
else:
print(f" Не установлено: {tool} Команда установки: {install_cmd}")
all_ok = False
return all_ok
if __name__ == "__main__":
print("Проверка зависимостей инструментов...")
if not check_tools(REQUIRED_TOOLS):
print("\n"Пожалуйста, сначала установите отсутствующие инструменты.")
sys.exit(1)
print("\n"Все инструменты готовы, продолжайте выполнение.")
检查工具依赖... 已安装:pandoc → /usr/bin/pandoc 未安装:ffmpeg 安装命令:sudo apt-get install ffmpeg 未安装:convert 安装命令:sudo apt-get install imagemagick 请先安装缺少的工具。
Объявление зависимостей инструментов в SKILL.md
Используйте в YAML frontmattercompatibilityполе `dependencies`, чтобы перечислить все внешние зависимости, чтобы пользователи знали, что подготовить перед установкой навыка.
---
name: doc-converter
description: >
将文档在不同格式间转换,支持 Markdown、HTML、PDF、Word.
当用户需要格式转换、导出文档时触发。
compatibility:
tools:
- pandoc >= 2.14 # 文档格式转换
- python >= 3.8 # 运行辅助脚本
python_packages:
- pypdf >= 3.0 # PDF 处理
- python-docx >= 1.0
---
Интеграция инструментов Node.js
Черезnpx`npx`, можно напрямую вызывать инструменты CLI из пакетов npm без глобальной установки.
Пример
import subprocess
import sys
def run_prettier(file_path: str) -> bool:
"""Форматировать файлы кода с помощью prettier"""
result = subprocess.run(
["npx", "--yes", "prettier", "--write", file_path],
capture_output=True,
text=True
)
if result.returncode == 0:
print(f"Форматирование выполнено успешно: {file_path}")
return True
print(f"Форматирование не удалось: {result.stderr}")
return False
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Использование: python use_node_tool.py <путь к файлу>")
sys.exit(1)
sys.exit(0 if run_prettier(sys.argv[1]) else 1)
npx --yesПри первом запуске пакет инструмента загружается автоматически, что требует сетевого подключения к реестру npm. В средах с ограниченным доступом к сети установите его глобально заранее:npm install -g prettier。
Стандартизация результатов вызова инструментов
Разные инструменты имеют разные форматы вывода. Рекомендуется единообразно оборачивать их на уровне Skill, предоставляя наружу только согласованную структуру.
| Способ обработки | Применимый сценарий | Типичные инструменты |
|---|---|---|
| Захват stdout | Инструмент выводит результат в стандартный вывод | pandoc、wc、cat |
| Проверка кода возврата | Инструмент возвращает 0 при успехе и ненулевое значение при ошибке | Почти все CLI-инструменты |
| Чтение выходного файла | Инструмент записывает результат в указанный файл | ffmpeg、pandoc -o |
| Парсинг JSON-вывода | Инструмент поддерживает параметр --json | eslint --format json |
Полный пример интеграции: отчёт Markdown в PDF
В следующем примере pandoc объединяется со скриптом Python для реализации полного скрипта Skill генерации Markdown → PDF.
Пример
# Полный рабочий процесс: проверить инструмент → проверить входные данные → вызвать pandoc → подтвердить вывод
import subprocess
import shutil
import sys
import os
import json
from datetime import datetime
def check_pandoc() -> bool:
"""Проверить, доступен ли pandoc"""
if not shutil.which("pandoc"):
print("Ошибка: pandoc не найден, пожалуйста, выполните: sudo apt-get install pandoc")
return False
return True
def validate_input(md_path: str) -> bool:
"""Проверить входной файл Markdown"""
if not os.path.exists(md_path):
print(f"Ошибка: файл не существует → {md_path}")
return False
if not md_path.lower().endswith(".md"):
print(f"Ошибка: файл должен быть в формате .md → {md_path}")
return False
return True
def convert_to_pdf(md_path: str, output_dir: str) -> dict:
"""Вызов pandoc для преобразования Markdown в PDF"""
os.makedirs(output_dir, exist_ok=True)
# Сгенерировать имя выходного файла с временной меткой, чтобы не перезаписывать старые файлы
base_name = os.path.splitext(os.path.basename(md_path))[0]
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_path = os.path.join(output_dir, f"{base_name}_{timestamp}.pdf")
result = subprocess.run(
[
"pandoc", md_path,
"-o", output_path,
"--pdf-engine=xelatex", # Поддержка китайского языка
"-V", "CJKmainfont=SimSun", # Китайский шрифт (настройте в соответствии с окружением)
"-V", "geometry:margin=2cm" # Поля страницы
],
capture_output=True,
text=True,
timeout=120
)
if result.returncode == 0 and os.path.exists(output_path):
size_kb = os.path.getsize(output_path) // 1024
return {
"status": "success",
"output": output_path,
"size_kb": size_kb
}
return {
"status": "error",
"message": result.stderr or "pandoc не создал выходной файл"
}
def main():
if len(sys.argv) < 2:
print("Использование: python md_to_pdf.py <путь к файлу Markdown>")
sys.exit(1)
md_path = sys.argv[1]
output_dir = "/mnt/user-data/outputs"
# Проверка по шагам; немедленно завершить, если какой-либо шаг не удался
if not check_pandoc():
sys.exit(1)
if not validate_input(md_path):
sys.exit(1)
print(f"Конвертация: {md_path}")
result = convert_to_pdf(md_path, output_dir)
print(json.dumps(result, ensure_ascii=False, indent=2))
sys.exit(0 if result["status"] == "success" else 1)
if __name__ == "__main__":
main()
正在转换:/mnt/user-data/uploads/example_report.md
{
"status": "success",
"output": "/mnt/user-data/outputs/example_report_20260518_102305.pdf",
"size_kb": 248
}
Вызовите этот скрипт в SKILL.md:
## 执行转换 获取用户上传的 .md 文件路径后,运行: ```bash python scripts/md_to_pdf.py <文件路径> ``` 解析 JSON 输出: - status 为 "success":调用 present_files 展示 output 路径的文件 - status 为 "error":将 message 内容展示给用户,说明可能原因Другие расширения