NextPDF Connect でのヒューマンインザループによるファイル出力
ヒューマンインザループ(HITL)確認ゲートは、意図しないファイルシステムへの書き込みを防ぎます。output_pdf が file_path を指定して呼び出されると、ゲートはその呼び出しをインターセプトし、ファイルを書き込む代わりに単回利用のチャレンジを返します。人間が承認し、エージェントがトークンを添えて再度呼び出して初めて、ファイルが書き込まれます。Base64 出力(file_path なし)はゲートされません。
インストール
「インストール」という見出しのセクションcomposer require nextpdf/serverトランスポートをバインドします。デフォルトでは、output_pdf のリスクレベルは Approval Required です。
概念の概要
「概念の概要」という見出しのセクションゲートは実効リスクレベルを評価します。これは、設定や呼び出し元のアイデンティティに基づくオーバーライドを適用した後に残るレベルです。Approval Required のツールでは、動作は次のとおりです。
- base64 モード —
output_pdfをfile_pathなしで呼び出すと Review に格下げされ、確認なしで許可されます。ファイルシステムへの副作用は発生しません。 - file モード —
output_pdfをfile_pathを指定して呼び出すと Approval Required のままです。ゲートはツール名にバインドされた単回利用のトークンを保存し、チャレンジを返します。対象ファイルがすでに存在する場合、チャレンジのテキストには上書き警告が含まれます。トークンは一定の時間枠が経過すると失効します。
どのトランスポートでも、ゲートの結果は通常のレスポンスです。承認待ちはワークフローの一時停止であり、トランスポートの失敗ではありません(PSR-18 §3、PSR-18 §p2)。
API サーフェス
「API サーフェス」という見出しのセクション| ツール | 役割 | リスクティア |
|---|---|---|
create_pdf | セッションを開く | Safe |
set_font、add_text | コンテンツの構築 | Caution |
output_pdf(base64) | インラインで返却。ゲートなし | Review |
output_pdf(file) | ディスクへ書き込み。ゲート対象 | Approval Required |
ツールカタログが正式なカタログです。利用可能なツールは、インストール済みのティアによって異なります。リスクのはしごとゲートはHITL リスクティアのリファレンスで定義されています。
コードサンプル — クイックスタート
「コードサンプル — クイックスタート」という見出しのセクションcreate_pdf→set_font/add_textでコンテンツを構築します。file_pathを指定してoutput_pdfを呼び出す → ゲートがチャレンジのエンベロープを返します(ファイルは書き込まれません)。- チャレンジを人間に中継します。
- 承認されたら、同じ引数に加え、チャレンジで返されたトークンを設定した
_confirmation_tokenを付けてoutput_pdfを再度呼び出す → ファイルが書き込まれ、セッションは破棄されます。
コードサンプル — 本番運用
「コードサンプル — 本番運用」という見出しのセクション- チャレンジは常にワークフローの一時停止として扱います。ループ内で再試行したり、トークンを捏造したりしてはいけません。
- トークンは単回利用で、ツール名にバインドされています。
output_pdf向けに発行されたトークンで、別のツールを認可することはできません。 - 人間が拒否した場合は、再度呼び出してはいけません。ファイルを書き込まずにバイト列を取得するには、代わりに
output_pdfを base64 モードで呼び出します。そのためにはセッションがまだ存在している必要があるため、必要になると見込まれる場合は、ゲート対象の呼び出しでdestroy: falseを使用します。 - 承認前にトークンが失効した場合、ゲートは新しいチャレンジを発行します。新しいチャレンジを中継します。
エッジケースと落とし穴
「エッジケースと落とし穴」という見出しのセクション- トークンが一度も提供されない。 操作は保留されたままです。人間が承認したうえで、中継して再度呼び出す必要があります。
- 失効したトークン。 新しいチャレンジが発行されます。そのチャレンジを再度中継します。
- 誤ったツール。 トークンはツールにバインドされています。別のツールへの再利用は失敗し、新しいチャレンジが発行されます。
- 絶対パスではないパス。 無効なパスとしてゲートの手前で拒否されます。
- 書き込み権限なし/ディスク満杯。 これは承認後に発生するファイル書き込みの失敗です。エラーとして表面化させます。やみくもに再試行してはいけません。
- 再呼び出しの前にセッションが破棄された。 前回の
output_pdfがdestroy: trueを使用していた場合、セッションは消失しています。承認のラウンドトリップを見込む場合はdestroy: falseを使用します。
パフォーマンス
「パフォーマンス」という見出しのセクションゲートにより、トークンストアのルックアップと、人間による承認のためのラウンドトリップが追加されます。ウォールタイムを支配するのは人間側の待ち時間であり、サーバーではありません。プロファイルは structural です。
セキュリティに関する注意
「セキュリティに関する注意」という見出しのセクションゲートは、エージェントとサーバーのファイルシステムとの境界です。ファイル書き込みは取り消せない副作用であり、人間が認可すべきものなので、このゲートが存在します。トークンは単回利用で、ツールにバインドされ、時間制限があります。クライアントが JSON を異なるキー順で再シリアライズする可能性があるため、引数は意図的にトークンへハッシュ化していません。したがってバインディングは、引数の完全一致ではなく、ツール + ノンス + TTL です。トークンをログに記録してはいけません。単回利用のシークレットとして扱います。
| ステートメント | 仕様 | 条項 | reference_id |
|---|---|---|---|
| 承認待ちは通常のレスポンスであり、失敗ではないこと | PSR-18 | §3 | |
| 結果にかかわらず、トランスポートがレスポンスを返すこと | PSR-18 | §p2 |
このレシピはゲートのメカニズムを説明するものです。ゲートが何らかの操作を「セキュア」にする、と主張するものではありません。ゲートは、副作用を人間が認可したものにします。
商用コンテキスト
「商用コンテキスト」という見出しのセクション該当なし — ゲートと output_pdf は Core です。
トランスポートの提供状況
「トランスポートの提供状況」という見出しのセクション| トランスポート | 提供 | 備考 |
|---|---|---|
| MCP(stdio) | あり | 人間が確認するためのツール結果として、チャレンジをホストに提示 |
| REST | あり | レスポンスボディでチャレンジを返却。トークンを添えて再呼び出し |
| gRPC | あり | ユナリ。チャレンジはレスポンスメッセージ。トークンを添えて再呼び出し |
HITL リスクティア
「HITL リスクティア」という見出しのセクションリスクのはしごは Safe(0)→ Caution(1)→ Review(2)→ Approval Required(3)です。人間による確認が必要なのは Approval Required のツールのみです。output_pdf は Approval Required です。base64 モードはこれを Review に格下げし、ゲートをスキップします。file モードは Approval Required を維持し、ゲートを適用します。正式なはしごとポリシー解決はHITL リスクティアのリファレンスにあります。
確認ゲートの JSON エンベロープ
「確認ゲートの JSON エンベロープ」という見出しのセクションゲートの結果は、サーバーの確認ゲートが公開しているとおり、ちょうど 2 つの形をとります。
許可された場合(Safe/Caution/Review、または有効なトークンが消費された場合):
{ "allowed": true }チャレンジ(有効なトークンがない Approval Required の場合):
{ "allowed": false, "challenge": "⚠️ CONFIRMATION REQUIRED\n\nOperation: output_pdf\nDescription: <tool description>\n\nTo proceed, call output_pdf again with parameter _confirmation_token: \"confirm_<single-use-hex>\"\nExpires in 300 seconds.", "token": "confirm_<single-use-hex>"}対象ファイルがすでに存在する場合、challenge のテキストには上書き警告の行も含まれます。同じツールを、token の値を設定した _confirmation_token 付きで再度呼び出すと { "allowed": true } が返り、操作が続行されます。トークンは単回利用で、チャレンジに記載された時間枠が経過すると失効します。