「この顧客の注文だけを調べて」とAIに頼んでも、実際のAPIが別の顧客の注文を返せるなら、指示文だけが最後の壁になります。問い合わせ対応や営業支援のエージェントでは、モデルの回答だけでなく、外部サービスへ送る引数も制御する必要があります。
そのためのPythonライブラリがCharterです。2026年10月29日公開の0.6.0リリースでは、顧客IDなどをアプリ側から毎回渡すFromContextが追加されました。本記事ではこの新機能を中心に、架空の注文を使った7項目の動作確認と、実務に組み込む際の限界を解説します。
Charter 0.6.0を実際に実行し、HTTP通信をモックへ置き換えて許可・拒否を確認しました。LLM、実際の顧客アカウント、実APIには接続していません。モデルが間違える確率や、本番システム全体の安全性を測った結果ではありません。
Charterとは:AIが呼ぶ道具の入力欄に、業務ルールを置く
Charterは、エージェントが外部APIへ送る1回のリクエストを、Pythonの型付きモデルとして宣言するライブラリです。Pydanticという入力検証ライブラリで、項目、型、許される値、独自の判定を定義します。エージェントが出した引数は、その検査を通ってからHTTPリクエストになります。公式READMEでは、任意のHTTP APIを対象とする仕組みとして説明されています。
| 層 | 決めること | 注文検索での例 |
|---|---|---|
| 認証・アプリ側 | 誰が操作しているか | ログイン済みの顧客IDをセッションから取得 |
| Charterと開発者の検証ルール | 今回の呼び出しで許される入力か | 注文の所有者と顧客IDを照合 |
| APIサーバー側 | その要求を実際に許可するか | サーバーでも注文へのアクセス権を確認 |
| LLM | 渡された道具で何を依頼するか | 調べたい注文IDを引数にする |
Charterが自動的に顧客の権限を調べてくれるわけではありません。注文の所有者はどこから調べるのか、何を許可するのかは開発者が実装します。また、このライブラリを通らない別のHTTPツールやコード実行経路があれば、その経路まで保護するものではありません。
0.6.0の新しさ:顧客IDをモデルの引数から切り離す
FromContextを付けた項目は、モデルへ見せる入力スキーマから外れ、アプリが呼び出しごとのcontextで値を渡します。必須の値が欠ければContextErrorになり、ルールを実行する前に止まります。顧客IDを自然言語で「変えないで」とお願いするのではなく、モデルが埋める欄から除く設計です。
class GetOrder(BaseModel): order_id: Annotated[str, Path()] customer_id: Annotated[str, FromContext()]
@model_validator(mode="after") def check_owner(self): if OWNERS.get(self.order_id) != self.customer_id: raise ValueError("この顧客の注文ではありません") return self
get_order.invoke( {"order_id": "order-a"}, context={"customer_id": "customer-a"},)ここではorder_idはモデルが指定でき、customer_idはアプリ側が指定します。ただし、アプリが受け取った未検証の文字列をそのままcontextへ渡せば、信頼できる情報にはなりません。誰の依頼かを認証で確定するところまでが、アプリの責任です。
FromContextだけを付けた項目は検証用に使われ、HTTPの送信項目にはなりません。QueryやBodyなどの送信先マーカーも併記すると、contextの値をその場所へ送れます。この違いは公式のFromContextテストでも確認できます。今回の教材は「判定にだけ使う」構成です。
| 0.6.0の追加点 | 実務上の意味 |
|---|---|
| FromContextと呼び出しごとのcontext | 顧客IDや検証済み状態などをホストアプリから渡す |
| AnyOfとmissing_scopes | APIが複数の権限を受け付ける場合の必要権限を表現・照合する |
| 資格情報の種類とInsufficientScope | トークンの種類や権限不足を区別する。権限を自動追加する機能ではない |
| Tool.derived(scopes=...) | 派生ツールが求める権限を調整する。これだけで呼び出し内容を制限するわけではない |
これらはリリースノートに記載された差分です。権限の名前を正しく宣言することと、実際に渡す引数を制限することは別の仕事です。顧客IDを固定するだけでなく、操作対象、件数、送信先など、業務で必要な条件を実装します。
日本の業務で使うなら:まず読み取り専用の問い合わせ対応から
| 試しやすい用途 | アプリ側が渡す情報 | 開発者が検証する例 |
|---|---|---|
| 顧客からの注文状況確認 | 認証済み顧客ID | 注文が本人のものか |
| 社内の案件照会 | 所属部署・担当者ID | その案件を参照できるか |
| サポートチケットの検索 | 契約テナントID | 他テナントのチケットが混ざらないか |
表は導入案であり、既存導入の成果ではありません。最初は一つの読み取り専用APIで、「正常に通るケース」と「必ず止めたいケース」を列挙すると境界を確かめやすくなります。注文の変更やメール送信などへ広げる際は、承認、二重実行防止、操作ログ、API側の権限を別途設計します。
日本語でも、TDSEの解説はAPIの引数・件数・送信先などの検証を課題に挙げています。今回の検索範囲では、Charter 0.6.0のFromContextを日本語で試す具体的な解説は確認できませんでした。一般的な権限設計の解説がない、あるいは日本初という意味ではありません。
実際に試す:外部APIもLLM料金も使わない7項目の教材
実行用Pythonファイル、依存バージョン一覧、今回の期待出力を用意しました。架空の注文だけを使い、respxというHTTPモックで通信を置き換えます。外部API用のキーを取得する必要はありません。
python3 -m venv .venvsource .venv/bin/activatepython -m pip install -r requirements.txtpython charter_demo.pypy -3 -m venv .venv.\.venv\Scripts\python.exe -m pip install -r requirements.txt.\.venv\Scripts\python.exe charter_demo.py確認環境はmacOS・Python 3.12、charter-ai 0.6.0、respx 0.22.0。確認日は2026年10月30日です。Charterの実装を動かし、送信の直前までを検査していますが、接続先は実サーバーではなくHTTPモックです。正しいケースではモックに1回到達し、拒否ケースでは到達回数が増えないことまで確認しました。
| 確認項目 | 期待する結果 | 今回の結果 |
|---|---|---|
| モデル用スキーマ | customer_idが入力項目にない | 確認 |
| 本人の注文 | モックに1回到達 | 確認 |
| 別顧客の注文 | 送信前にToolValidationError | 確認 |
| 引数で顧客IDを偽装 | 送信前にToolValidationError | 確認 |
| アプリが顧客IDを渡し忘れ | 送信前にContextError | 確認 |
| 存在しない注文 | 送信前にToolValidationError | 確認 |
| 判定用の顧客ID | URL・ヘッダー・本文に含まれない | 確認 |
最後に表示するegress mapは、モデルに見せる項目と、contextで渡す項目を一覧にしたものです。これをコードと一緒に保存すると、ツールの変更で操作可能な範囲が広がっていないかレビューできます。ただし、一覧だけで独自の検証コードが正しいと証明できるわけではありません。拒否ケースのテストも残します。
demo_order_get (GET orders/{order_id}) visible to the model (1): + order_id withheld (1): - customer_id [context] <- context['customer_id']利用条件と限界:無料のライブラリでも、連携先は別
| 項目 | 確認内容 |
|---|---|
| ライセンス | Apache-2.0。Charter本体はオープンソース |
| 実行環境 | Python 3.10以上。今回の実測はmacOS。Windows/Linuxでの動作は未実測 |
| 言語 | 開発者向けPython。今回の日本語の説明・エラー文は動作確認済み。日本語GUIを備えるサービスではない |
| 費用 | Charter自体の呼び出し従量料金はない。利用するLLM・外部API・ホスティングの費用は別 |
| 動作場所 | 自分のプロセス内で動作。ローカルLLM専用ではなく、モデルが返したツール引数を検査する層 |
| 今回の試用範囲 | LLMなし・実APIなしのHTTPモック検証。実際のOAuth接続やマルチテナント運用は未検証 |
公式READMEはプロキシやテレメトリーを使わないと説明しています。ただし、Charterで外部APIを呼べばリクエストはそのAPIへ送られます。「自分のプロセスで動く」ことと「顧客データが外部へ出ない」ことは同じではありません。どの項目をどこへ送るかは、連携先ごとに確認します。
0.6.0の制限事項では、複数回の呼び出しをまとめる処理、再試行やページ送りのループはエージェント側の仕事とされています。ファイルのmultipartアップロード、リクエスト署名、ストリーミングも未対応です。また、Modeはモデルに見せる項目の切り替えであり、誰が呼び出せるかという認可ではありません。
承認用の専用マーカーなどはロードマップにあり、現時点の完成機能と混同できません。人の承認が必要な業務では、アプリ側で承認を取得・検証し、その状態を信頼できるcontextとして渡す設計が必要です。戻ってきたデータをLLMへ何でも渡す問題や、プロンプトインジェクション全般をこれ一つで解決するものでもありません。
導入を頼むときの指示文:先に禁止ケースを決める
自社が管理する読み取り専用の注文照会APIにCharter 0.6.0を使う設計案を作ってください。まだ本番接続や設定変更はしないでください。
モデルが指定してよい項目と、認証済みセッションからホストが渡す項目を分けてください。顧客IDはFromContextで受け、モデル引数や未検証のリクエストから流用しないでください。注文の所有権照合はDBとAPI側の認可も含めて設計し、他のHTTPツールで迂回できないかも確認してください。
正常、他顧客、顧客ID偽装、context欠落、存在しないID、期限切れの権限について、期待結果と送信回数をHTTPモックで検証する案を出してください。実APIキー、個人情報、構成全文は要求しないでください。egress mapとテストをレビュー対象にし、未対応機能と本番で追加確認が必要な項目を明記してください。ローカルのシェルコマンドを確認するShellfirmの記事とは、守る対象が異なります。Charterは外部APIへ渡す項目の制御です。LLMのプロンプト、実行環境、APIの認可をそれぞれ設計し、どの層のテストをしたのかを分けて記録すると導入判断がしやすくなります。
出典確認:2026年10月30日16時台JST。GitHubの0.6.0公開時刻は10月29日05:25:55 UTC(14:25:55 JST)、PyPIの0.6.0のwheel公開は同日06:42:15 UTC(15:42:15 JST)です。製品全体の初ローンチではなく、0.6.0の重要更新として紹介しています。