Generate or rotate the SDK API key for an agent.
If an active (non-revoked) key already exists for the agent, this
endpoint revokes it and inserts a new active row in a single
transaction. The new full_key is returned exactly once in the
response; the plaintext secret is never persisted server-side, only
its bcrypt hash.
Args:
agent_id: Path parameter; the target agent’s primary key.
current_user: Resolved from the Authorization: Bearer <JWT>
header by get_current_user.
db: SQLAlchemy session injected by FastAPI.
Returns:
:class:APIKeyGenerateResponse containing full_key (one-shot
plaintext), key_prefix, and created_at.
Raises: HTTPException 401: missing or invalid JWT. HTTPException 404: agent does not exist or does not belong to the caller (deliberate to avoid leaking agent existence). HTTPException 500: any unexpected error; transaction rolled back. The most plausible internal failure is a partial-unique index violation from a concurrent POST race, which the DB enforces.
Notes:
auth.setup_admin and
custom_api.create_custom_api — we collect all writes in the
session and commit once. There is no SELECT ... FOR UPDATE;
concurrent rotations are caught by the
uq_agent_api_keys_agent_active partial unique index and
surfaced as a 500. Two clients racing to rotate the same key is
a corner case; a 500 is acceptable.key_prefix only — never the full_key,
the secret half, or the bcrypt hash.Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Successful Response
Response model for POST /api/agents/{agent_id}/api-key.
The full_key is plaintext and returned exactly once per
rotation. Clients (the web UI) must show it to the agent owner
immediately and warn that it will not be retrievable later. The
server only persists bcrypt(full_key) in agent_api_keys.key_hash;
the plaintext leaves this response and is never written to disk
server-side.
Plaintext API key in the format xag_<6 chars>_<32 chars>. Returned exactly once; cannot be retrieved later.
Public-safe 6-char lookup handle. Same value embedded in the full_key middle segment; returned separately so the UI does not have to re-parse the full key.
UTC timestamp when the new key was persisted.