
Durchsetzung von Delegation mit geringsten Privilegien für KI-Agenten mittels signierter, eingeschränkter Anmeldeinformationen. Gewähren Sie Unter-Agenten begrenzte Fähigkeiten und Ressourcen, überprüfen Sie Aktionen vor der Ausführung und verhindern Sie Privilegienausweitung.
Dein Agent hat einen Sub-Agenten erzeugt und ihm denselben API-Schlüssel übergeben. Dieser Sub-Agent kann nun in Produktion deployen, die Zahlungsdatenbank lesen und in den Main-Branch mergen.
Pigeon verhindert das. Du gibst dem Kind einen Pigeon Pass: eine eingeschränkte, signierte Berechtigung für das, was es tun darf – keine Kopie von allem, was du tun kannst.
Python 3.12 oder neuer.
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 gibt niemals einen nackten Boolean zurück. Eine Ablehnung enthält einen Reason-Code, eine Nachricht und den Vergleich, der fehlgeschlagen ist (requested vs. allowed).
Probiere es aus, ohne das selbst zu schreiben:
python examples/01_infrastructure.py
python demo/agent.py
Es gibt keinen Pigeon-Server, mit dem man sich verbinden müsste. Du änderst zwei Stellen, die du bereits hast:
delegate(...) auf und gibst dem Kind einen Pass.verify(...) auf und führst das Tool nicht aus, wenn es abgelehnt wird.Bewahre das echte Geheimnis auf dem Runner auf. Das Kind trägt den 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}, # kann eine Parent-Constraint nicht entfernen
)
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"
Ein Kind kann keine Capabilities hinzufügen, Ressourcen erweitern, ein Limit anheben oder eine Parent-Constraint entfernen. Wenn Pigeon nicht beweisen kann, dass das Kind enger gefasst ist, lehnt es ab.
Wenn der Runner verify nie aufruft, ist der Pass nur Deko.
Dies ist ein Durchsetzungspunkt, kein Teil des Protokolls. Der Client prägt einen engeren Pass pro Tool-Aufruf. Der Server verifiziert ihn, bevor das Tool ausgeführt wird.
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"
Identität sagt dir, wer der Agent ist. Autorität sagt dir, was er tun darf.
pigeon keygen
pigeon inspect pass.json
Pigeon ist ein kleines Primitive. Es ist keine Plattform, keine Policy-Engine, kein Identitätsanbieter und kein Schlüsselverwalter. Es stoppt keine Prompt-Injection. Es begrenzt den Blast-Radius entlang der Dimensionen, die du auf den Pass setzt – und nur entlang dieser.
SPEC.mdSECURITY.mdexamples/ (Infrastruktur, Daten, Code, dann Zahlungen)