Agent Identity
← GUIDES · SECURITY

How should an AI agent store and use API keys and other secrets?

By Naol Ketema, founder · · Markdown

SHORT ANSWER

Keep secrets out of the model's context and out of anything the agent can read and repeat, and hand them to the agent only at the moment it needs one, for one operation. On Agent Identity, the vault encrypts a secret to the agent's own public key on the client, so the server never sees plaintext, and the agent redeems a single-use, short-lived lease to decrypt it locally.

Why agents make secret handling harder

A traditional service reads an API key from an environment variable and that is the end of it. An agent is different: it reads untrusted input, decides what to do with a language model, and can be talked into revealing what is in its context. Any secret the model can see, it can repeat.

  • A secret pasted into a system prompt is one prompt injection away from an email reply.
  • A tool that returns a config file or environment dump can leak every key at once.
  • A long-lived key shared by all agents means one leak exposes all of them.
  • Logs and traces of model calls often capture tool arguments, including credentials.

Rules that hold regardless of tooling

  • Never put a secret in the prompt. Let code that runs outside the model attach it to the outgoing request.
  • Give each agent its own credentials, so revoking one does not break the others.
  • Fetch a secret at the point of use and drop it afterwards, rather than holding it for the life of the process.
  • Record each access, so you can answer who used which secret and when.
  • Keep the decrypting key on the agent's side, so a breach of the secret store alone yields only ciphertext.
  • Prefer secrets the agent can lose cheaply: restricted provider keys with only the permissions the task needs, and spending limits where the provider offers them.

How the Agent Identity vault works

The vault's invariant is that the server never holds a private key and never sees plaintext. Encryption and decryption happen in the @agentidentity/sdk package on your machine, using ECIES over X25519. The API endpoints do not accept plaintext at all.

  • Step 1: register a vault keypair for the agent with generateIdentityKey. The private key is returned once and never sent anywhere. Store it where only the agent runtime can read it.
  • Step 2: create the secret with the org key. The SDK encrypts it to the agent's public key before it leaves your process.
  • Step 3: when the agent needs it, it creates a lease with its own key, naming the operation and a time to live.
  • Step 4: it redeems the lease, gets the encrypted envelope and decrypts it locally.
import { AgentClient } from "@agentidentity/sdk";

const base = "https://api.agent-identity.dev";
const org = new AgentClient({ baseUrl: base, apiKey: process.env.AID_ORG_KEY! });
const asAgent = new AgentClient({ baseUrl: base, apiKey: process.env.AID_AGENT_KEY! });
const agentId = process.env.AID_AGENT!;

// Once per agent. The private key is returned once; keep it with the agent runtime.
const keypair = await asAgent.vault.generateIdentityKey(agentId);

// Setup, with the org key: encrypted on this machine before it is sent.
const secret = await org.vault.createSecret({ identityId: agentId, name: "stripe", plaintext: process.env.STRIPE_KEY! });

// At the point of use, with the agent's own key.
const lease = await asAgent.vault.createLease(secret.id, { operation: "charge", ttlSeconds: 60 });
const { secret: plaintext } = await asAgent.vault.redeemLease(lease.leaseId, keypair);

Use the secret without showing it to the model

The model should ask for an action, not for a key. Expose a tool such as charge_customer(customerId, amountCents). The tool's code creates a lease, decrypts the key, makes the API request and returns only the result. The decrypted value never enters the prompt, the tool result or your traces, so an injected instruction to print it has nothing to print.

Leases, rotation and recovery

  • A lease is single-use. Redeeming it twice fails, and so does redeeming after it expires; create a new one.
  • ttl_seconds defaults to 60 and is clamped between 1 and 3600. A request for a day silently gets an hour.
  • Create leases at the point of use. A crash between redeeming and decrypting burns the lease.
  • An agent can only lease and redeem its own secrets. Another agent's secret reads as 404.
  • The org key creates and lists secrets and can list leases with GET /v1/vault/leases. Only the owning agent fetches envelopes and rotates.
  • There is no key escrow. If the private key is lost, the secrets encrypted to it cannot be recovered; register a new keypair and re-create them from source.

Call generateIdentityKey once. Calling it again overwrites the registered public key and orphans every secret encrypted to the old one. To check whether a key exists, read vault_public_key from GET /v1/identities, which is null until one is registered.

When a general secrets manager is enough

If your agents run on infrastructure you already secure, and a cloud secrets manager with per-workload access is in place, keep using it and apply the rules above: no secrets in prompts, per-agent credentials, fetch at use. The vault is useful when you want the secret tied to the agent identity, encrypted so the host never sees it, and handed out one operation at a time with a record of each lease.

FAQ

Can Agent Identity read the secrets in the vault?

No. Secrets are encrypted on the client to the agent's public key, and the server never holds a private key or sees plaintext.

What happens if I lose the agent's vault private key?

The secrets encrypted to it cannot be recovered. Register a new keypair and re-create each secret from its original source.

How long does a lease last?

60 seconds by default, between 1 second and 1 hour. It can be redeemed once.

Should the language model ever see the decrypted secret?

No. Decrypt it in code that makes the outgoing request, and keep it out of the model's context, tool results and logs.

Related guides

Give your agent its own identity in a couple of minutes. Get started free → · Docs · All guides