Changelog

What changed in each version of the specification, extensions, and guides, newest first. Each published version stays at its own URL, such as /docs/0.1/spec.

Draft 0.2

In progress, at /docs/spec. This list grows until 0.2 is published. Changes marked "Breaking" can require an implementation that followed the 0.1 text to change.

  • Breaking: Which domain poppy.json speaks for. organization.domain is the host that serves the document after any redirects, not the host the Personal Agent requested. Domains are compared ignoring case only, so a leading www. is no longer ignored, and the poppy_domains check also ignores case. A Company that uses a provider has the provider serve the document on the Company's own domain (3, 3.1, 3.2). Issue #5
  • Breaking: One issuer per Company. An issuer represents exactly one Company. A provider that hosts several Companies gives each its own issuer, even on shared servers, so they don't share User IDs or Account Tokens. The spec also says where the metadata is for an issuer with a path, as RFC 8414 defines (3.2, 4.2, 9.4). Issue #3
  • Breaking: DPoP algorithms. Companies accept DPoP Proofs signed with ES256. They may list the algorithms they accept in dpop_signing_alg_values_supported in their OAuth metadata, and the list then includes ES256. A Company whose issuer serves other OAuth clients can leave the field out, since it tells them the issuer supports DPoP. Personal Agents sign with ES256 or an algorithm from the list (3.2). Issue #12
  • Breaking: extension_required responses. At the token endpoint and at endpoints this protocol or an extension defines, the error is a JSON body. At APIs, it goes in the WWW-Authenticate header. It's listed in the token endpoint and API error tables. An MCP server returns it only to refuse the Personal Agent entirely, never for a single tool (3.3, 4.2, 6).
  • Breaking: Assertion audience. In 0.1, a client assertion's aud wasn't specified, and a Session assertion's was the Company's token endpoint. Both are now the Company's auth.issuer, and Companies reject any other aud (4.1, 4.2, 9.4). Issue #2
  • Breaking: DPoP Proof checks. Companies MUST validate every proof as RFC 9449 §4.3 describes. That adds checks that the request has exactly one DPoP header, typ is dpop+jwt, alg is an asymmetric algorithm the Company accepts and never none, and jwk holds no private key. In 0.1, every endpoint had to reject a reused jti. Now only the token endpoint must, and APIs and conversation endpoints may. A Company can judge the acceptance window by when it issued the proof's nonce, not only by iat. Companies don't need to support dpop_jkt. Where the spec is silent, RFC 9449 applies (4.3).
  • Breaking: DPoP errors at APIs and conversations. invalid_dpop_proof and use_dpop_nonce come with HTTP 401 and the WWW-Authenticate: DPoP header. At the token endpoint they're OAuth errors with HTTP 400 (4.3, 6).
  • DPoP at MCP servers. An MCP server supports DPoP by listing dpop_signing_alg_values_supported in its protected resource metadata. Personal Agents then use a DPoP Session Token there, issued for the server's resource. The server still accepts Bearer tokens for MCP clients without DPoP, and rejects a DPoP token sent as a Bearer token. New MCP servers should support DPoP (4.3, 6). Issue #6
  • rate_limited body. At the token endpoint and at endpoints this protocol or an extension defines, such as conversations and Mediated Sign-In, the body is {"error": "rate_limited"}. APIs and the website keep their own bodies (4.3).
  • Breaking: A Session stays tied to its account. Once a Session has been signed in to an account, it can only be signed in to that account again, even after sign-out. This applies to every sign-in type, and to using an Account Token with a signed-out Session (4.4, 4.8, 4.9). Issue #8
  • Breaking: Mediated Sign-In responses. Every status comes with HTTP 200, and submitting a code to a failed or expired sign-in returns the same status again. Problems with the request are errors with a JSON body: invalid_scope and account_mismatch (400), and sign_in_not_found (404) for a sign-in that is unknown or that another Session started (4.7).
  • Breaking: Mediated Sign-In credentials. After a sign-in ends, Personal Agents MUST discard the credentials or keep them only in a credential store the User chose, such as a password manager. They MUST NOT keep them anywhere else, including model context and logs. After the User or the Company revokes their access, they SHOULD NOT sign in again with stored credentials unless the User asks (4.7). Issue #5
  • Work after a token expires. A Session Token expiring isn't a sign-out, and work the Company accepted with a valid token can continue. When access is revoked, the Company may stop work in progress that uses the account, or let it finish (4.9). Issue #15
  • Sessions from plain MCP clients. A Session started by an MCP client that doesn't implement this protocol has no User ID, can't continue signed out, and ends when its sign-in does (6).
  • Conversation query parameters. cursor and wait are query parameters, as the 0.1 examples showed, on reads and on the POST requests that send a message or hand off. wait is a whole number of seconds (7.3, 7.5).
  • Breaking: Messages. role is listed as a message field, set by the Company. A message event holds the message as it was sent, and every accepted message is recorded, including one with only context (7.4, 7.5).
  • Long polling. A Company that caps wait holds the request for its cap instead of rejecting it (7.5).
  • Breaking: Read fields. Every successful read includes conversation_id and events, as the examples showed, along with cursor, has_more, status, and responder. events is empty when there are none (7.5). Issue #13
  • Streaming. When a request has both Last-Event-ID and cursor, Last-Event-ID wins (7.6).
  • Repeated requests. Handing off a conversation that is already queued or with a person, or closing one that is already closed, returns the current state and changes nothing (7.9, 7.12).
  • user_requested. The event doesn't change status or responder (7.10).
  • Conversation errors. Conversations add invalid_request (400) and rate_limited (429) (7.13).
  • Feedback. A new section 8 lets a Company list a feedback.endpoint in poppy.json. With a Session Token, Personal Agents can report a User's task that the Company offers no way to do through this protocol. A report has a kind, which is missing for now, the task, and a description without identifiers, and isn't for errors (3.1, 8). Issue #9
  • Breaking: Security considerations. A new section 9 covers content from Companies and prompt injection, secrets and the model, what a domain vouches for, and why assertions name the issuer. It adds requirements for Personal Agents: they MUST treat content from a Company as data, not instructions, and MUST NOT act at one Company, or send it information, because another Company's content asked. References move to section 10 (9, 9.1). Issue #4
  • Operations. Personal Agents should show the User the values in an operation's terms next to its summary, or check that they agree, before asking for approval (Operations 5.1). Issue #4
  • Guides. Sign DPoP Proofs with ES256, which every company accepts. A company's token endpoint keeps a replay cache shared by every server, and its APIs may keep one too. A client or Session assertion's aud is the company's auth.issuer. Personal agents keep Mediated Sign-In credentials only in a credential store the user chose, and don't sign in with them again after the user disconnects. Companies ask for a one-time code on a personal agent's first mediated sign-in after the user disconnected it (Guides). Issue #5
  • Guides: key refetches, rate limits, and running work. Companies refetch a personal agent's keys at most once per interval, counting failures, and charge per-agent rate limits only after the signature checks pass. Accepted work isn't stopped because a session token expired, and work that can take consequential actions stops right away when access is revoked (Rotating keys, Rate limits, Token lifetimes and sign-out). Issue #15
  • Guides: hosting several companies. A new section for providers that host several companies, with an example of which storefronts share an issuer, metadata for an issuer with a path, and keeping each company's tokens and records apart on shared servers. Personal agents key user IDs and account tokens by the full auth.issuer (Hosting several companies, User IDs). Issue #3

Version 0.1

Published October 9, 2026, the first published draft. It's frozen at /docs/0.1/spec.