Protocol implementation status
Target: PAP draft 0.1, updated October 9, 2026, and the Operations extension version 1 (see Compatibility).
| Area | Status |
|---|---|
| Discovery document and OAuth metadata | Implemented in Python and TypeScript |
| Client metadata, conversation-event, and Operations wire models | Implemented in Python and TypeScript with shared fixtures |
| Domain and issuer binding | Implemented in Python and TypeScript |
| Duplicate JSON member rejection | Implemented at Python and TypeScript trust boundaries |
| Client metadata validation | Implemented in Python and TypeScript |
| Client metadata and public JWKS retrieval | Implemented in Python and TypeScript with Reactor safety policies |
| Pairwise user IDs and session wire primitives | Implemented in Python and TypeScript |
| Signed-out session start and renewal over HTTP | Implemented in Python and TypeScript; host signer and DPoP provider required |
| Direct Sign-In state, S256 PKCE, callback validation, and exchange grant | Implemented in Python and TypeScript |
| Reactor clock, randomness, signer, DPoP proof, token, cache, browser, Account Token lock, protected input, standing permission, and company contracts (Contribution points) | Implemented and lifecycle-tested in Python and TypeScript |
| ES256/RS256 assertion signing | Implemented in Python and TypeScript |
| DPoP proof creation and verification | Implemented in Python and TypeScript; host key resolver and replay cache required |
| DPoP-aware API/conversation HTTP transport | Implemented in Python and TypeScript with nonce retry and same-origin redirect proof rebinding |
| Conversation creation, continuation, and ordered JSON event reads | Implemented in Python and TypeScript with long polling, backlog draining, cursor recovery, and duplicate suppression |
| Direct Sign-In browser handoff and token exchange | Implemented in Python and TypeScript; host state, browser, signer, and DPoP providers required |
| Browser Session assertion, controlled form POST, and verification | Implemented in Python and TypeScript; host signer/form-post and company replay cache required |
| Device Sign-In | Implemented in Python and TypeScript; host state store, signer, and DPoP provider required |
| Mediated Sign-In | Implemented in Python and TypeScript; credentials only through the host's pap.protectedInput, one endpoint on the company's domain, no redirects, one-time code from the same Session |
| Account Token refresh, rotation, narrowing, and revocation | Implemented in Python and TypeScript; rotation serialized by pap.accountTokenLock, invalid_grant signs out, wider scopes are re_consent_required |
| OpenAPI and MCP clients | Implemented in Python and TypeScript: ApiClient (DPoP, 202 operations, scope-carrying refusals) and McpClient/McpBearerAuth with a resource-bound Bearer token from bearer_for_mcp/bearerForMcp, sent only to its MCP server's exact URL |
| Conversation SSE streaming, handoff, Direct Conversations, sign-in mid-conversation, and active close | Implemented in Python and TypeScript: Last-Event-ID reconnects, display-only text deltas, discarded partial messages, direct_conversation_open details |
| Operations v1 | Client implemented in Python and TypeScript: negotiation, exact approval (revision + digest), terms_changed, recovery after a lost confirm, cancel, extension_required, and standing permissions through pap.standingPermissionStore; company handlers in both reference companies |
Extensible pap CLI | Reactor host/plugin, non-secret profiles, company discovery, agent identity/JWKS inspection, extension diagnostics, and live discovery command implemented |
| Generated API references | Python and TypeScript public exports inventoried; documentation CI rejects stale pages |
| Company/server SDK | Reference companies in Python (personal_agent_protocol.company, over ASGI) and TypeScript (@datalayer/personal-agent-protocol/server, over node:http(s)), every replaceable part a Reactor point; both serve MCP and, with web, browser sessions and operation pages |
| Demo worlds and end-to-end journeys | Python (personal_agent_protocol.demo): a user with a company (Manzanita) and two companies composed (Ledgerly at Northwind); TypeScript: Manzanita; real keys over in-process HTTP or TLS |
Supported package line​
The supported SDK versions, the draft and Operations version each implements, and the four language pairings are on the Compatibility page; the Support page says which versions get fixes.
Known gaps​
- Python pins metadata connections to the addresses its URL safety policy
approved (
PinnedNetworkBackend), closing the DNS-rebinding interval. Node rejects non-public DNS results before metadata requests, but its default transport does not yet pin the socket: production Node deployments need an enforcing egress proxy to fully close the interval. - Pairwise ID generation and a file-backed atomic Python reference store are
implemented. Distributed deployments must contribute their own transactional
pap.pairwiseUserIdStoreand own retention and erasure policy. - Python and TypeScript Direct Sign-In perform trusted browser handoff, atomic one-use state consumption, exact callback validation, fresh assertion/DPoP exchange, one nonce retry, and partial-scope reporting. Hosts still provide the authorization-state store, browser surface, signer, and DPoP key custody.
- Session clients sign fresh claims, create a DPoP proof, and send the token request. Local JOSE implementations are available, but applications still own key selection and custody.
- Security contribution contracts exist, but the SDK deliberately ships no default signer, DPoP key custody, durable replay cache, token store, browser handoff, or browser form-post surface.
- Browser Session clients sign the distinct
poppy-browser+jwtassertion and submit it throughpap.browserFormPost; company verification enforces the endpoint, Session owner, 60-second lifetime, company-domain return target, and one-usejti. Company adapters still own cookie creation and must bind cookie state and lifetime to the underlying PAP Session. - DPoP resource clients own authorization headers, create a fresh proof for every attempt, retry one nonce challenge, and refuse cross-origin credential forwarding. The Account Token lifecycle and resource-bound MCP Bearer acquisition on top of it are implemented in both SDKs.
- Conversation clients (messages, JSON events, SSE, handoff, Direct Conversations, closing), Account Tokens, Mediated Sign-In, and the Operations client are aligned in Python and TypeScript, and so are the two reference companies; all four language pairings pass every conformance case.
- The reference company keeps state in one process by default. Production
companies contribute a durable
pap.company.store(an async keyed store withcreate,take, and compare-and-set, checked bycheck_store) over which a restarted or replaced company continues every flow, a distributedpap.company.replayCache, their account directory, agent, and idempotent operation executors. - The SDK ships an in-memory standing permission store for examples and tests
only. Hosts contribute a durable, atomic
pap.standingPermissionStoreand their own interface for granting permissions. - The CLI does not expose auth, session, conversation, Operations, or conformance workflows until their service and protected-store boundaries are implemented.
The machine-readable requirement ledger lives in
protocol/requirements.yaml.
PAP itself still leaves payments, push notifications, and message attachments as open topics. See Open topics and SDK gaps before designing private extensions or interpreting an unimplemented SDK service as an omission from the protocol.