Skip to main content

promptstrata

カスタマーサポート AI エージェントのシステムプロンプトを、5枚の YAML レイヤーから1本の文字列に合成するライブラリです。

カスタマーサポートのシステムプロンプトは、要件を継ぎ足すたびに1本の巨大な文字列になっていきます。禁止事項、話し方のルール、電話とチャットでの違い、返金のような業務手順が同じファイルに混ざり、誰も全体を把握できなくなります。担当が違う人が同じファイルを編集すれば衝突しますし、電話向けの制約をチャットにも誤って持ち込む、といった事故も起きます。promptstrata は、この1本の文字列を「誰として振る舞うか」「用語」「禁止事項」「チャネル」「業務手順」の5レイヤーに分けて YAML で管理し、必要な組み合わせだけをビルド時に合成します。LLM 自体は呼ばず、文字列を組み立てるだけのライブラリです。

インストール

pip install promptstrata
uv add promptstrata

最小の使い方

from promptstrata import PromptSet

ps = PromptSet.load("examples/sorairo-pay")
built = ps.build(
    channel="voice",
    procedures=["refund"],
    vars={"company_name": "ソライロ決済株式会社"},
)

system_prompt = built.text  # そのままシステムプロンプトに渡す
print(built.fingerprint)  # 例: "a817c6ad1e90"。応対ログに残してどのプロンプトか特定する

5つのレイヤー

レイヤー ファイル 何を書くか 個数
ロール role.yaml 誰として振る舞うか(identity)、あるべき振る舞い(principles)、話し方(tone) ファイルにつき1つ
語彙 vocabulary.yaml 扱うサービス名・用語(canonical・読み・別名・音声認識の誤変換) terms を複数件
ガバナンス governance.yaml 禁止事項(prohibitions)、引き継ぎ条件(escalation)、範囲外の断り文句(out_of_scope) 各項目を複数件
チャネル channels/<name>.yaml 媒体ごとの制約(constraints)と表記ルール(formatting) チャネルの数だけファイル
手順 procedures/<name>.yaml 業務手順の発動条件(trigger)、手順(steps)、逸脱を防ぐ制約(guardrails) 手順の数だけファイル

すべてのレイヤーは任意です。ファイルが無いレイヤーは無いものとして扱われます。

ディレクトリ構成の例

examples/sorairo-pay は、架空のコード決済サービス「ソライロペイ」のカスタマーサポート窓口を題材にしたサンプルです。実在の企業・サービスとは関係ありません。

examples/sorairo-pay/
├── role.yaml
├── vocabulary.yaml
├── governance.yaml
├── channels/
│   ├── voice.yaml
│   └── chat.yaml
└── procedures/
    └── refund.yaml

各レイヤーの YAML 例

以下は examples/sorairo-pay/ からの抜粋です。架空のサービス「ソライロペイ」を題材にしたサンプルで、実在の企業・サービスとは関係ありません。

role.yaml

${company_name} はビルド時に vars で埋める変数です。$company_name とも書けますが、日本語の文中では直後の文字と続けて書ける ${...} のほうが確実です。本文に $ をそのまま出したい場合は $$ と書きます。

vars に顧客の個人情報を入れないでください。 企業名・窓口名・営業時間のような、その窓口で固定の値だけに使います。氏名を入れると built.text が顧客ごとに変わり、fingerprint も顧客ごとに一意になるため「どのポリシーで応対したか」を横断で集計できなくなります。システムプロンプトのログも個人情報を含む扱いになり、保管と共有の条件が変わります。

identity: |-
  あなたは${company_name}が提供するソライロペイのカスタマーサポート窓口担当です。
  ソライロペイアプリ、ソライロペイ残高、ソライロポイントに関する問い合わせに対応します。
principles:
  - id: verify_before_payment
    text: 返金や重複請求など金銭が動く申告は、注文番号や取引日時などの裏付けを確認してから対応する
tone: 丁寧だが事務的になりすぎない。落ち着いた低めのトーンで、誠実に淡々と話す。

vocabulary.yaml

misheard は音声認識が実際に誤変換しそうな表記です。ここに載せることで、モデルが会話履歴中の誤変換を正しい語に読み替えられるようにします。

terms:
  - canonical: ソライロペイ
    reading: ソライロペイ
    summary: コード決済サービス。バーコードやQRコードで加盟店にて支払いができる。
    aliases:
      - そらいろペイ
      - sorairo pay
    misheard:
      - 空色ペイ
      - ソライロペー
      - ソラエロペイ

governance.yaml

prohibitions:
  - id: no_smalltalk
    text: 雑談を始めない。世間話や不要な相槌を返さず、要件の解決に集中する
escalation:
  - when: 本人確認が取れない
    action: 有人窓口(電話サポート)に引き継ぐ
    say: 本人確認ができないため、担当者にお繋ぎします
out_of_scope: ソライロペイ以外のサービスに関するお問い合わせは担当外のためご案内できません。各サービスの窓口にご確認ください。

channels/voice.yaml と channels/chat.yaml

同じ「返金の手順を伝える」場面でも、チャネルによって制約は変わります。voice には「URL を読み上げない」を必ず入れ、chat には入れません。

# channels/voice.yaml
constraints:
  - id: no_url_readout
    text: URLやメールアドレス、記号列を読み上げない。案内が必要な場合はSMSでURLを送る
  - id: two_sentences_max
    text: 1回の発話は2文以内にまとめる
formatting:
  金額: 金額は「1,000円」ではなく「せんえん」のように読み上げの形で伝える
# channels/chat.yaml
constraints:
  - id: url_ok
    text: URLはそのまま貼ってよい
  - id: numbered_steps
    text: 手順は番号付きの箇条書きにする
formatting:
  リンク: URLはそのままの形式で貼り付ける

procedures/refund.yaml

trigger: 返金、返品、二重請求の申告を受けたとき
steps:
  - 注文番号または取引日時、支払い方法を確認する
  - 本人確認を行う(本人確認ツールに登録氏名または生年月日を照会し、一致の結果を得る。顧客が名乗っただけの氏名・生年月日は本人確認の完了とみなさない)
guardrails:
  - 金額を独断で変更・確約しない。システムで確認できた金額のみを伝える

合成の規則

節の順序は次のとおりです。

優先順位 → 役割 → 語彙 → 手順 → チャネル → 禁止事項

節の並びと、制約の強さの優先順位は別です。優先順位はこの順で強くなります。

語彙 < 役割 < 手順 < チャネル < 禁止事項

強い制約ほど後ろに置いたうえで、冒頭でもこの優先順位を宣言します。モデルは長いプロンプトの末尾を重く扱う傾向があるため、順序と優先順位の宣言の両方で衝突時の勝ち負けを明示します。

レイヤーはすべて任意です。ファイルが無ければその層は無いものとして扱い、空の見出しは残しません。ただし --channel voice のように明示したチャネルのファイルが無い場合はエラーにします。存在しないレイヤーを暗黙に省くことと、指定を間違えたことは区別する必要があるためです。

会話中に判明したことは書き戻さない

built.text はビルド時に一度決まる固定の文字列です。会話が進んでも作り直さず、そのままシステムプロンプトとして渡してキャッシュさせてください。

本人確認が済んだ氏名や、契約から引いた注文番号のような会話中に確定する事実は、promptstrata の合成対象ではありません。システムプロンプトの末尾に足さないでください。

tools ──▶ system ──▶ messages [過去のターン …… 最新ターン]

プロンプトキャッシュはこの順の前方一致で効き、ある段が変わるとそれ以降の段のキャッシュも落ちます。Anthropic の仕様では "Changes at each level invalidate that level and all subsequent levels" と明記されています(Prompt caching)。OpenAI も前方一致です。つまりシステムプロンプトの末尾を毎ターン書き換えると、それ以降の会話履歴のキャッシュが丸ごと落ちます。会話が伸びるほど再計算する量が増え、音声チャネルではそのままターンごとの応答遅延になります。

事実を反映したい場合は messages 側に足してください。整形と配線は利用側で組みます。基盤ごとに経路が違うためです。

基盤 事実を足す経路
Pipecat LLMMessagesAppendFrame でメッセージ履歴に追記する(Context Management。システムメッセージの書き換えは信頼性が低いと明記されている)
LiveKit Agents chat context の末尾に追記する(Anthropic プラグイン)
Retell・Vapi dynamic variables かツールの戻り値で渡す

そもそも、客が口頭で名乗った氏名はモデルが会話履歴からすでに読めています。書き戻す必要があるのは「ツールで裏が取れた」という印が要る事実だけです。

role.yaml や governance.yaml に書くのは、事実そのものではなく事実の扱い方です。「確認済みと明示された事実だけを既知として扱う」「複数ある場合は会話履歴の最後のものを最新とする」といった規律をレイヤーに書いておけば、事実がどこから来ても振る舞いは揃います。

ただし、これはモデルへの指示であって強制ではありません。 本人確認が済んでいない状態で返金の操作が実行されるのを確実に止めたい場合は、ツール呼び出しの可否を判定する実行時のガードレール(NeMo Guardrails・Guardrails AI・OpenAI Agents SDK など。このライブラリの対象外)で止めてください。プロンプトは会話を導く指示であって、制御ではありません。

CLI

promptstrata build examples/sorairo-pay --channel voice --procedure refund --var company_name=ソライロ決済株式会社
promptstrata lint examples/sorairo-pay

build は合成したプロンプトを標準出力に書きます。lint は YAML のスキーマ違反に加えて、id の重複(レイヤー横断)や aliases の衝突(同じ別名が2つの canonical に属する)を検出します。

やらないこと

やらないこと 代わりに
STT の keyterm・カスタム語彙の出力 STT 側の設定で持つ
プロンプトのレジストリ・Web UI・版管理サーバー git。必要なら Langfuse
実行時ガードレール(出力の検査とブロック) NeMo Guardrails / Guardrails AI / OpenAI Agents SDK
eval・A/Bテスト promptfoo
LLM の呼び出し 呼ばない。文字列を返すだけ
テンプレートエンジン string.Template(標準ライブラリ)

バージョンとリリース

版は pyproject.toml の version だけです。SemVer に従いますが、0.x のあいだは minor(例: 0.2.0)で破壊的変更が入ることがあります。1.0 以降は破壊的変更を major に限ります。

公開 API として扱うのは、PromptSet / BuiltPrompt / SourceRef などの型とそのフィールド・メソッド、例外(PromptStrataError / LayerFileError / BuildError)、レイヤーの型(Role / Vocabulary / Governance / Channel / Procedure)、レイヤー YAML のスキーマ、CLI のサブコマンドとオプション(build / lint / --channel / --procedure / --var)、そして合成後のプロンプト本文の文面です。文面を変えると built.fingerprint も変わり、過去の応対ログと突き合わせられなくなるため、意味が変わる変更は破壊的変更として扱います。誤字の修正のように意味が変わらない変更は patch で構いません。理由は docs/adr/0009-versioning.md を参照してください。

変更履歴は CHANGELOG.md に Keep a Changelog 形式で記録します。

リリース手順(メンテナ向け)は次のとおりです。

  1. CHANGELOG.md の ## [Unreleased] の中身を新しい版の節に移し、日付を入れます。
  2. pyproject.toml の version を上げます。
  3. uv sync して uv.lock を更新し、コミットします。
  4. git tag vX.Y.Z を打ち、git push origin main --tags します。
  5. .github/workflows/release.yml が CI と同じ検査を回してから PyPI に公開します(タグと pyproject.toml の version が食い違う場合は失敗します)。

Metadata

Release files for promptstrata 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for promptstrata 0.1.0
File Size Uploaded
promptstrata-0.1.0.tar.gz 74.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for promptstrata 0.1.0
File Interpreter ABI Platform
promptstrata-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 94.4 kB

Release files / promptstrata-0.1.0.tar.gz

Download URL promptstrata-0.1.0.tar.gz
Size 74.7 kB
Tags Source
SHA-256 checksum
How to use checksums
eac856eb8d169b6c2c6e781d33f0c76d8c50b30a40b64e69df80e53aca5bd31a
BLAKE2b-256 checksum
How to use checksums
1c05b7cd300aab4f07a3a0a694c4b1565f4babef526af2acc6379ae87fdc5363
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 23, 2026.

Transparency log

Release files / promptstrata-0.1.0-py3-none-any.whl

Download URL promptstrata-0.1.0-py3-none-any.whl
Size 19.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ee6df94c22874b70dedda38c796851e20ec36c14abe69df50f2301425b1257c6
BLAKE2b-256 checksum
How to use checksums
b641fee7f9aab5d11232f05e37cea1a8c363c04bf0cc0fa667cb8fd8b203cb05
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page