Registration & Verification

May 8, 2026 ยท View on GitHub

Registration turns a local AgentVeil identity into a backend-known agent DID. Verification proves that the holder of the local Ed25519 private key controls that DID. A local key alone is not enough for production Runtime Gate or signed API flows; the backend must know and verify the DID first.

Lifecycle

created locally
  -> register(...)
registered with backend
  -> proof-of-work + challenge signature
verified DID
  -> optional onboarding/card pipeline
ready for integration_preflight() and controlled_action(...)

State meanings:

StateMeaning
CreatedLocal Ed25519 key and did:key exist. Nothing has been submitted to the backend yet.
RegisteredBackend has accepted the DID registration request.
VerifiedBackend has verified key ownership through challenge signing and proof-of-work.
OnboardedOptional capability-card/onboarding pipeline has completed. This is separate from DID verification.

agent.is_registered and agent.is_verified are local cached booleans. They are set after register(...) succeeds and saved with the agent file. Before a controlled action, prefer agent.integration_preflight() because it checks the live API, registration state, verification state, agent status, and a safe signed request.

Register

def register(
    self,
    display_name: str | None = None,
    capabilities: list[str] | None = None,
    endpoint_url: str | None = None,
    provider: str | None = None,
) -> dict

Parameters:

ParameterMeaning
display_nameHuman-readable name shown in agent metadata. Defaults to the local agent name.
capabilitiesOptional capability labels. Supplying these can start the onboarding pipeline after verification.
endpoint_urlOptional URL where this agent can be reached.
providerOptional LLM/provider label such as anthropic or openai.

register(...) performs three steps in one call:

  1. POST the public key and optional card metadata.
  2. Solve the registration proof-of-work challenge.
  3. Sign the server challenge and verify key ownership.

On success, it returns the registration response with an added onboarding_pending boolean, marks the local agent as registered and verified, and saves the agent file. It no longer waits for onboarding completion. Current SDK versions do not accept a passphrase argument on register(...); call agent.save(passphrase=...) after registration if the production key should be stored encrypted.

Expected failures use SDK exception types:

ExceptionCommon cause
AVPValidationErrorDuplicate/conflicting DID, invalid input, or backend validation failure.
AVPAuthErrorSigned follow-up request is forbidden or invalid.
AVPRateLimitErrorRegistration or trust-gate rate limit. Inspect retry_after.
AVPServerErrorBackend dependency/configuration issue or malformed server response.
httpx.RequestErrorNetwork, DNS, TLS, or timeout failure before a response is returned.

See Error Handling for the full SDK exception hierarchy, HTTP status mapping, and recovery patterns.

Onboarding

Registration/verification and onboarding are different.

register(...) verifies DID ownership and returns immediately after the verification step. If capabilities are supplied, the backend may start an onboarding/card pipeline in the background.

Use:

challenge_result = agent.auto_answer_onboarding_challenge(max_wait=30.0)
status = agent.wait_for_onboarding(timeout=60.0, poll_interval=2.0)

auto_answer_onboarding_challenge(...) is explicit opt-in. It polls for a challenge, submits a stock SDK answer when a challenge is available, and returns the challenge result or None if no challenge is available.

wait_for_onboarding(...) blocks until completed, failed, or not_started, then returns the final status dictionary. Only completed means success. not_started means there is no onboarding session to wait for.

Common Patterns

PatternFlowNotes
First-time setupAVPAgent.create(...) -> register(...) -> integration_preflight()Use this for a new production DID.
Reload existing agentAVPAgent.load(..., passphrase=...) -> integration_preflight()Use the same name and passphrase that saved the key.
Re-registration after key rotationold_agent.migrate(new_agent) -> use new_agentMigration is for DID succession; do not keep using the old DID after success.
Headless / CI setupregister(..., capabilities=[...]) -> optional auto_answer_onboarding_challenge(...)Avoid interactive prompts. Keep passphrases in your secret manager.

Passphrase Security

By default, SDK agent files live under:

~/.avp/agents/{name}.json

Use a passphrase when storing production keys:

agent = AVPAgent.create("https://agentveil.dev", name="release-agent", save=False)
agent.register(display_name="Release Agent")
agent.save(passphrase=os.environ["AVP_AGENT_PASSPHRASE"])

If saved with a passphrase, AVPAgent.load(...) requires the same passphrase. Without a passphrase, the local private key is stored as plaintext hex with owner-only file permissions. There is no passphrase recovery in the SDK. Keep the passphrase in your credential manager or CI secret store. If the passphrase and private-key backup are both lost, create a new DID and use migrate(...) only if the old key is still available to sign the migration.

Never commit ~/.avp/agents/*.json, raw private keys, passphrases, or CI secrets to a repository.

Error Cases And Recovery

CaseWhat you seeRecovery
Network failure during registrationhttpx.RequestError before an SDK response existsCheck base_url, DNS/TLS, proxy settings, and retry once connectivity is stable.
Proof-of-work is slowregister(...) spends time solving PoWTreat this as normal anti-abuse work. If it never completes, inspect CPU limits and retry.
Backend returns malformed registration dataAVPServerError mentioning a missing challenge, pow_challenge, or pow_difficultyStop and inspect backend health/configuration.
Duplicate DID or conflicting stateAVPValidationError with Conflict: ...Load the existing saved agent if this DID is yours; otherwise create a fresh identity.
Onboarding challenge unavailableauto_answer_onboarding_challenge(...) returns None or wait_for_onboarding(...) returns not_startedContinue with DID verification checks, or publish capabilities/card data to start onboarding.
Challenge expired or rejectedChallenge answer result shows failure, or status becomes failedRe-run onboarding or register a new capability card depending on backend guidance.
Mismatched local key and DIDintegration_preflight() reports signature_invalidLoad the correct saved key or restore from a known private-key backup.

Next Steps

After registration is ready:

  1. Run agent.integration_preflight().
  2. Obtain or issue a DelegationReceipt for the intended action scope.
  3. Call controlled_action(...).
  4. Export and verify Proof Packets with Proof Packet Guide.

See Customer Integration for the controlled-action path and DelegationReceipt Guide for delegation issuance and verification.