要点
AIエージェントファイルを3ステップで10種類のIDEに対応させる方法:(1) `get_field()`、`get_body()`、`to_kebab()` bash関数を使ってYAMLフロントマターを解析、(2) `convert.sh`を使ってツール固有のフォーマット(Claude Codeの`.md`、Cursorの`.mdc`、Aiderの`CONVENTIONS.md`、Windsurfの`.windsurfrules`)に変換、(3) `install.sh`を使って正しいパスにインストール。一度書けば、自動的に変換され、どこにでもデプロイできます。
1つのエージェントファイルで10種類のIDEに対応。The Agencyプロジェクトが単一のMarkdownファイルをClaude Code、Cursor、Aider、Windsurf、GitHub Copilot、その他6つ以上のツールで動作するように変換する方法を学びましょう。
AIエージェントを作成したとします。それを以下の場所で利用可能にしたい場合:
- Claude Code (`~/.claude/agents/`内の`.md`ファイル)
- Cursor (`.cursor/rules/`内の`.mdc`ファイル)
- Aider (プロジェクトルートの単一の`CONVENTIONS.md`ファイル)
- Windsurf (単一の`.windsurfrules`ファイル)
- GitHub Copilot (`~/.github/agents/`内の`.md`ファイル)
- その他5つ以上のツール
10種類のバージョンを作成しますか?いいえ。一度書けば、自動的に変換できます。
The Agencyプロジェクトは、この問題を2つのbashスクリプトで解決します:
- `convert.sh` — エージェントファイルをツール固有のフォーマットに変換します
- `install.sh` — 変換されたファイルを正しいパスにコピーします
このチュートリアルでは、両方のスクリプトをリバースエンジニアリングします。YAMLフロントマターの解析方法、本文コンテンツの抽出方法、あらゆるツールに対応する変換パイプラインの構築方法を学びます。
エージェントフォーマット
The Agencyのすべてのエージェントは同じ構造を使用しています:
---
name: API Tester
description: Specialized in API testing with Apidog, Postman, and automated validation
color: purple
emoji: 🧪
vibe: Breaks APIs before users do.
---
# API Tester Agent Personality
You are **API Tester**, an expert in API validation...
## Identity & Memory
- Role: API testing specialist
- Personality: Thorough, skeptical, evidence-focused
...
ファイルは2つの部分から構成されています:
- フロントマター — `---`区切り文字で囲まれたYAMLメタデータ
- 本文 — 2番目の`---`以降のMarkdownコンテンツ
変換とは:フロントマターのフィールドを抽出し、本文をターゲットフォーマットに変換し、正しいパスに書き込むことです。
ステップ1:YAMLフロントマターの解析
`parse-frontmatter.sh`を作成します:
#!/usr/bin/env bash
#
# parse-frontmatter.sh — Extract YAML frontmatter fields from agent files
#
set -euo pipefail
# Extract a single field value from YAML frontmatter
# Usage: get_field <field> <file>
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " {
sub("^" f ": ", "");
print;
exit
}
' "$file"
}
# Strip frontmatter, return only body
# Usage: get_body <file>
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# Convert name to kebab-case slug
# Usage: to_kebab "API Tester" → api-tester
to_kebab() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g'
}
# Demo
if [[ "${1:-}" == "--demo" ]]; then
AGENT_FILE="${2:-test-agent.md}"
echo "File: $AGENT_FILE"
echo "Name: $(get_field 'name' "$AGENT_FILE")"
echo "Description: $(get_field 'description' "$AGENT_FILE")"
echo "Slug: $(to_kebab "$(get_field 'name' "$AGENT_FILE")")"
echo "---"
echo "Body preview:"
get_body "$AGENT_FILE" | head -10
fi
テストします:
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
出力:
File: engineering-backend-architect.md
Name: Backend Architect
Description: Senior backend architect specializing in scalable system design...
Slug: backend-architect
---
Body preview:
# Backend Architect Agent Personality
You are **Backend Architect**, a senior backend architect...
ステップ2:Claude Codeフォーマットへの変換
Claude Codeは生の`.md`ファイルを使用します。変換は不要で、単にコピーするだけです:
convert_claude_code() {
local agent_file="$1"
local dest="$HOME/.claude/agents/"
mkdir -p "$dest"
cp "$agent_file" "$dest/"
echo " Claude Code: $(basename "$agent_file")"
}
ステップ3:Cursorフォーマットへの変換
Cursorはフロントマターに`description`フィールドを持つ`.mdc`ファイルを使用します:
convert_cursor() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local description=$(get_field 'description' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
local output=".cursor/rules/agency-${slug}.mdc"
mkdir -p "$(dirname "$output")"
cat > "$output" << EOF
---
description: Agency agent: $description
---
$body
EOF
echo " Cursor: agency-${slug}.mdc"
}
入力:
---
name: API Tester
description: Specialized in API testing...
---
# API Tester Agent...
出力(.mdc):
---
description: Agency agent: Specialized in API testing...
---
# API Tester Agent...
ステップ4:Aiderフォーマットへの変換
Aiderはすべてのエージェントを含む単一の`CONVENTIONS.md`ファイルを使用します:
convert_aider() {
local agent_file="$1"
local output="CONVENTIONS.md"
# Append with separator
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Aider: appended to $output"
}
完全なファイルを構築します:
build_aider() {
local output="CONVENTIONS.md"
echo "# Agency Agents for Aider" > "$output"
echo "" >> "$output"
echo "This file contains all Agency agents for Aider integration." >> "$output"
echo "" >> "$output"
for agent_file in engineering/*.md design/*.md testing/*.md; do
convert_aider "$agent_file"
done
}
ステップ5:Windsurfフォーマットへの変換
Windsurfは単一の`.windsurfrules`ファイルを使用します(Aiderと同様):
convert_windsurf() {
local agent_file="$1"
local output=".windsurfrules"
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Windsurf: appended to $output"
}
ステップ6:Antigravityフォーマットへの変換
Antigravity (Gemini) はサブディレクトリ内の`SKILL.md`ファイルを使用します:
convert_antigravity() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local slug=$(to_kebab "$name")
local output="integrations/antigravity/skills/agency-${slug}/SKILL.md"
mkdir -p "$(dirname "$output")"
cat > "$output" << EOF
# Agency Agent: $name
$(get_body "$agent_file")
EOF
echo " Antigravity: agency-${slug}/SKILL.md"
}
ステップ7:OpenClawフォーマットへの変換
OpenClawはエージェントごとに3つのファイル(`SOUL.md`、`AGENTS.md`、`IDENTITY.md`)を使用します:
convert_openclaw() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local description=$(get_field 'description' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
local output_dir="integrations/openclaw/agency-${slug}"
mkdir -p "$output_dir"
# SOUL.md - Main agent definition
cat > "$output_dir/SOUL.md" << EOF
# $name
$description
---
$body
EOF
# AGENTS.md - Agent capabilities
cat > "$output_dir/AGENTS.md" << EOF
# Agent Capabilities: $name
- Specialized expertise in domain
- Deliverable-focused output
- Success metrics defined
See SOUL.md for full definition.
EOF
# IDENTITY.md - Agent identity
cat > "$output_dir/IDENTITY.md" << EOF
# Identity: $name
- Name: $name
- Description: $description
- Source: The Agency (agency-agents repo)
EOF
echo " OpenClaw: agency-${slug}/"
}
ステップ8:`convert.sh`スクリプトの全貌
完全な変換スクリプト(簡略化版)です:
#!/usr/bin/env bash
#
# convert.sh — Convert all Agency agents to tool-specific formats
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUT_DIR="$REPO_ROOT/integrations"
# Frontmatter helpers
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " { sub("^" f ": ", ""); print; exit }
' "$file"
}
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
to_kebab() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g'
}
# Conversion functions
convert_claude_code() {
local agent_file="$1"
local dest="$OUT_DIR/claude-code/"
mkdir -p "$dest"
cp "$agent_file" "$dest/"
}
convert_cursor() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
mkdir -p "$OUT_DIR/cursor/.cursor/rules/"
cat > "$OUT_DIR/cursor/.cursor/rules/agency-${slug}.mdc" << EOF
---
description: Agency agent: $(get_field 'description' "$agent_file")
---
$body
EOF
}
convert_aider() {
local output="$OUT_DIR/aider/CONVENTIONS.md"
echo "" >> "$output"
echo "---" >> "$output"
cat "$agent_file" >> "$output"
}
convert_windsurf() {
local output="$OUT_DIR/windsurf/.windsurfrules"
echo "" >> "$output"
echo "---" >> "$output"
cat "$agent_file" >> "$output"
}
# Main conversion loop
echo "Converting Agency agents..."
AGENT_DIRS=(engineering design testing marketing sales)
for dir in "${AGENT_DIRS[@]}"; do
for agent_file in "$REPO_ROOT/$dir"/*.md; do
[[ -f "$agent_file" ]] || continue
name=$(get_field 'name' "$agent_file")
echo "Processing: $name"
convert_claude_code "$agent_file"
convert_cursor "$agent_file"
done
done
# Build combined files
echo "# Agency Agents for Aider" > "$OUT_DIR/aider/CONVENTIONS.md"
for dir in "${AGENT_DIRS[@]}"; do
for agent_file in "$REPO_ROOT/$dir"/*.md; do
[[ -f "$agent_file" ]] || continue
convert_aider "$agent_file"
done
done
echo "# Agency Agents for Windsurf" > "$OUT_DIR/windsurf/.windsurfrules"
for dir in "${AGENT_DIRS[@]}"; do
for agent_file in "$REPO_ROOT/$dir"/*.md; do
[[ -f "$agent_file" ]] || continue
convert_windsurf "$agent_file"
done
done
echo "Conversion complete!"
echo " Claude Code: $OUT_DIR/claude-code/"
echo " Cursor: $OUT_DIR/cursor/.cursor/rules/"
echo " Aider: $OUT_DIR/aider/CONVENTIONS.md"
echo " Windsurf: $OUT_DIR/windsurf/.windsurfrules"
実行します:
chmod +x convert.sh
./convert.sh
ステップ9:各ツールへのインストール
変換後、ファイルをツール固有のパスにコピーします:
#!/usr/bin/env bash
#
# install.sh — Install converted agents to your local tools
#
set -euo pipefail
# Claude Code
install_claude_code() {
local src="$REPO_ROOT/integrations/claude-code/"
local dest="$HOME/.claude/agents/"
mkdir -p "$dest"
cp "$src"/*.md "$dest/"
echo "Claude Code: $(find "$dest" -name '*.md' | wc -l) agents installed"
}
# Cursor
install_cursor() {
local src="$REPO_ROOT/integrations/cursor/.cursor/rules/"
local dest="./.cursor/rules/"
mkdir -p "$dest"
cp "$src"/*.mdc "$dest/"
echo "Cursor: $(find "$dest" -name '*.mdc' | wc -l) rules installed"
}
# Aider
install_aider() {
local src="$REPO_ROOT/integrations/aider/CONVENTIONS.md"
local dest="./CONVENTIONS.md"
cp "$src" "$dest"
echo "Aider: CONVENTIONS.md installed"
}
# Windsurf
install_windsurf() {
local src="$REPO_ROOT/integrations/windsurf/.windsurfrules"
local dest="./.windsurfrules"
cp "$src" "$dest"
echo "Windsurf: .windsurfrules installed"
}
# Install all detected tools
install_all() {
if [[ -d "$HOME/.claude/agents/" ]]; then
install_claude_code
fi
if command -v cursor &>/dev/null || [[ -d "./.cursor/" ]]; then
install_cursor
fi
if command -v aider &>/dev/null; then
install_aider
fi
}
install_all
フォーマット比較
| ツール | フォーマット | スコープ | 変換 |
|---|---|---|---|
| Claude Code | .md |
ユーザー全体 (~/.claude/agents/) |
そのままコピー |
| Cursor | .mdc |
プロジェクト (.cursor/rules/) |
descriptionフロントマターを追加 |
| Aider | CONVENTIONS.md |
プロジェクトルート | すべてのエージェントを連結 |
| Windsurf | .windsurfrules |
プロジェクトルート | すべてのエージェントを連結 |
| GitHub Copilot | .md |
ユーザー全体 (~/.github/agents/) |
そのままコピー |
| Antigravity | SKILL.md |
ユーザー全体 (~/.gemini/antigravity/) |
スキルディレクトリにラッピング |
| OpenClaw | SOUL.md + その他 |
ユーザー全体 (~/.openclaw/) |
3つのファイルに分割 |
| Gemini CLI | 拡張機能 | ユーザー全体 (~/.gemini/extensions/) |
マニフェスト + スキルを生成 |
| OpenCode | .md |
プロジェクト (.opencode/agents/) |
そのままコピー |
| Qwen Code | .md |
プロジェクト (.qwen/agents/) |
SubAgentとしてコピー |
独自の変換スクリプトを構築する
新しいツールを追加するためのテンプレート:
#!/usr/bin/env bash
# 1. Define conversion function
convert_your_tool() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local description=$(get_field 'description' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
# 2. Create output path
local output="path/to/your/tool/agency-${slug}.ext"
mkdir -p "$(dirname "$output")"
# 3. Write converted content
cat > "$output" << EOF
# Your tool-specific format
# Use: $name, $description, $body
EOF
echo " YourTool: agency-${slug}.ext"
}
# 4. Add to main loop
for agent_file in engineering/*.md; do
convert_your_tool "$agent_file"
done
構築したもの
| コンポーネント | 目的 |
|---|---|
get_field() |
YAMLフロントマターの値を抽出 |
get_body() |
フロントマターを削除し、Markdown本文を返す |
to_kebab() |
名前をURLセーフなスラッグに変換 |
convert_cursor() |
.mdcフォーマットに変換 |
convert_aider() |
単一ファイルに連結 |
convert_windsurf() |
単一ファイルに連結 |
convert_antigravity() |
スキルディレクトリを作成 |
convert_openclaw() |
エージェントごとに3つのファイルに分割 |
install.sh |
ツール固有のパスにコピー |
次のステップ
スクリプトを拡張する:
- `xargs -P`またはGNU parallelを使った並列変換を追加する
- バリデーションを追加する(必須のフロントマターフィールドのチェック)
- ドライランモードを追加する(`--dry-run`フラグ)
さらにツールを追加する:
- VS Code拡張機能
- JetBrains IDE
- 独自の社内ツール
大規模なリポジトリ向けに最適化する:
- 解析済みフロントマターをキャッシュする
- 安全なファイル処理のために`find`と`-print0`を使用する
- 100以上のエージェント向けにプログレスバーを追加する
一般的な問題のトラブルシューティング
変換スクリプトが「bad substitution」で失敗する:
- bashではなくshで実行していることを確認する:`#!/usr/bin/env bash`
- bashのバージョンを確認する:`bash --version`(4.0以上であること)
- bashで明示的に実行する:`bash convert.sh`
- Windowsの改行コードを探す:`sed -i 's/\r$//' convert.sh`
フロントマターフィールドが抽出されない:
- YAMLフォーマットが単なる`:`ではなく`: `(コロンとスペース)を使用していることを確認する
- フィールド名の前の余分なスペースをチェックする
- フロントマターの区切り文字が正確に`---`(ハイフン3つ)であることを確認する
- 手動で解析をテストする:`./parse-frontmatter.sh --demo agent.md`
スラッグ生成で壊れた名前が作成される:
- `to_kebab()`関数をエッジケースでテストする
- 特殊文字を処理する:`to_kebab() { echo "$1" | iconv -f utf8 -t ascii//translit | ... }`
- 空のスラッグに対するフォールバックを追加する:`[[ -z "$slug" ]] && slug="unknown-agent"`
- デバッグ用に元の名前をログに記録する
Cursorルールがロードされない:
- `.mdc`ファイルに`description`を含む有効なフロントマターがあることを確認する
- CursorのMCP設定を確認する:`.cursor/mcp.json`
- ファイルが`.cursor/rules/`にあり、`.cursor/agents/`ではないことを確認する
- 新しいルールを追加した後、Cursorを再起動する
AiderのCONVENTIONS.mdが大きくなりすぎる:
- カテゴリ別に分割する:`CONVENTIONS-engineering.md`、`CONVENTIONS-design.md`
- 非推奨のエージェントの自動削除を実装する
- 上部に目次を追加する
- includeディレクティブ付きの各エージェントファイルを検討する
大規模変換のためのパフォーマンス最適化
並列処理:
100以上のエージェントを持つリポジトリでは、GNU parallelを使用します:
#!/usr/bin/env bash
# convert-parallel.sh
export OUT_DIR="$REPO_ROOT/integrations"
# Export functions for parallel use
export -f get_field get_body to_kebab convert_cursor convert_claude_code
# Find all agent files and process in parallel
find "$REPO_ROOT" -name "*.md" -type f | \
parallel -j 8 --progress '
name=$(get_field "name" {})
slug=$(to_kebab "$name")
echo "Converting: $name"
convert_cursor "{}"
convert_claude_code "{}"
'
echo "Parallel conversion complete!"
増分変換:
変更されたファイルのみを変換します:
#!/usr/bin/env bash
# convert-incremental.sh
CACHE_FILE="$REPO_ROOT/.conversion-cache"
# Load previous state
declare -A PREV_HASHES
if [[ -f "$CACHE_FILE" ]]; then
while IFS='=' read -r file hash; do
PREV_HASHES["$file"]="$hash"
done < "$CACHE_FILE"
fi
# Process each agent
for agent_file in engineering/*.md; do
CURRENT_HASH=$(md5sum "$agent_file" | cut -d' ' -f1)
PREV_HASH="${PREV_HASHES[$agent_file]:-}"
if [[ "$CURRENT_HASH" != "$PREV_HASH" ]]; then
echo "Changed: $agent_file"
convert_cursor "$agent_file"
convert_claude_code "$agent_file"
NEW_HASHES["$agent_file"]="$CURRENT_HASH"
else
echo "Unchanged: $agent_file"
fi
done
# Save cache
for file in "${!NEW_HASHES[@]}"; do
echo "$file=${NEW_HASHES[$file]}"
done > "$CACHE_FILE"
進捗状況の追跡:
長い変換のために視覚的な進捗を追加します:
#!/usr/bin/env bash
total_files=$(find "$REPO_ROOT" -name "*.md" -type f | wc -l)
current=0
for agent_file in "$REPO_ROOT"/**/*.md; do
((current++))
percent=$((current * 100 / total_files))
# Progress bar
filled=$((percent / 5))
empty=$((20 - filled))
bar=$(printf '%*s' "$filled" | tr ' ' '#')
spaces=$(printf '%*s' "$empty" | tr ' ' ' ')
name=$(get_field 'name' "$agent_file")
echo -ne "\r[${bar}${spaces}] ${percent}% - $name"
convert_cursor "$agent_file"
done
echo -ne "\n"
共有エージェントのセキュリティに関する考慮事項
エージェントソースの検証:
外部ソースからエージェントをダウンロードする場合:
#!/usr/bin/env bash
# validate-agent.sh
validate_agent() {
local file="$1"
# Check required frontmatter fields
local name=$(get_field 'name' "$file")
local description=$(get_field 'description' "$file")
if [[ -z "$name" ]]; then
echo "ERROR: Missing 'name' field in $file"
return 1
fi
if [[ -z "$description" ]]; then
echo "WARNING: Missing 'description' field in $file"
fi
# Check for malicious patterns in body
local body=$(get_body "$file")
if echo "$body" | grep -q 'rm -rf\|curl.*\|wget.*\|eval\|exec'; then
echo "WARNING: Potentially dangerous patterns in $file"
return 1
fi
echo "VALID: $name"
return 0
}
エージェント実行のサンドボックス化:
信頼できないエージェントについては、隔離された環境で実行します:
- エージェント実行にDockerコンテナを使用する
- 読み取り専用マウントでファイルシステムアクセスを制限する
- 特定のドメインへのネットワークアクセスを制限する
- 監査ログのためにすべてのエージェントアクションを記録する
1つのエージェントファイル。10のIDE。2つのbashスクリプト。
これが変換自動化の力です。一度書けば、自動的に変換され、どこにでもインストールできます。
次はあなたの番です:お気に入りのAIツールに変換サポートを追加しましょう。スクリプトを共有し、エージェントをポータブルにしましょう。
主要なポイント
- 一度書けば、10以上のフォーマットに変換可能 — YAMLフロントマターを持つ単一のMarkdownファイルが、Claude Code、Cursor、Aider、Windsurf、その他6つ以上のツールに変換されます。
- Bash解析がフロントマター抽出を処理 — `get_field()`はYAML値を抽出し、`get_body()`はフロントマターを削除し、`to_kebab()`はURLセーフなスラッグを作成します。
- ツール固有のフォーマットには異なる変換が必要 — Claude Codeはそのままコピーし、Cursorはdescriptionフロントマターを追加し、Aider/Windsurfはすべてのエージェントを連結します。
- インストールスクリプトが正しいパスにコピー — ユーザー全体のツールは`~/.claude/agents/`を使用し、プロジェクトツールは`.cursor/rules/`またはプロジェクトルートファイルを使用します。
- 新しいツールのテンプレートで拡張可能 — `convert_your_tool()`関数を定義し、メインループに追加し、フォーマット要件を文書化します。
よくある質問
convert.shとは何ですか?どのように機能しますか?convert.shは、エージェントのMarkdownファイルからYAMLフロントマターを解析し、本文コンテンツを抽出し、各エージェントをツール固有のフォーマットに変換するbashスクリプトです。解析にはawkを、スラッグ変換にはsedを、出力生成にはヒアドキュメントを使用します。
bashでのフロントマター解析はどのように行われますか?`get_field()`関数は、awkを使用してフロントマターの区切り文字(`---`)を追跡し、フィールド名と一致する行を見つけて値を抽出します。`get_body()`は、2番目の`---`区切り文字以降のすべての行を出力します。
どのIDEとツールがサポートされていますか?Claude Code (`.md`)、Cursor (`.mdc`)、Aider (`CONVENTIONS.md`)、Windsurf (`.windsurfrules`)、GitHub Copilot (`.md`)、Antigravity (`SKILL.md`)、OpenClaw (`SOUL.md` + 2ファイル)、Gemini CLI拡張機能、OpenCode、Qwen Codeです。
新しいツールの変換サポートを追加するにはどうすればよいですか?フロントマターフィールドを抽出し、本文をツールのフォーマットに変換し、正しいパスに書き込む`convert_yourtool()`関数を作成します。その関数呼び出しをメインの変換ループに追加します。
より高速な処理のために並列で変換を実行できますか?はい。`xargs -P`またはGNU parallelを使用して、複数のエージェントファイルを同時に処理できます。100以上のエージェントの場合、並列変換により実行時間を数分から数秒に短縮できます。
フロントマターフィールドが存在することを確認するにはどうすればよいですか?変換関数に検証チェックを追加します:`[[ -z "$name" ]] && echo "Missing name field" && exit 1`。出力ファイルを書き込む前に検証を実行してください。
一部のエージェントで変換が失敗した場合はどうなりますか?エラー時にすぐに失敗させるために`set -euo pipefail`を使用します。壊れたファイルをスキップするには`|| continue`でエラー処理を追加します。デバッグのために失敗を別のファイルにログとして記録します。
