你的智能体生成了一个子智能体,并把同一个 API 密钥交给了它。这个子智能体现在可以部署到生产环境、读取支付数据库,并合并到主分支。
Pigeon 阻止了这一切。你交给子智能体的是一个 Pigeon Pass:一份收窄的、经过签名的凭证,明确它被允许做什么,而不是你全部权限的副本。
需要 Python 3.12 或更高版本。
git clone https://github.com/pigeonlabsHQ/pigeon.git
cd pigeon
pip install .
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 从不返回一个简单的布尔值。拒绝结果包含原因代码、消息以及失败的比较(requested 与 allowed)。
无需自己编写,直接尝试:
python examples/01_infrastructure.py
python demo/agent.py
没有需要连接的 Pigeon 服务器。你只需修改已有的两个地方:
delegate(...) 并给子智能体一个 Pass。verify(...),如果被拒绝则不运行该工具。将真正的密钥保留在运行器上。子智能体携带的是 Pass。
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,Pass 就只是装饰。
这是一个执行点,不属于协议本身。客户端为每次工具调用铸造一个更窄的 Pass。服务器在工具运行前对其进行验证。
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"
身份(Identity)告诉你智能体是谁。权限(Authority)告诉你它可以做什么。
pigeon keygen
pigeon inspect pass.json
Pigeon 是一个小型原语。它不是平台、策略引擎、身份提供者或密钥保管者。它不能阻止提示注入。它只在你放入 Pass 的维度上限制爆炸半径,且仅限于这些维度。
SPEC.mdSECURITY.mdexamples/(基础设施、数据、代码,然后是支付)