Pigeon,一份关于分代理人权限的签名通行证。
Pigeon, a signed Pass for what a sub-agent may do

原始链接: https://github.com/pigeonlabsHQ/pigeon

Pigeon 是一种旨在限制 AI 子智能体“爆炸半径”的安全原语。Pigeon 不再向子智能体传递强大的 API 密钥(这会授予其对生产环境、数据库和代码仓库的完全访问权限),而是允许您委派被称为“Pigeon 通行证”(Pigeon Passes)的、经过加密签名的受限凭证。 Pigeon 强制执行一种层级结构:父智能体可以向子智能体委派权限,但子智能体无法扩大其范围、增加功能或绕过父智能体设置的限制。如果子智能体试图提升权限,Pigeon 将拒绝该委派。 **工作原理:** * **委派:** 无需共享原始凭证,而是为子智能体生成一个受限的通行证。 * **验证:** 在执行时(例如调用工具或部署代码),智能体调用 `verify()` 来检查操作是否被允许。 * **执行:** 如果未经授权,系统会提供详细的原因代码,而非简单的布尔值,从而实现精确的调试。 Pigeon 并非一个独立的平台或策略引擎;它是一个轻量级工具,通过确保子智能体仅拥有其任务所需的特定权限,来保障智能体工作流的安全,从而防止意外或恶意的权限过度扩张。

Pigeon 是一种专为 AI 智能体之间实现安全权限委派而设计的新型轻量级协议。通常,当一个 AI 智能体生成子智能体时,它会将自己的凭据(如 API 密钥或数据库访问权限)完全授予子智能体。Pigeon 通过允许开发者发布“通行证”(Passes)来降低这种安全风险——这是一种经过加密签名的能力凭证,明确界定了子智能体可以执行的操作及访问范围。 与 JWT 或类似格式不同,Pigeon 使用其专门的结构来强制执行限制,例如速率限制或特定资源访问。该协议侧重于身份和授权,而非充当中心化服务器;密钥保留在本地运行器上,而子智能体仅携带受限的“通行证”。如果子智能体试图超出其委派的权限,系统会采取“默认拒绝”的安全策略。 v0.1 版本的核心功能包括 Ed25519 签名、链式验证支持以及用于强制执行的 MCP(模型上下文协议)辅助工具。虽然 Pigeon 为最小权限委派提供了稳健的框架,但它并非独立的平台,也无法防御提示词注入攻击。 仓库地址:[github.com/pigeonlabsHQ/pigeon](https://github.com/pigeonlabsHQ/pigeon)
相关文章

原文

Your agent spawned a sub-agent and handed it the same API key. That sub-agent can now deploy to production, read the payments database, and merge to main.

Pigeon stops that. You hand the child a Pigeon Pass: a narrowed, signed credential for what it may do, not a copy of everything you can do.

Python 3.12 or newer.

git clone https://github.com/pigeonlabsHQ/pigeon.git
cd pigeon
pip install .

The whole idea, in 20 lines

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 never returns a bare boolean. A denial includes a reason code, a message, and the comparison that failed (requested vs allowed).

Try it without writing that yourself:

python examples/01_infrastructure.py
python demo/agent.py

Where it goes in an agent

There is no Pigeon server to connect to. You change two places you already have:

  1. Spawn. Where you would have copied an API key into a sub-agent, call delegate(...) and give the child a Pass.
  2. Tool. Where the side effect happens (deploy, query, MCP tool), call verify(...) and do not run the tool if it is denied.

Keep the real secret on the runner. The child carries the 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},  # cannot drop a parent constraint
)

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"

A child cannot add capabilities, widen resources, raise a bound, or drop a parent constraint. If Pigeon cannot prove the child is narrower, it rejects.

If the runner never calls verify, the Pass is decoration.

This is an enforcement point, not part of the protocol. The client mints a narrower Pass per tool call. The server verifies it before the tool runs.

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 tells you who the agent is. Authority tells you what it may do.

pigeon keygen
pigeon inspect pass.json

Pigeon is a small primitive. It is not a platform, a policy engine, an identity provider, or a key custodian. It does not stop prompt injection. It bounds blast radius along the dimensions you put on the Pass, and only those.

  • Protocol: SPEC.md
  • Limits: SECURITY.md
  • More scripts: examples/ (infrastructure, data, code, then payments)
联系我们 contact @ memedata.com