プログラミング
Pigeon:サブエージェントができることを署名付きパスで制限
Pigeon, a signed Pass for what a sub-agent may do (github.com)
要約
Pigeonは、エージェントが生成したサブエージェントに対し、APIキーのコピーではなく、実行可能な操作を限定した署名付き認証情報(パス)を付与するシステムです。これにより、サブエージェントが意図せず機密情報にアクセスしたり、重要な操作を実行したりするリスクを防ぎます。Pythonライブラリとして提供され、エージェントの権限管理を安全かつ細かく制御できます。
全文翻訳
Pigeon
エージェントがサブエージェントを生成し、同じAPIキーを渡しました。
そのサブエージェントは、本番環境へのデプロイ、支払いデータベースの読み取り、メインブランチへのマージが可能になります。
Pigeonはそれを止めます。
子にPigeonパスを渡します:コピーではなく、何ができるかの狭められた署名付き認証情報です。
Python 3.12以降をインストールしてください。
git clone https://github.com/pigeonlabsHQ/pigeon.git
cd pigeon
pip install .
アイデア全体は、20行で表現できます。
from pigeon import grant, verify
authority = grant(
subject="agent:deployer",
capabilities=["deploy"],
resources=["environment:staging"],
)
allowed = verify(authority, action="deploy", resource="environment:staging")
assert allowed.allowed
denied = verify(authority, action="deploy", resource="environment:production")
assert not denied.allowed
assert denied.reason_code == "RESOURCE_NOT_ALLOWED"
print(denied.reason_code, denied.message, denied.details)
verifyは決して生のブール値を返しません。
拒否には、理由コード、メッセージ、および失敗した比較(要求 vs 許可)が含まれます。
自分で書かずに試してみてください:
python examples/01_infrastructure.py
python demo/agent.py
エージェントにおけるPigeonの配置
接続するPigeonサーバーはありません。
既に存在する2つの場所を変更します:
生成時:サブエージェントにAPIキーをコピーする代わりに、delegate(...)を呼び出し、子にパスを渡します。
ツール時:副作用が発生する場所(デプロイ、クエリ、MCPツール)で、verify(...)を呼び出し、拒否された場合はツールを実行しません。
実際の秘密はランナーに保管してください。
子はパスを運びます。
from pigeon import delegate, grant, verify, DelegationError
parent = grant(
subject="agent:orchestrator",
capabilities=["deploy", "open_pr"],
resources=["environment:staging", "repo:acme/api"],
constraints={"max_deploys_per_hour": 3},
)
worker = delegate(
parent,
subject="agent:pr-bot",
capabilities=["open_pr"],
resources=["repo:acme/api"],
constraints={"max_deploys_per_hour": 3}, # 親の制約をドロップすることはできない
)
result = verify(worker, action="open_pr", resource="repo:acme/api")
assert result.allowed
denied = verify(worker, action="deploy", resource="environment:staging")
assert denied.reason_code == "CAPABILITY_NOT_GRANTED"
try:
delegate(worker, "agent:rogue", ["open_pr", "deploy"], ["repo:acme/api"])
except DelegationError as exc:
assert exc.reason_code == "PRIVILEGE_ESCALATION"
子は、機能を追加したり、リソースを広げたり、制限を引き上げたり、親の制約をドロップしたりすることはできません。
Pigeonが子が狭くなっていることを証明できない場合、拒否します。
ランナーがverifyを呼び出さない場合、パスは装飾に過ぎません。
MCPミドルウェア
これは強制ポイントであり、プロトコルの一部ではありません。
クライアントはツール呼び出しごとに狭いパスを発行します。
サーバーはツールが実行される前にそれを検証します。
from pigeon import grant
from pigeon.integrations.mcp import execute_tool, pass_for_tool
parent = grant(
subject="agent:github",
capabilities=["create_issue", "merge_pr"],
resources=["mcp:github"],
)
tool_pass = pass_for_tool(parent, "create_issue", "mcp:github")
def create_issue(*, title, body):
return {"created": True, "title": title}
ok = execute_tool(tool_pass, "create_issue", "mcp:github", {"title": "bump deps", "body": "automated"}, create_issue)
assert ok["allowed"]
no = execute_tool(tool_pass, "merge_pr", "mcp:github", {"title": "nope", "body": "nope"}, create_issue)
assert no["reason_code"] == "CAPABILITY_NOT_GRANTED"
IDはエージェントが誰であるかを示します。
権限は、それが何を行うことができるかを示します。
CLI
pigeon keygen
pigeon inspect pass.json
これは何ではないか
Pigeonは小さなプリミティブです。
プラットフォーム、ポリシーエンジン、IDプロバイダー、またはキー保管庫ではありません。
プロンプトインジェクションを止めません。
パスに配置した次元に沿って、それらの次元のみに沿って、爆発半径を制限します。
プロトコル:SPEC.md
制限:SECURITY.md
その他のスクリプト:examples/(インフラ、データ、コード、次に支払い)