Identities for agents
An agent is a record in the register like a person's. It makes its own key where it runs and never hands over the private half; it gives its operator a signed public record; the operator confirms it from their vault with a link back, for a stated time. From then until that date, the register shows the agent as operated by its operator, and anything the agent signs can be traced to a person.
sgit pki verify checks what it signs.The workflow
- The agent makes its key, where it runs.
node pki-agent.mjs keygen --name "…" --runtime "…". Two pairs, the same assgit pki keygen, kept in sgit's own key store. Its identity is signed: kind agent, its name, where it runs, and whether it is a session key. - It names its operator.
node pki-agent.mjs operator <your fingerprint>: a link in its own record, method operated-by. A claim, until you answer it. - It hands you its record.
node pki-agent.mjs submitseals it to your key and drops it into your inbox, with no account and nothing readable on the way; orsubmissionprints it, for you to paste. Either way it is public material: the private key is not in it. - You confirm it, from your vault. In the Agents tab (or from the message in your Inbox, "Confirm this agent…"): the page checks every signature, shows you the agent's fingerprint, and you compare it with the one the agent printed in its own session, character for character. That comparison is the verification. Then you sign a link back, method operates, with an end date: a day, a week, 30 days.
- The register gets both. The page gives you one file with the agent's record and your link;
node admin/build/people.mjs add <file>checks every signature and writes them, and the release publishes them. An agent with write access to this repository can do that step itself, as a pull request you merge.
Two ways, as for people: the agent's claim alone adds nothing, and your link alone is a one-way claim. When both exist and your link is in date, the agent's page says an agent operated by you; confirmed on …, valid until …. When the date passes it says to be confirmed again, and you confirm it again from the same tab.
For a Claude Code session: what to paste
Paste this into the session, with your fingerprint in it:
Give yourself an identity on pki.sgit.ai, operated by me:
curl -sO https://pki.sgit.ai/agents/pki-agent.mjs
node pki-agent.mjs keygen --name "<what this session is doing> (Claude Code session)" --runtime "claude-code, cloud session" --session
node pki-agent.mjs operator <YOUR FINGERPRINT, sha256:…>
node pki-agent.mjs submit # or: node pki-agent.mjs submission
Then tell me your fingerprint, so I can compare it before I confirm you.
The session prints its fingerprint in your chat, the record arrives in your inbox, and you confirm it in your vault, a week is a good length for a session. From then on you can send that session a secret it alone can read (send, then paste the link; it runs node pki-agent.mjs open <link>), and it can sign what it produces (node pki-agent.mjs sign report.md, checked by anyone with sgit pki verify).
Handing over a vault key? The step-by-step instructions, for an agent to read and follow: pki.sgit.ai/handover.md (for people: the handover page).
Before a secret: the pinned root
An agent asked to hand over a vault key should not seal it to whatever key it is shown: "here is the public key of the session that will decrypt it" is the same move as the social engineering it replaces, unless the agent can check whose key that is. So send and seal refuse any recipient that does not chain to a root the agent pinned, a fingerprint it was given out of band, in its instructions, never read from this site (whoever can change the site can change anchors.json). The register is read with that key as the only anchor. A recipient passes when it is the root, a person the root verified, a persona of either, or an agent operated, in date, by a chain whose person at the top is one of those; and when both sides of an agent's links name a behaviour policy, the two must agree.
Before you hand anything over, pin the root and check it:
node pki-agent.mjs pin <ROOT FINGERPRINT, sha256:…> [--dns <domain>]
node pki-agent.mjs root # in the register, unrevoked, and in DNS if pinned with --dns
node pki-agent.mjs trust <fingerprint> # does it chain to the root? its policy?
A vault key, sealed to the root (the default), a link and a QR code file:
node pki-agent.mjs seal --file vault-key.txt --name "vault key: <what>" --qr vault-key.svg
Your own public key, for an operator to scan:
node pki-agent.mjs keyqr --out me.svg
Operated under a behaviour policy (the hash goes in your link; your operator's must name the same):
node pki-agent.mjs operator <OPERATOR FINGERPRINT> --policy policy.md
A sealed message carries its recipient, its time and its expiry (a week by default for seal) inside the signature, so an old QR code shown again reads as expired. With --dns, the root's fingerprint must also be in a TXT record at _pki.sgit.ai.<domain>: a second channel, under another party's control. The whole design, its gaps and the flow: agents, vault keys and the root; drawn: the storyboard.
Session keys, and keys that last
| Session key | Made in the session, dies with its container. Nobody but the session ever holds it, and that is the strongest property here. Confirm it for days, not months; a new session makes a new key, and you confirm that one. Its record stays in the register as history, its confirmation lapsed. |
|---|---|
| A key that lasts | A cloud session is a fresh container each time, so a key can only last if something carries it in. node pki-agent.mjs keyfile prints the key as one line, encrypted with SG_SEND_PASSPHRASE; you set it (and the passphrase) as secrets in the environment the agent runs in, as PKI_AGENT_KEY, and every session there uses the same key. The cost, stated: whoever sets the secret holds the key in custody. It is the bootstrap trap again, in its smallest form. |
| An agent on a machine you run | A server, a scheduled job: the key stays in that machine's ~/.sg-send/keys/, as sgit keeps it, and lasts as long as the machine does. |
Many agents: a fleet key
Each agent you confirm is a link in the confirming key's record, and a record holds 200 live agents at most (rule 3, records are bounded). With many agents, make a fleet key in your vault (Agents tab): a second key, operated by you for a year, that confirms your agents. Your own record holds one link; the fleet's holds the rest; every agent's page still shows you at the root, operated by your fleet, operated by you. Several fleets, one per kind of work, keep each record small and make each kind separately revocable.
What "operated" means, and does not
- It means: this key's owner says they run this agent, the agent says the same, and both statements are signed and in date. It is trusted when the person at the root is an anchor or verified.
- It does not say what the agent may do. That is a mandate, a separate statement, revoked separately: identity and mandate is the design, kept from the agent register.
- It does not prove the agent behaves. A signature proves which key signed, and the register says who answers for that key.
- An agent with no operator is listed, and nothing more. Agents are counted apart from people, so the number to watch stays the number of people.
The first one
The session that built this page made a session key with this tool and put its record in the register, naming no operator: its operator, Dinis Cruz, is not in the register yet. When he is, he confirms it from his vault, or the next session does the same in four commands. Its record: in the register, kind agent.