mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-07 16:35:48 +01:00
Give agents persistent Ed25519 identities encrypted with the existing instance master key. Create keys transactionally for new agents and lazily before supported managed runs, expose public identities in the API and agent UI, and protect private material during runtime delivery and output persistence. Preserve identities in recovery backups while giving imported and development-cloned agents fresh keys. Co-Authored-By: Paperclip <noreply@paperclip.ing>
101 lines
5.6 KiB
Markdown
101 lines
5.6 KiB
Markdown
# Agent cryptographic identity
|
||
|
||
Each agent has one persistent Ed25519 keypair. New agents receive it in the
|
||
agent-creation transaction. Existing agents receive it when Paperclip prepares
|
||
their next managed run. Migration, startup, public API reads, and opening the
|
||
agent page do not provision existing agents. There is no backfill command.
|
||
|
||
## Storage
|
||
|
||
`agent_identity_keys` lives in the agent's home instance database, including a
|
||
hosted stack's database. Its agent primary key and composite company/agent
|
||
foreign key enforce one identity and company-consistent ownership. Deleting an
|
||
agent cascades to its identity. Creation locks the agent row inside a transaction,
|
||
so simultaneous first runs use the same stored pair.
|
||
|
||
Public keys use SPKI PEM and private keys use PKCS#8 PEM. `keyId` is `sha256:`
|
||
followed by the base64url SHA-256 digest of the public key's SPKI DER bytes.
|
||
Private material is encrypted using the existing `local_encrypted` provider and
|
||
stored separately from company secrets. The wrapping key is the stack's
|
||
`PAPERCLIP_SECRETS_MASTER_KEY` or the local instance's secrets master-key file.
|
||
The file is published atomically with mode `0600` on first use. No per-agent
|
||
Cloud secret or Cloud registry record is needed.
|
||
|
||
Decryption and public/private key validation happen before launch. A wrong
|
||
master key, corrupt ciphertext, or mismatched public key fails the run; none
|
||
causes automatic key replacement. Renames, model changes, pauses, resumes, and
|
||
restarts preserve the keypair.
|
||
|
||
## Managed runs
|
||
|
||
Paperclip supplies these server-owned environment variables:
|
||
|
||
```text
|
||
PAPERCLIP_AGENT_KEY_ID
|
||
PAPERCLIP_AGENT_PUBLIC_KEY
|
||
PAPERCLIP_AGENT_PRIVATE_KEY
|
||
```
|
||
|
||
The two key values are multiline PEM strings. Runtime-only adapter context and
|
||
native runner environment fields deliver them to managed processes. Configured
|
||
or inherited environment values cannot replace the assigned identity. Session
|
||
compatibility includes the public key ID, so an older warm process is replaced
|
||
before its next turn. Private values are excluded from invocation metadata and
|
||
execution configuration; output and failure diagnostics redact known private
|
||
material. The run-log redactor handles split stdout/stderr chunks independently.
|
||
Native output deltas also buffer potential key fragments before persistence.
|
||
Raw provider trace contents are suppressed for identity-enabled runs; trace
|
||
routing, timing, and interpretation metadata remain available.
|
||
|
||
Managed remote providers, including Cursor Cloud, receive the same private key
|
||
as managed local processes. Selecting a runtime therefore trusts its host with
|
||
the agent's persistent identity: the agent and its host can retain the key and
|
||
sign outside Paperclip. Encryption at rest protects database storage, not an
|
||
executing runtime. Move an agent only between runtime hosts trusted with that
|
||
identity.
|
||
|
||
Independently hosted HTTP and gateway agents, including Runner's API-hosted Claude Managed and AWS AgentCore providers, do not receive private keys in v1.
|
||
Their new agent records still get stored identities; their existing records stay
|
||
unprovisioned until a supported managed run.
|
||
|
||
An agent can sign using an ordinary cryptographic library, for example Node.js:
|
||
|
||
```js
|
||
import { sign } from "node:crypto";
|
||
const signature = sign(null, challengeBytes, process.env.PAPERCLIP_AGENT_PRIVATE_KEY);
|
||
```
|
||
|
||
This identity does not change Paperclip bearer-token authentication. There is no
|
||
signing API, private-key download endpoint, Git integration, rotation UI, or
|
||
external-key import. Agents possess their private keys. External consumers must
|
||
define their own authorization, expiry, and revocation rules.
|
||
|
||
## Public identity
|
||
|
||
`GET /api/agents/:id/identity` applies the existing agent-read access checks. It
|
||
returns `null` before provisioning, otherwise:
|
||
|
||
```ts
|
||
{ algorithm: "Ed25519", keyId: string, publicKeyPem: string, createdAt: string }
|
||
```
|
||
|
||
The agent's Identity section shows a shortened fingerprint and copies the full
|
||
public PEM. Before provisioning it shows “Not created yet” and explains that
|
||
creation happens on the next managed run.
|
||
|
||
## Copies and recovery
|
||
|
||
Company/template imports and duplication use normal agent creation and get new
|
||
identities. Minimal and full development seeds omit identity **rows**, while
|
||
retaining the schema, even with live-work preservation. Those copied agents get
|
||
fresh identities on their next managed runs.
|
||
|
||
Ordinary disaster-recovery backups include encrypted identities. Recovery needs
|
||
both the database and the matching wrapping key; back up the key separately.
|
||
Do not use a disaster-recovery backup as a development clone when agents should
|
||
have distinct identities.
|
||
|
||
Native failure records and reports redact the assigned key before truncating diagnostics. Streaming output buffers settle at item or turn completion: short structural prefixes (such as a trailing dash) are preserved, longer interrupted key fragments become redaction markers, and pending buffers are cleared. Terminal events carry these settled `outputTails`; transcript projection displays them as deltas without changing the source event receipt.
|
||
|
||
Codex shell delivery preserves its default `KEY`/`SECRET`/`TOKEN` name exclusions for other configured credentials. The exceptions are the three identity variables and `PAPERCLIP_API_KEY`: the latter is the short-lived, scoped run/bridge credential required by the Paperclip agent skill’s Bash/curl API calls. Disabling Codex’s automatic exclusions is paired with this explicit filtered allowlist; it does not admit arbitrary host environment variables. Provider authentication secrets can still reach the provider process without being newly exposed to shell commands by this feature.
|