Get an identity — managed or bring-your-own-key
Every agent is a did:hedera or did:key document whose Ed25519 public key is the verification method. What differs is who ever holds the private key: MetaMynd, once, at issuance — or only you, proven rather than trusted.
Managed — MetaMynd generates the key
POST /onboarding/agent (or npx create-metamynd-agent, no --byok flag) generates the Ed25519 keypair, returns the private key once in the response, and stamps the agent as key-proven immediately — control was established at issuance, so no separate proof step is needed. This is the default for the sandbox and for most first integrations: fastest to a working agent, at the cost of MetaMynd having seen the key at generation time.
Bring your own key — you generate it, you keep it
Register the public half of a key you generated yourself and never sent anywhere. Until you prove control, the gate refuses every action from that DID with AGENT_KEY_UNVERIFIED — an unproven key makes the signature check meaningless, since nobody has shown the key belongs to the party claiming it. Proof is a signed challenge, not a key upload.
- POST /agent-identity/:ref/verify-key — the gate issues a challenge; you sign it with the key you already hold; the gate verifies against the public key on file
- POST /agent-identity/:ref/network-identities/:id/regenerate-challenge — a fresh challenge if one expired before you signed it
- The private key never leaves your process — not at registration, not at proof, not after
A third option: keep the key out of the guard's own process too
@metamynd/agentsafe-signer is a separate daemon that holds a BYOK key and signs on request over a local socket or named pipe — so a compromise of the agent process that embeds the guard doesn't hand over the signing key with it. It's an early implementation pass, not the finished design; its own README states exactly what's verified today and what's still open.
A fourth option: bring your own did:key (skip Hedera entirely)
Pass did instead of publicKey and MetaMynd never touches Hedera for that identity at all: no account mint, no HCS anchor, no VC. A did:key is self-certifying — the Ed25519 public key IS the identifier — so issuing one costs nothing and needs no Hedera network access to create. It is still proven the same way as BYOK (verify-key, below): the gate refuses every action from that DID with AGENT_KEY_UNVERIFIED until you sign the challenge. A did:key identity is always testnet-scoped — never mainnet, never counted against the free-tier cap — trading Hedera's on-chain anchoring for an identity you can create anywhere, including where Hedera itself is unreachable.
- POST /agent-identity (or /onboarding/agent) with { "did": "did:key:z6Mk..." } in place of publicKey
- Same proof-of-possession step as bring-your-own-key: POST /agent-identity/:ref/verify-key
What verification actually means
Key-proven and principal-verified are different facts. A testnet or did:key agent's principal is reported, not required — no KYC/KYB needed for a sandbox or an evaluation. A mainnet agent's principal MUST be verified by a mainnet-eligible provider before the identity can be created at all, and stays within free-tier caps (1 mainnet agent per owner, 5 active mandates) beyond which the gate refuses with PRINCIPAL_UNVERIFIED. Every verdict carries the principal's verification status and its basis (provider, manual_review, self_approved or unrecorded) — self_approved cannot create a mainnet agent, and a counterparty that needs a real identity check should look for provider or manual_review, not just verified: true.
See it in code
# 1. Generate your own Ed25519 keypair locally — it never leaves this machine.
# 2. Register the PUBLIC key and get a challenge back.
curl -X POST https://metamynd.ai/api/v1/onboarding/agent \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "name": "Support Bot", "scope": "flight-purchase", "publicKey": "'"$PUBLIC_KEY_HEX"'" }'
# -> { agentDid, mandate, bundleUrl, ... } — agentKey is absent; you already hold it.
# 3. Sign the challenge and prove control before the gate accepts anything from this DID.
curl -X POST https://metamynd.ai/api/v1/agent-identity/$AGENT_REF/verify-key \
-H "Content-Type: application/json" -d '{ "signature": "'"$SIGNED_CHALLENGE"'" }'
# Until this succeeds: every authorize call -> block / AGENT_KEY_UNVERIFIED.