# Link with secret keys

A secret key is a P-256 signing key for one agent. The key is the complete
credential, so anyone who holds it can act as that agent, within the agent's
[policy](https://docs.catena.com/policies.md).

You'll use a secret key wherever `catena link` cannot keep a credential. Common
examples include:

- A cloud sandbox that starts fresh for each task (e.g., Claude, Codex, or
  Cursor cloud agents)
- A CI job
- A serverless function
- A service you deploy

If your agent runs on a machine or VM that keeps its home directory, we
recommend [`catena link`](https://docs.catena.com/connect/cli.md) instead.

## Create a key

1. In the console, open the agent from the **Agents** page.
2. Select the **Secret keys** tab, then click **Create secret key**.
3. Name the key for where it will run (such as `production-worker`).
4. Copy the key. We show it only once.

Creating and revoking keys requires the admin [role](https://docs.catena.com/team.md) and a signed-in
console session. An agent can hold several keys (for example, one per
deployment).

## Use a key

Set the key as `CATENA_SECRET_KEY` in the host's secret settings, where both the
CLI and the SDK read it:

```sh
export CATENA_SECRET_KEY=...
npx -y @catena/cli@latest whoami
```

```ts
import { createCatenaClient } from "@catena/sdk"

// Reads CATENA_SECRET_KEY when privateKeyHex is omitted.
const client = createCatenaClient()
const agent = await client.whoami()
```

There's no link step on the host. Each command signs with the key and does not
read a profile, unless the command passes `--profile`.

> [!NOTE] **Precedence over profiles**
>
> When `CATENA_SECRET_KEY` is set, it takes precedence over every linked profile
> on the machine, and only an explicit `--profile` overrides it. On a machine
> that also has a linked [profile](https://docs.catena.com/connect/cli.md#profiles), each command prints a
> line to stderr naming the credential it used.

## Revoke a key

You can revoke a key on the agent's **Secret keys** tab. Revocation takes effect
immediately and can't be undone, so anything that used the key will lose access.

Note that `catena unlink` does not apply to a secret key. To replace a key, we
recommend creating a new one, deploying it, and then revoking the old one.

If Catena rejects a key, the error names `CATENA_SECRET_KEY`. In that case,
create a new key and set the variable again. Running `catena link` does not
repair it.

## Provision a key from the terminal

An admin can also create a key for a deployment from their own machine. This is
useful when you want to check the key's thumbprint before approving, or when the
deployment generates its own keypair and its secret should stay on the
deployment.

```sh
catena link --service agent_...
```

1. The command prints the signing key's thumbprint. Check that it matches the
   approval screen before you approve.
2. After approval, it prints `CATENA_SECRET_KEY` once. Store it in the
   deployment's secret settings. (With `--public-key`, below, it prints no
   secret, since the deployment already holds it.)
3. If the deployment already generated its own keypair, pass its public key with
   `--public-key <hex>` and keep the secret where it is.

`--service` stores nothing on the machine you run it on. It's a setup step for a
person, and an agent that runs interactively in a terminal must use plain
`catena link`, including on a VM with no keychain. See
[Credential storage](https://docs.catena.com/connect/credentials.md) for where that key will live.

A key stays in the organization that first registered it. To move a service to
another organization, unlink it in the console, and then run
`catena link --service` from the right organization with a new keypair.

## Best practices

**Store the key in the host's secret settings.** The key is the complete
credential for the agent, so set it as `CATENA_SECRET_KEY` there.

**Name each key for where it runs.** An agent can hold several keys, for example
one per deployment, and a name such as `production-worker` shows which one is
which on the **Secret keys** tab.

**Deploy the replacement before you revoke.** Revocation takes effect
immediately, so create the new key and deploy it before you revoke the old one.

## Related

- [Cloud coding agents](https://docs.catena.com/integrations/cloud-agents.md): Connect Claude, Codex, and Cursor cloud agents and Copilot's coding agent to Catena with a secret key that the platform injects into each sandbox.
- [SDK reference](https://docs.catena.com/sdk.md): Setup, methods, intent actions, errors, and client options for @catena/sdk, the TypeScript client for the agent API.
- [Credential storage](https://docs.catena.com/connect/credentials.md): Where the CLI keeps an agent's signing key on each kind of host, and which credential mode to use when there's no keychain.
