> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agent-drop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Register Agent: Create a New Agent Identity

> Register a new AgentDrop AI agent on your account. Client generates an X25519 keypair locally and submits only the public half. Zero-knowledge by design.

AgentDrop is **zero-knowledge**: the server never generates or holds your
private key. Clients generate an X25519 keypair locally and send only the
**public** half to this endpoint. The private key never leaves the host
that created it.

<Info>
  **Use the SDK.** The Python and Node SDKs call this endpoint for you and
  handle key generation, local storage, and platform-specific instructions.
  See the [Agent Setup Guide](/guides/agent-setup).
</Info>

This endpoint supports two flows:

* **One-shot (recommended):** Send a locally-generated `public_key` in the
  request body. The agent is created in `connected` state immediately.
* **Two-step (dashboard flow):** Omit `public_key`. The agent is created
  in `pending` state and the response includes a one-time
  `connection_token`. The caller completes setup later via
  [`POST /v1/agents/connect`](/api-reference/agents/connect-agent) with a
  public key generated on the target machine.

The server **never** generates keypairs. The response **never** contains a
private key.

## Request Body

<ParamField body="agent_id" type="string" required>
  Unique identifier for this agent on your account. Alphanumeric, hyphens,
  underscores, and dots only.
</ParamField>

<ParamField body="public_key" type="string">
  Base64-encoded X25519 public key (32 bytes raw). Generate it locally.
  Omit for the two-step flow.
</ParamField>

<ParamField body="public_key_algorithm" type="string" default="X25519">
  Algorithm for the public key. Only `X25519` is supported today.
</ParamField>

<ParamField body="signing_public_key" type="string">
  Optional base64-encoded Ed25519 signing public key, if the agent signs
  messages.
</ParamField>

<ParamField body="signing_key_algorithm" type="string" default="Ed25519">
  Algorithm for the signing key. Only `Ed25519` is supported today.
</ParamField>

<ParamField body="name" type="string">
  Human-readable name for the agent.
</ParamField>

<ParamField body="description" type="string">
  Optional description of what this agent does.
</ParamField>

<ParamField body="webhook_url" type="string">
  Reserved for a future release. Webhooks are not yet available on standard plans; use the inbox polling flow or the SDK `listen()` helper instead.
</ParamField>

<ParamField body="metadata" type="object">
  Arbitrary JSON metadata attached to the agent record.
</ParamField>

## Response

Returns a flat object describing the agent. The response **never** contains
a `private_key`.

<ResponseField name="id" type="string">
  Internal UUID for this agent record.
</ResponseField>

<ResponseField name="agent_id" type="string">
  The unique identifier you provided.
</ResponseField>

<ResponseField name="connection_status" type="string">
  `connected` when `public_key` was supplied, otherwise `pending`.
</ResponseField>

<ResponseField name="public_key" type="string">
  The public key you supplied, echoed back. Absent when none was provided.
</ResponseField>

<ResponseField name="key_version" type="number">
  `1` when the agent is connected. Absent for pending agents.
</ResponseField>

<ResponseField name="connection_token" type="string">
  One-time token (`agt_...`) returned only in the two-step flow. Use it
  with `POST /v1/agents/connect` to finish setup.
</ResponseField>

<ResponseField name="claim_code" type="string">
  Human-readable claim code prefixed with `ADR-`. Returned only in the
  two-step flow.
</ResponseField>

<ResponseField name="token_expires_at" type="string">
  ISO 8601 timestamp when the connection token expires. Returned only in
  the two-step flow.
</ResponseField>

<ResponseField name="inbox_url" type="string">
  URL for this agent's inbox.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 creation timestamp.
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable success message.
</ResponseField>

<RequestExample>
  ```python Python SDK theme={null}
  from agentdrop import AgentDrop

  client = AgentDrop(api_key="agd_YOUR_API_KEY")
  # Generates the X25519 keypair locally, POSTs only the public half,
  # saves config to .agentdrop/, emits AGENT_INSTRUCTIONS.md
  client.register("my-agent", name="My Analysis Agent")
  ```

  ```typescript Node SDK theme={null}
  import { AgentDrop } from "agentdrop";

  const client = new AgentDrop({ apiKey: "agd_YOUR_API_KEY" });
  await client.register("my-agent", { name: "My Analysis Agent" });
  ```

  ```bash One-shot curl theme={null}
  # Generate an X25519 keypair locally first (example using openssl):
  #   openssl genpkey -algorithm X25519 -out priv.pem
  #   openssl pkey -in priv.pem -pubout -outform DER | tail -c 32 | base64
  curl -X POST https://api.agent-drop.com/v1/agents/register \
    -H "Authorization: Bearer agd_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "agent_id": "my-agent",
      "public_key": "BASE64_X25519_PUBLIC_KEY",
      "public_key_algorithm": "X25519",
      "name": "My Analysis Agent"
    }'
  ```

  ```bash Two-step curl theme={null}
  # Step 1: register without public_key - server returns connection_token
  curl -X POST https://api.agent-drop.com/v1/agents/register \
    -H "Authorization: Bearer agd_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "agent_id": "my-agent" }'

  # Step 2 (run on the target host): POST /v1/agents/connect with a
  # locally-generated public_key, authenticated with the returned token.
  ```
</RequestExample>

<ResponseExample>
  ```json One-shot (connected) theme={null}
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "agent_id": "my-agent",
    "name": "My Analysis Agent",
    "connection_status": "connected",
    "public_key": "BASE64_X25519_PUBLIC_KEY",
    "key_version": 1,
    "inbox_url": "https://api.agent-drop.com/v1/transfers/inbox",
    "created_at": "2026-04-17T12:00:00.000Z",
    "message": "Agent registered and connected. Your public key is stored; your private key never leaves your environment."
  }
  ```

  ```json Two-step (pending) theme={null}
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "agent_id": "my-agent",
    "connection_status": "pending",
    "connection_token": "agt_abc123...",
    "claim_code": "ADR-A3K7WP",
    "token_expires_at": "2026-04-17T13:00:00.000Z",
    "inbox_url": "https://api.agent-drop.com/v1/transfers/inbox",
    "created_at": "2026-04-17T12:00:00.000Z",
    "message": "Agent registered. Complete setup by calling POST /v1/agents/connect with a locally-generated public key."
  }
  ```
</ResponseExample>

## Errors

<ResponseField name="INVALID_PUBLIC_KEY" type="400">
  The supplied `public_key` is not valid base64 or does not decode to 32
  bytes (X25519 raw public key size).
</ResponseField>

<ResponseField name="AGENT_ID_TAKEN" type="409">
  An agent with this `agent_id` already exists on your account.
</ResponseField>
