Claudeと対話しながらIT作業手順書プロンプトの標準フォーマットを設計した話
はじめに
ITインフラエンジニアとして作業手順書を書く機会は多いのですが、最近は「LLMに渡して実行支援・レポート生成・別ツール変換に使う」ことを前提に手順書を整備したくなってきました。
そこで Claude と対話しながら、XML と YAML を組み合わせた構造化プロンプトの標準フォーマットを設計してみました。本記事はその設計プロセスと、最終的に出来上がったテンプレートを共有するものです。
「LLMに食わせやすい手順書ってどう書くんだ?」と悩んでいる方の叩き台になれば幸いです。
なぜXMLとYAMLを組み合わせるのか
最初に Claude と整理した設計思想がここです。
XMLの役割:意味境界の明示
LLM は「ここからここまでが目的」「ここからは前提条件」といったセクション境界をタグで明示されると誤読が大幅に減ります。Anthropic 公式のプロンプトエンジニアリングガイドでも、長いコンテキストでは XML タグでの区切りが推奨されています。
XML が向いているのは次のような場面です。
- 意味の異なる大きなブロックを並列に並べる
- LLM に「このセクションは厳守事項」と強調する
- 複数の入力資料を1つのプロンプトに混在させる
YAMLの役割:内側のデータ構造化
一方、手順の列挙・パラメータ・検証条件のようなデータ性の強い情報は YAML が圧倒的に書きやすく読みやすいです。
- インデントで階層が表現できる
- リストとキーバリューが自然に書ける
- コメントが書ける
- 後で Ansible や CI/CD 設定への変換が容易
JSON でも代用できますが、コメント不可・引用符地獄になりやすい点で手順書には不向きです。
入れ子の方針
XML タグで囲み、その中に YAML を書く、という入れ子にします。
<section_name>
key: value
list:
- item1
- item2
</section_name>
XML は「役割の宣言」だけを担い、内容のスキーマはすべて YAML で持つ、という分業です。
Markdownと比べてどうなのか — トークン効率と指示理解の精度
ここまで読んで「いやMarkdownで十分じゃないの?」と思う方も多いはずです。私自身も最初そう考えました。結論を先に書くと、トークン効率は若干悪化、指示理解の精度は明確に向上、というトレードオフです。順に分解します。
トークン処理効率の話
純粋なトークン数の比較
同じ内容を表現したときのトークン消費量は、おおむね次の傾向です。
| 形式 | トークン数の目安 | 理由 |
|---|---|---|
| プレーンテキスト | 最小 | 構造を持たないため |
| Markdown | 小〜中 |
# - など軽量記号 |
| YAML | 中 | インデントとキー名 |
| XML | 中〜大 | 開始/終了タグの重複 |
| XML+YAML(本記事) | 大 | XML タグ + YAML キーの両方 |
| JSON | 大 | 引用符・カンマ・括弧 |
DKIM 手順書を3形式で書いた場合のざっくり感覚として、Markdown を 1 とすると、YAML 単体で 1.1〜1.2 倍、XML+YAML で 1.3〜1.5 倍くらいになります。XMLの閉じタグは情報量ゼロなのに必ずトークンを食うのが効率面では明確な負債です。
でも「実効効率」は別の話
トークン数だけ見ると不利なのですが、実務での効率は次の3点で評価すべきです。
1. 1回で正しい答えが出る確率
Markdown で曖昧に書いた手順書は、LLM の解釈ブレで再質問・修正が発生します。再プロンプトが1回でも発生すれば、そちらのトークン消費のほうが圧倒的に大きい。構造化で1発で通る確率が上がるなら、トータルでは安くつきます。
2. キャッシュとの相性
Anthropic API のプロンプトキャッシュを使うと、同じ手順書テンプレートを使い回す場合に大幅にコスト圧縮できます。XML+YAML のように前半が固定で末尾だけ可変な構造はキャッシュヒット率が高く、繰り返し利用するほど効率が逆転します。
3. 出力の構造化が容易
output_format セクションのように出力テンプレートを YAML で渡すと、後処理(パース・自動化)が楽になります。LLM 出力をプログラムで扱う前提なら、入力のトークン増加は十分元が取れます。
指示理解の正確性の話
こちらが本題で、構造化の主目的です。Markdown と比較した優位点を具体的に挙げます。
セクション境界の明示性
Markdown の見出し ## 手順 と、XML タグ <procedure> を比べると、後者のほうが**「ここからここまでが手順」という境界が明確**です。Markdown の場合、見出し階層が深くなると LLM が「どこまでがこのセクションの内容か」を見失うことがあります。XML タグは閉じタグがあるので境界が一意に決まります。
同じ概念の区別
「verification」を Markdown で書くと、
### 手順1
コマンド: `sudo apt install ...`
確認: dpkg -l で opendkim を確認
のように自然文に埋もれます。YAML で書くと、
- id: STEP-01
commands: [...]
verification:
command: dpkg -l | grep opendkim
expected: "ii opendkim"
となり、「これは検証ステップで、expected と command の出力を比較すべきもの」と LLM が機械的に解釈できます。
並列要素の扱い
手順のように同じ構造を持つ要素が並ぶケースで、構造化の優位が顕著です。Markdown で5ステップ書くと、LLM は各ステップから「コマンド」「確認」を自力で抽出しなければなりませんが、YAML なら配列の各要素として均質に扱えます。「STEP-03 の verification だけ実行して」のような指示にも正確に応答できます。
否定形・制約の伝達
constraints セクションの must_not のように「禁止事項」を構造化して渡すと、LLM の遵守率が体感で明確に上がります。Markdown の「※注意:〜しないでください」よりも、独立した must_not: [...] リストのほうが LLM が「これは破ってはいけない制約だ」と認識しやすい。
誤解の代表例(Markdownで起こりがちなこと)
実務で遭遇した誤解パターンです。
-
コードブロック内のコメントを指示と誤認:Markdown のコードブロック内に書いた
# この行は本番では削除のようなコメントを、LLM が手順の一部として実行してしまう -
見出し階層の混乱:
###が続くと LLM がどの上位セクションに属するか取り違える -
箇条書きの曖昧さ:
- 〜するが手順なのか前提条件なのか文脈依存になる
これらは XML+YAML だと構造的に発生しにくくなります。
比較サマリー
| 観点 | Markdown | XML+YAML |
|---|---|---|
| トークン効率(単発) | ◎ | △ |
| トークン効率(キャッシュ前提) | ○ | ◎ |
| 一発で正しく動く確率 | △ | ◎ |
| 指示理解の正確性 | △ | ◎ |
| 人間の可読性(短文) | ◎ | ○ |
| 人間の可読性(長文・複雑) | △ | ◎ |
| 出力の機械処理しやすさ | △ | ◎ |
| 書く手間 | ◎ | △ |
使い分けの推奨
- 雑談・単発の質問・短い指示 → Markdown で十分(むしろ過剰構造化は逆効果)
- 作業手順書・ワークフロー・繰り返し使うプロンプト → XML+YAML が効く
- 超大量バッチ処理でコスト最優先 → トークン効率を測定した上で形式を選ぶ
つまり今回のテーマ(IT 作業手順書)は、**「ミスると本番が落ちる」「同じテンプレートを繰り返し使う」「出力を機械処理する」**という3条件が揃っているので、トークン効率の不利を補って余りあるユースケースです。逆に「今晩の献立教えて」みたいな会話に XML+YAML を持ち込むのは完全に過剰、ということになります。
標準フォーマットの全体構造
提案する標準フォーマットは以下の9セクションで構成します。
| セクション | 役割 | 省略可否 |
|---|---|---|
metadata |
文書のID・版数・対象システム | 必須 |
objective |
目的と成功基準 | 必須 |
preconditions |
前提条件・依存関係 | 必須 |
variables |
環境依存パラメータ | 推奨 |
procedure |
実作業ステップ | 必須 |
rollback |
切り戻し手順 | 推奨 |
output_format |
LLM に求める出力形式 | 任意 |
constraints |
守るべき制約 | 推奨 |
references |
参考資料・関連ID | 任意 |
この順序自体が、人間がレビューする順番にもなっており、LLM が上から読んで文脈を組み立てるのに自然な流れになっています。
完成版テンプレート(DKIM設定を例に)
具体例として、メール認証の DKIM 設定手順をテンプレートに落とし込んだものを示します。{{ }} で囲ったプレースホルダや variables を書き換えれば、他システムにそのまま流用できます。
<procedure_prompt>
<metadata>
```yaml
document_id: PROC-MAIL-DKIM-001
title: DKIM署名の設定手順
version: 1.0.0
created_at: 2026-05-31
author: Infrastructure Team
category: mail / security
target_system: Postfix + OpenDKIM (Ubuntu 24.04)
estimated_duration_min: 60
risk_level: medium # low | medium | high
requires_maintenance_window: true
```
</metadata>
<objective>
```yaml
purpose: |
送信ドメイン認証(DKIM)を有効化し、自社送信メールに
電子署名を付与することでなりすまし対策と到達率改善を行う。
success_criteria:
- opendkim サービスが active (running) であること
- 外部宛テストメールの Authentication-Results に "dkim=pass" が含まれること
- DNS に公開鍵 TXT レコードが伝播していること
```
</objective>
<preconditions>
```yaml
required_access:
- target_host: mail.example.com
user: ops-admin
privilege: sudo
- dns_zone: example.com
provider: Route53
permission: edit
required_knowledge:
- Postfix の基本操作
- DNS TXT レコードの編集
dependencies:
- SPF レコードが既に設定済みであること
- Postfix が正常稼働していること
backout_plan_ready: true
```
</preconditions>
<variables>
```yaml
# 環境ごとに書き換えるパラメータをここに集約
DOMAIN: example.com
SELECTOR: default
KEY_SIZE: 2048
KEY_DIR: /etc/opendkim/keys/example.com
OPENDKIM_PORT: 8891
MILTER_DEFAULT_ACTION: accept
```
</variables>
<procedure>
```yaml
steps:
- id: STEP-01
name: パッケージインストール
type: command
host: mail.example.com
commands:
- sudo apt update
- sudo apt install -y opendkim opendkim-tools
verification:
command: dpkg -l | grep opendkim
expected: "ii opendkim"
rollback:
- sudo apt remove -y opendkim opendkim-tools
- id: STEP-02
name: 鍵ペアの生成
type: command
host: mail.example.com
commands:
- sudo mkdir -p ${KEY_DIR}
- sudo opendkim-genkey -b ${KEY_SIZE} -d ${DOMAIN} -s ${SELECTOR} -D ${KEY_DIR}
- sudo chown -R opendkim:opendkim ${KEY_DIR}
- sudo chmod 600 ${KEY_DIR}/${SELECTOR}.private
verification:
command: ls -l ${KEY_DIR}/
expected: "${SELECTOR}.private と ${SELECTOR}.txt が存在"
- id: STEP-03
name: OpenDKIM 設定ファイル編集
type: file_edit
host: mail.example.com
target_file: /etc/opendkim.conf
changes:
- set: "Domain ${DOMAIN}"
- set: "KeyFile ${KEY_DIR}/${SELECTOR}.private"
- set: "Selector ${SELECTOR}"
- set: "Socket inet:${OPENDKIM_PORT}@localhost"
verification:
command: sudo opendkim -n
expected: "エラー出力がないこと"
- id: STEP-04
name: DNS への公開鍵登録
type: manual
target: Route53 / example.com zone
instruction: |
${KEY_DIR}/${SELECTOR}.txt の内容を確認し、
${SELECTOR}._domainkey.${DOMAIN} の TXT レコードとして登録する。
verification:
command: dig +short TXT ${SELECTOR}._domainkey.${DOMAIN}
expected: "v=DKIM1; k=rsa; p=..."
wait_propagation_min: 10
- id: STEP-05
name: Postfix への milter 連携設定
type: file_edit
host: mail.example.com
target_file: /etc/postfix/main.cf
changes:
- append: "milter_default_action = ${MILTER_DEFAULT_ACTION}"
- append: "smtpd_milters = inet:localhost:${OPENDKIM_PORT}"
- append: "non_smtpd_milters = inet:localhost:${OPENDKIM_PORT}"
- id: STEP-06
name: サービス起動と反映
type: command
host: mail.example.com
commands:
- sudo systemctl enable --now opendkim
- sudo systemctl restart postfix
verification:
command: systemctl is-active opendkim postfix
expected: "active\nactive"
- id: STEP-07
name: 動作確認(外部宛テストメール送信)
type: validation
host: mail.example.com
commands:
- echo "DKIM test" | mail -s "DKIM test" check-auth@verifier.port25.com
verification:
method: 返信メールの Authentication-Results を確認
expected: "dkim=pass"
```
</procedure>
<rollback>
```yaml
trigger_conditions:
- メール送信が完全停止した場合
- dkim=fail が継続する場合
steps:
- sudo systemctl stop opendkim
- sudo postconf -e 'smtpd_milters='
- sudo postconf -e 'non_smtpd_milters='
- sudo systemctl restart postfix
- DNS の TXT レコードを削除(必要に応じて)
```
</rollback>
<output_format>
```yaml
report_template:
- section: 実行サマリ
items: [実施日時, 実施者, 対象システム, 結果]
- section: 各ステップ結果
format: |
STEP-XX [PASS/FAIL]
実行コマンド:
出力:
判定根拠:
- section: 検出された問題
- section: 残課題・推奨事項
```
</output_format>
<constraints>
```yaml
must:
- 各ステップの verification を必ず実行し結果を記録すること
- 失敗時は即座に rollback セクションを参照すること
- 本番反映前にステージング環境で実行済みであることを前提とする
must_not:
- 鍵ファイルのパーミッションを 644 以上に緩めないこと
- DNS 伝播確認前に Postfix を再起動しないこと
```
</constraints>
<references>
```yaml
related_procedures:
- PROC-MAIL-SPF-001
- PROC-MAIL-DMARC-001
external_docs:
- https://datatracker.ietf.org/doc/html/rfc6376
```
</references>
</procedure_prompt>
各セクションの設計意図
テンプレートを単純コピーするのではなく、設計意図を理解しておくと運用で迷いません。
metadata — 同定と運用情報
document_id を ID 体系(例:PROC-<領域>-<対象>-<連番>)で振っておくと、references から相互参照できます。risk_level と requires_maintenance_window は、LLM に「丁寧に確認しながら進める必要がある手順か」を伝える役目もあります。
objective — 目的と成功基準を分ける
purpose(何のためか)と success_criteria(完了をどう判定するか)を分けるのが肝です。LLM に作業報告を書かせる場合、success_criteria が判定軸として直接使われます。
preconditions — 着手前のチェックリスト
required_access でアカウントや権限を明示し、dependencies で「先に終わっていなければならない別手順」を書きます。LLM にレビューさせると「前提が満たされているか確認する質問」を返してくれるようになります。
variables — 環境依存値の集約
ここを別ファイル化・別環境化することで、同じ手順書を本番/ステージング/開発で使い回せるようになります。${KEY_DIR} のようにステップ内で参照しておけば、書き換え漏れも防げます。
procedure — 手順の構造化
最も重要なセクションです。各ステップに必ず以下を持たせます。
-
id: 一意な識別子(報告書での参照用) -
name: 人間向けの短いタイトル -
type: ステップの種別 -
commands/changes/instruction: 実際の操作内容 -
verification: 完了確認方法 -
rollback(任意): そのステップ単位の戻し方
type は次のように使い分けています。
| type | 意味 |
|---|---|
command |
コマンド実行(冪等にできるものが望ましい) |
file_edit |
設定ファイル変更 |
manual |
人手や GUI での作業 |
validation |
動作確認のみ |
approval |
承認待ち(変更管理で必要な場合) |
LLM に「type: manual のステップは自動実行しないでください」と伝えるだけで、誤操作リスクが下がります。
rollback — 全体切り戻し
ステップごとの rollback とは別に、全体としての切り戻し条件と手順を独立セクションに置きます。trigger_conditions を明示しておくのが重要で、「どうなったら戻すのか」が曖昧だと現場で迷います。
output_format — LLM出力の型を縛る
LLM に作業報告書を生成させたいときに、ここで雛形を指定します。report_template のような YAML で構造を渡すと、Markdown 混在の自由フォーマットより一貫した出力が得られます。
constraints — 厳守事項
must と must_not を明示します。LLM は禁止事項のリストに対してかなり忠実に従ってくれるため、危険な操作を防ぐ重要な防波堤になります。
references — 関連性の維持
別の手順書 ID や外部仕様書を並べておくと、LLM が「関連手順を読みに行くべきか?」を判断する材料になります。
カスタマイズの方法
標準フォーマットをそのまま使う必要はありません。プロジェクトに応じてセクションを足し引きします。よくある拡張パターンを紹介します。
パターン1:セキュリティレビュー観点を追加
セキュリティ要件が厳しい現場では、<security_considerations> セクションを足します。
<security_considerations>
```yaml
data_classification: confidential
affected_credentials:
- opendkim private key
audit_log_required: true
pii_involved: false
</security_considerations>
### パターン2:変更管理ワークフローの統合
`<approval_workflow>` を加えると、変更管理(ITIL系)との接続が明確になります。
```xml
<approval_workflow>
```yaml
change_ticket: CHG-2026-00123
approvers:
- role: System Owner
name: tanaka@example.com
- role: Security Officer
name: yamada@example.com
scheduled_window:
start: 2026-06-15T22:00:00+09:00
end: 2026-06-16T01:00:00+09:00
</approval_workflow>
### パターン3:事後確認の追加
実施から数日後に確認すべき項目を `<post_implementation_check>` に書いておくと、報告書テンプレートとの整合が取りやすくなります。
```xml
<post_implementation_check>
```yaml
schedule_after_days: 7
items:
- DMARC レポートで dkim=pass の比率が 95% 以上
- ログに opendkim のエラー出力がない
</post_implementation_check>
### パターン4:変数の階層化
環境別に切り替えたいときは `variables` を入れ子にします。
```yaml
variables:
common:
SELECTOR: default
KEY_SIZE: 2048
environments:
production:
DOMAIN: example.com
KEY_DIR: /etc/opendkim/keys/example.com
staging:
DOMAIN: stg.example.com
KEY_DIR: /etc/opendkim/keys/stg.example.com
LLM に「production 環境で実行する想定で書き出して」と指示すれば、適切に展開してくれます。
パターン5:複数手順書のカタログ化
組織で多数の手順書を運用する場合、メタ的なカタログを別ファイルで持ちます。
# procedures-catalog.yaml
procedures:
- id: PROC-MAIL-SPF-001
file: mail/spf.xml
tags: [mail, security]
- id: PROC-MAIL-DKIM-001
file: mail/dkim.xml
tags: [mail, security]
- id: PROC-MAIL-DMARC-001
file: mail/dmarc.xml
tags: [mail, security]
LLM にカタログごと食わせて、「メール認証関連の手順を順序立てて実施する計画を作って」のような上位指示が出せます。
運用上の工夫
実際にこのフォーマットを運用する上での実践 Tips です。
Gitで版管理する
手順書はコードと同じく Git 管理します。document_id をディレクトリ構造に対応させると見通しが良くなります。
procedures/
├── mail/
│ ├── PROC-MAIL-SPF-001.xml
│ ├── PROC-MAIL-DKIM-001.xml
│ └── PROC-MAIL-DMARC-001.xml
├── network/
└── catalog.yaml
PR レビューで「success_criteria が観測可能か」「rollback が書かれているか」といった観点を機械的にチェックできます。
LLM呼び出し時のラッパープロンプト
手順書本体に加えて、外側を包むラッパープロンプトを用意します。
あなたは熟練のインフラエンジニアです。
以下の <procedure_prompt> に従って作業を進めてください。
ルール:
- type: manual のステップは自動実行せず、ユーザーに作業依頼の文面を出力してください。
- 各ステップは verification を実行し、expected と一致しなければ停止して報告してください。
- 失敗時は constraints と rollback セクションを参照してください。
- 最終的に output_format に従ったレポートを出力してください。
<procedure_prompt>
... (本体) ...
</procedure_prompt>
これにより、同じ手順書を「実行モード」「ドライランモード」「レビューモード」など複数モードで使い分けられます。
スキーマ検証
YAML パートに対しては JSON Schema を書いておき、CI で構文と必須項目をチェックすると、手順書の品質が劣化しません。procedure.steps[].verification 必須、などのルールを機械的に保証できます。
ナレッジとしての循環
実施後の報告書(LLM が生成したもの)を Git にコミットし、次回以降の手順書改善にフィードバックする運用にすると、手順書が生きたドキュメントになります。
落とし穴と対策
実際に運用してみて出会いやすい問題と対策をまとめます。
YAMLインデントの罠
XML タグの中に YAML を埋めると、エディタによってはインデントが乱れます。YAML パートのインデントはタブを使わずスペースで統一し、保存時に自動整形させるのが安全です。
XML タグ名の揺れ
<rollback> と <roll_back> のような揺れがあると LLM の解釈精度が落ちます。タグ名は本記事のテンプレートに合わせて統一し、組織内で辞書化しておきましょう。
機密情報のハードコード
variables にパスワードや API キーを直接書かないでください。vault_ref などの参照キーに留めるのが原則です。
variables:
DB_PASSWORD_REF: vault:secret/data/mail/dkim#password
LLMの過剰実行
「進めて」と一言で指示すると、LLM が manual や approval のステップまでスキップして報告してしまうことがあります。ラッパープロンプトで step 単位の確認を必須化してください。
大きすぎる手順書
1ファイルが大きくなりすぎたら分割します。PROC-MAIL-DKIM-001-prepare、-execute、-verify のように分け、上位の手順書から参照するスタイルが扱いやすいです。
Claudeと対話して設計してみての所感
最後に、この標準フォーマットを Claude と対話しながら設計してみての気付きを共有します。
「LLMに食わせやすい構造」と「人間が書きやすい構造」は、思ったほどズレないということです。XML で意味境界を切り、YAML でデータを書く、というハイブリッド構造は、人間がレビューするときにも見通しが良く、結果として両者にとって扱いやすい形になりました。
もう一つは、LLM 自身に「自分が読みやすい構造」を提案させると設計が早いということです。本記事のフォーマットも、最初から完成形を狙わず、「DKIM を例にやってみて」「これを標準化して」「ここをカスタマイズしたい」と段階的に詰めていきました。設計対象が「LLM 向けの何か」であるとき、設計パートナーとして LLM 自身を使うのは合理的だと感じます。
まとめ
XML+YAML のハイブリッド構造で作業手順書プロンプトを設計する利点をまとめます。
- XML で意味境界を明示し、LLM の誤読を抑える
- YAML でデータ構造を表現し、人間にも機械にも読みやすくする
-
verificationとrollbackを全ステップに紐づけることで安全性を担保する -
variablesの集約で環境横断の再利用が可能になる - セクション単位の足し引きで組織要件にカスタマイズできる
この標準フォーマットは、DKIM 以外にも、ネットワーク機器のコンフィグ変更、Kubernetes クラスタのアップグレード、データベース移行など、ほぼ任意のインフラ作業に流用できます。
「LLM 時代の Runbook」をどう書いておくと未来の自分やチームを救えるか、その出発点として本記事のフォーマットを叩き台にしていただければ幸いです。
Discussion