🤖 🌸 Personal Agent Protocol
Python and TypeScript SDKs for Personal Agent Protocol, currently targeting draft 0.1.
The first implemented slice provides:
- forward-compatible discovery, OAuth metadata, client metadata, conversation messages/events, and Operations v1 models in Python and TypeScript;
- company discovery at
/.well-known/poppy.json; - validation of the requested company domain, OAuth issuer, and
poppy_domainsrelationship; - HTTPS-only redirects, bounded response sizes, and a public-address preflight guard in the Python discovery client;
- Reactor-backed protocol profiles, discovery transports, URL-safety policies, extension handlers, clocks, randomness, signing, protected keys, token storage, pairwise identity, caches, and browser-handoff contribution points in both SDKs;
- redacted session-token values, random pairwise user-ID generation and atomic file-backed reference persistence, PAP 4.2 assertion claims, and JWT-bearer request forms;
- signed-out session start and renewal over HTTP, with Reactor-provided signing and DPoP proof generation, in both SDKs;
- asymmetric ES256/RS256 JOSE signers and RFC 9449 DPoP creation and verification, including nonce, request, token-hash, freshness, and replay checks, in both SDKs;
- Direct Sign-In state, S256 PKCE, callback validation, and redacted exchange forms plus one-use browser and token-exchange orchestration in both SDKs;
- duplicate JSON member rejection at Python and TypeScript trust boundaries;
- a Reactor-extensible
papCLI with non-secret profiles, verified company discovery, extension diagnostics, versioned JSON, and a safe live-session discovery command; - one shared set of fixtures exercised by both SDKs.
Managed key custody and durable replay storage, device/mediated sign-in, conversations, and the Operations client/server are not implemented yet. Direct Sign-In requires host-provided authorization-state, browser, signer, and DPoP contributions; the SDK does not open a browser or persist state through an implicit global service.
Session requests fail closed unless the host contributes signer and DPoP providers backed by suitable key custody.
Python
python -m pip install -e '.[test,lint,typing]'
python -m pytest tests
import asyncio
from personal_agent_protocol import DiscoveryClient
async def main() -> None:
async with DiscoveryClient() as client:
company = await client.discover("example.com")
print(company.document.organization.name)
asyncio.run(main())
DiscoveryClient(reactor=platform) accepts an existing Reactor
PluginPlatform. The default build_pap_reactor() host contributes the HTTPX
transport, public-network safety policy, and PAP 0.1 profile. A plugin can
replace a default by contributing at a lower order; equal highest priorities
fail closed as ambiguous.
The core also contributes UTC time and operating-system randomness. It does not provide insecure fallbacks for signing, DPoP proof generation, protected keys, token storage, cache, or browser handoff. A flow requiring one fails closed until its host contributes it. This also applies to pairwise identity; Python includes an explicit SQLite reference provider, but the core does not silently install it.
Command line
The Python package installs an extensible pap command. Its command groups are
provided through Reactor's datalayer.reactor.cli entry-point contract.
pap config set domain example.com --profile work
pap config show --profile work --json
pap company verify --profile work --json
pap extensions list --profile work
Only non-secret settings belong in CLI profiles. See the CLI guide for precedence, security boundaries, machine output, and third-party extension examples.
TypeScript
The TypeScript package lives at the repository root: sources are in
src/, tests in test/, and emitted package files in
lib/.
npm install
npm test
import { discoverCompany } from "@datalayer/personal-agent-protocol";
const company = await discoverCompany("example.com");
console.log(company.document.organization.name);
Use buildPapReactor(options, plugins) to assemble the TypeScript host, or
pass an existing ReactorPlatformView as discoverCompany(..., { reactor }).
The package bundles Reactor's framework-neutral core in its ESM entry so it can
run directly in Node as well as through a browser bundler.
Server-side TypeScript callers can import NodeUrlSafetyPolicy, JoseSigner,
and DPoP verification from the explicit
@datalayer/personal-agent-protocol/server entry. The portable entry excludes
those server APIs and rejects obvious local/private literal addresses; the Node
policy additionally checks every resolved A and AAAA address.
The Python and Node preflights reject a host if any resolved address is non-public. Transport-level address pinning, required to close the DNS-rebinding interval, is still part of the security work before the first beta.
Examples
The examples/ directory includes an Agent Runtimes Python
application that discovers a PAP company over HTTPS while exposing only
verified, non-secret capability metadata to the model. Authorization and token
handling remain outside the agent tool boundary.
Protocol sources
Metadata
Release files for personal-agent-protocol 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| personal_agent_protocol-0.3.1.tar.gz | 730.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| personal_agent_protocol-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 771.5 kB
Release files / personal_agent_protocol-0.3.1.tar.gz
| Download URL | personal_agent_protocol-0.3.1.tar.gz |
|---|---|
| Size | 730.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
98a41868979263238e77f540f7a9773f75fcf8af4a3bb93dc76f03fcf7af7e2f
|
|
BLAKE2b-256 checksum How to use checksums |
590d54cfd3575aa870a847e54083a11d8ee1b456778a40ec45bf7315c01ab14d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / personal_agent_protocol-0.3.1-py3-none-any.whl
| Download URL | personal_agent_protocol-0.3.1-py3-none-any.whl |
|---|---|
| Size | 40.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cbb162785f3c5ce27238ceb2e8756c9e71b066d3773598bff0308f9f0de3226a
|
|
BLAKE2b-256 checksum How to use checksums |
ed2d6bc8cd18110dabb0c5710ca51b881a80088886f9f1816f7a8895f2bfb9d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency log