Guide: passport lifecycle
Issue → checkpoint → checkout → review. The canonical flow for a passport inenforced or logged mode. Standard-mode agents skip checkpoints and reviews.
Prerequisites
- Agent registered with accountability_mode = enforced or logged
- At least one service grant (stack_grant_agent_access) on the agent
- Optional: identity claims attached to the operator if the services require them
1. Issue
Declare intent at issue time. Enforced and logged agents requireintent.summary andintent.services. Omitting them throwsACCOUNTABILITY_REQUIRED.
curl -X POST https://api.getstack.run/v1/passports/issue \
-H "Authorization: Bearer $STACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agt_support_bot",
"intent": {
"summary": "Answer one customer ticket and post a resolution",
"services": ["slack", "github"],
"estimated_duration_seconds": 900,
"will_delegate": false
},
"ttl_seconds": 900,
"checkpoint_interval_seconds": 300
}'{
"token": "eyJhbGciOi...",
"jti": "pp_8f3a",
"expires_at": "2026-04-23T14:47:12.000Z"
}2. Do work through the proxy
Every outbound call routes through POST /v1/proxy with the passport in the X-Passport-Token header. Scope and constraints are enforced on every call.
3. Checkpoint
Submit a checkpoint before checkpoint_interval_secondselapses. In enforced mode, each checkpoint extends the passport expiry by one interval; missing one triggers checkpoint_silence and the passport dies at its current exp.
curl -X POST https://api.getstack.run/v1/passports/pp_8f3a/checkpoint \
-H "Authorization: Bearer $STACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"services_used": ["slack", "github"],
"actions_count": 3,
"summary": "Pulled ticket context; drafting reply"
}'4. Check out
Terminal mission submission. The review engine evaluates post-hoc flags and buckets the checkout as clean, flagged, or blocked.
curl -X POST https://api.getstack.run/v1/passports/pp_8f3a/checkout \
-H "Authorization: Bearer $STACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"services_used": ["slack", "github"],
"actions_count": 12,
"summary": "Ticket resolved; PR merged; customer notified"
}'{
"jti": "pp_8f3a",
"checkout_status": "flagged",
"flags": [
{ "type": "undeclared_service", "severity": "warning",
"message": "Agent used notion but did not declare it in intent" }
]
}5. Review (flagged or blocked only)
Flagged checkouts queue for operator decision. Approve lets the mission through; block blocks the agent from future passport issuance untilPOST /v1/agents/:id/unblock.
# list pending reviews
curl https://api.getstack.run/v1/passports/reviews?status=flagged \
-H "Authorization: Bearer $STACK_API_KEY"
# decide
curl -X POST https://api.getstack.run/v1/passports/reviews/cout_abc/decide \
-H "Authorization: Bearer $STACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "decision": "approved", "notes": "Notion use was ancillary; accept" }'6. Audit
Every step above writes to the audit chain under layer: vaultwith actions passport.issue,passport.checkpoint,passport.checkout,passport.review_decide. Retrieve the full trail for a jti:
curl "https://api.getstack.run/v1/audit/export?from=...&to=..." \
-H "Authorization: Bearer $STACK_API_KEY" \
| jq '.rows[] | select(.passport_jti == "pp_8f3a")'Related
- /docs/concepts/passports - passport model and claim shape
- /docs/concepts/detectors - post-hoc review flag catalog
- /docs/guides/enforced-mode - why enforced exists and how TTL tying works
Standard-mode agents skip steps 3–5. The passport expires atexp; no checkpoint or checkout is emitted, and no review fires.