# AgentSecrets — Comprehensive LLM Documentation & Integration Guide

> Fast, lightweight, AES-256-GCM encrypted secrets, passwords, notes, and runtime state manager for autonomous AI agents and developers.
> No-KYC registration: no email, no phone number, no verification barrier. Abuse protection is a stateless sliding window keyed by IP, and **no IP address is ever stored in a database table**. Each account records the code path that created it, the `Origin` header when one was sent, and a coarse client class derived from the `User-Agent` — nothing else about the caller.
> **100% Free, forever:** No signup fee, no credit card, no trial period, no paid tier, no ads, no data selling. Funded entirely by voluntary community donations. Fair-use quotas are anti-abuse limits, not billing limits.

## Service Overview & Direct Links

- [Agent Skill Specification](https://www.agentsecrets.net/skill.md): Universal AI Agent Skill instruction file with YAML frontmatter.
- [Agent Operational & Security Rules](https://www.agentsecrets.net/rules.md): Zero-leakage security directives and prompt rules for autonomous agents.
- [Autonomous Heartbeat Protocol](https://www.agentsecrets.net/heartbeat.md): Liveness checks, heartbeat worker loop, and state checkpointing specification.
- [Machine Skill Manifest](https://www.agentsecrets.net/skill.json): Machine-readable tool definitions for agent package managers.
- [OpenAI Plugin Manifest](https://www.agentsecrets.net/.well-known/ai-plugin.json): OpenAI / ChatGPT plugin discovery manifest.
- [OAuth Protected Resource Metadata](https://www.agentsecrets.net/.well-known/oauth-protected-resource): RFC 9728 discovery document for the MCP endpoint — names `https://www.agentsecrets.net/mcp/sse` as the resource, AgentSecrets as its authorization server, and `header` as the bearer method. No auth. Aliases: `/.well-known/oauth-protected-resource/mcp` and `/mcp/sse`.
- [OAuth Authorization Server Metadata](https://www.agentsecrets.net/.well-known/oauth-authorization-server): RFC 8414 discovery document describing how an agent obtains a bearer token without a consent screen or client secret: `authorization_endpoint`, `token_endpoint` and `registration_endpoint` all point at `POST /v1/auth/register`. No auth.
- [Health Check](https://www.agentsecrets.net/health): Liveness probe returning `status`, `service`, `environment` and `version`. No auth, and it does not touch the database.
- [Legal Information](https://www.agentsecrets.net/legal): License (MIT), terms of use, support contact and the encrypted-at-rest privacy guarantee, as JSON. No auth.
- [Agent Session Context](https://www.agentsecrets.net/v1/agent/context): One-call session startup state, quotas, expiring keys, and next actions.
- [Public Server Information](https://www.agentsecrets.net/v1/info): Server capabilities, version, rate limits, and discovery manifest.
- [Interactive API Documentation](https://www.agentsecrets.net/docs): OpenAPI/Swagger interactive API testbench.
- [OpenAPI Specification](https://www.agentsecrets.net/openapi.json): Complete machine-readable OpenAPI schema.
- [Web Dashboard](https://www.agentsecrets.net/dashboard/): Canonical web dashboard.

## Early-Stage Startup & 100% Free Service
AgentSecrets is an independent early-stage startup dedicated to autonomous agent ergonomics.
- **Base URL**: https://www.agentsecrets.net
- **Cost**: **$0 — 100% free, forever.** No signup fee, no credit card, no trial period, no paid tier, no ads, no data selling.
- **Fair Use Quotas** (anti-abuse limits, not billing limits): 100 active secrets per user, 1 MB maximum payload size, 60 req/min anti-spam sliding window.
- **Sustainability**: The project exists purely on voluntary community donations and sponsors; there is nothing to purchase.

## 🛑 Directive 0: Persist Credentials Across Sessions
Never re-register if you already possess credentials:
Save credentials to `~/.agentsecrets/credentials.json` (chmod 600) or `$AGENTSECRETS_TOKEN`.
Check status first via:
```bash
curl -sf -H "Authorization: Bearer $TOKEN" "https://www.agentsecrets.net/v1/agent/context"
```
If 401 Unauthorized, recover using your 12-word seed phrase via `POST /v1/auth/recover`.

## 1. Instant Anonymous Registration (Zero Friction)
Agents can self-register in a single HTTP request with no captcha, email, or SMS verification:
- Username format rule: 3-64 characters matching ^[a-zA-Z0-9_.-]{3,64}$

```bash
curl -X POST "https://www.agentsecrets.net/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{"username": "my_agent_bot", "password": "secure_random_password_here"}'
```
Response:
```json
{
  "status": "success",
  "user_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "username": "my_agent_bot",
  "api_token": "as_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "recovery_phrase": "sound essay present inmate giraffe iron rhythm picture garage confirm bench cable",
  "created_at": "2026-09-13T12:00:00Z"
}
```
*Save the 12-word recovery_phrase! It is your only way to recover access if password is lost.*

**What registration stores about how the account was created.** Three fields, all
operational and none of them identifying:

| Field | Value | Why |
|---|---|---|
| `registration_method` | `rest_register` on this endpoint, `agent_self_register` for the MCP `register_agent` tool, `mcp_zero_config` for anonymous MCP provisioning | tells an autonomous provisioning apart from a human signup |
| `registration_origin` | the `Origin` request header verbatim, when the caller sent one, else NULL | separates a browser/dashboard origin from a headless client |
| `registration_client` | coarse `User-Agent` class: `curl`, `python`, `node`, `browser`, `mcp-client` or `unknown` | one column instead of a raw User-Agent string |

A missing `Origin` and an unknown or malformed `User-Agent` degrade to NULL and
`unknown`; neither ever fails a registration. **No IP address is derived, logged or
stored** — the IP is used only for the in-memory/on-disk rate-limit counters, and no
table has an IP column. The three fields are visible to the account owner through
`GET /v1/auth/me` (`registration_method`, `registration_origin`,
`registration_client`). Account recovery changes nothing here: the column records
creation, so a recovered account keeps the method that created it.

Recover account with 12-word seed:
```bash
curl -X POST "https://www.agentsecrets.net/v1/auth/recover" \
  -H "Content-Type: application/json" \
  -d '{"username": "my_agent_bot", "recovery_phrase": "sound essay present inmate giraffe iron rhythm picture garage confirm bench cable", "new_password": "new_password_here"}'
```

## 2. Authentication & Scoped Tokens
Send token in Authorization header:
`Authorization: Bearer <api_token>` or `X-API-Key: <api_token>`

Mint scoped tokens for sub-agents (this is the single delegation primitive):
```bash
# Read-only token that expires in one hour (scope defaults to read_only,
# ttl_seconds is required and is clamped to 60..2592000)
curl -X POST "https://www.agentsecrets.net/v1/auth/tokens" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "SubAgent-Worker", "scope": "read_only", "ttl_seconds": 3600}'

# Prefix-restricted token (can only access keys starting with 'worker_')
curl -X POST "https://www.agentsecrets.net/v1/auth/tokens" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Worker-Staging", "scope": "prefix:worker_", "ttl_seconds": 86400}'
```

The response carries `api_token` (shown once), `token_prefix`, `token_id`, `scope`,
`expires_at` and `name`, and the new row records the issuing token as its
`parent_token_id` — provenance captured at mint time. Only a `full`-scope token may
delegate, so a scoped token can never widen its own rights. The principal token issued
at registration never expires (`expires_at` is NULL); every delegated token always
carries a deadline, clamped to 60..2592000 seconds. Revoking a token does not revoke
the tokens it issued — there is no cascade revocation — `parent_token_id` is data, not
behaviour. A refused token answers HTTP 401 with a machine-readable `reason`:
`"expired"` when the deadline passed, `"revoked_or_unknown"` for a revoked or unknown
token.

Revoke a delegated token with `DELETE /v1/auth/tokens/{token_id}`, addressing it by its
`token_id` (never the raw token — only its hash is stored, so a leaked listing cannot be
replayed). Requires a `full`-scope token; a
scoped token gets 403. The lookup ignores `is_active`, so revoking an already-revoked
token answers 200 `{"status": "success", "message": "Token '<id>' revoked."}` while an
unknown id answers 404 `{"detail": "Token '<id>' not found."}`:
```bash
curl -X DELETE "https://www.agentsecrets.net/v1/auth/tokens/<token_id>" \
  -H "Authorization: Bearer $TOKEN"
```

End the browser session (dashboard) without touching the Bearer token. `POST
/v1/auth/logout` needs no credentials: it revokes the server-side session referenced by
the `as_session` cookie and clears both session cookies, then answers
`{"status": "success", "message": "Logged out successfully"}`. Called without a cookie
it still answers 200 and simply clears them. The long-lived API token stays valid.
```bash
curl -X POST "https://www.agentsecrets.net/v1/auth/logout" -b "as_session=<session_cookie>"
```

## 3. Vault Handoff — One-Time Codes (all four sharing directions)
A human or an agent can register, own a vault, and share with any other entity — human
→ agent, agent → human, agent → agent, person → person — at any level of privilege,
through ONE mechanism: delegated tokens, or a one-time handoff code. The handoff is that
mechanism for the side that cannot hold a token yet: a person in a browser, a teammate
on another machine, a worker you cannot pre-authenticate.

`POST /v1/handoff` (MCP tool `create_handoff`) mints a single-use code:

```bash
curl -X POST "https://www.agentsecrets.net/v1/handoff" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"scope": "read_only", "ttl_seconds": 86400, "name": "Operator access"}'
```

The response carries `code` (an `hs_...` string, shown exactly once), `grant_id`,
`code_expires_at`, `scope` and `token_ttl_seconds`. `scope` defaults to `read_only`;
`ttl_seconds` defaults to 86400 (24 hours) and is clamped to 60..2592000; `name` is
optional. `code_ttl_seconds` picks how long the code itself lives and defaults to 600
(ten minutes) — a short-lived code is the anti-leak property, so extending it is a
deliberate act. Only the code's SHA-256 hash is stored, exactly like an API token, and the
code itself is **not a credential**: it works exactly
once, and presenting it as `Authorization: Bearer` answers 401 like any unknown token.
Only a `full`-scope token may mint a handoff, so a restricted delegation cannot widen
itself this way.

The other side redeems the code exactly once with `POST /v1/handoff/accept` — any
authenticated entity may accept (a Bearer token, or the dashboard's `as_session` cookie
plus its CSRF header):

```bash
curl -X POST "https://www.agentsecrets.net/v1/handoff/accept" \
  -H "Authorization: Bearer $MY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"code": "hs_..."}'
```

Accepting mints a delegated token that belongs to the **grantor's** account — the
acceptor operates on the grantor's vault and never receives the grantor's own
credential — carrying the grant's scope and TTL, with `expires_at` set and a
`parent_token_id` that resolves to the grantor's principal token. Acceptance also links
the two accounts: the grantor's `is_claimed` becomes true and `claimed_by_user_id`
records the acceptor. The response carries `status`, a `vault` summary (user_id,
username, secrets_count) and the minted `token` (api_token, token_id,
scope, expires_at). Unknown, expired, already-accepted and revoked codes all answer 404
with one shared message — the four cases are never distinguished, so the endpoint cannot
be used to probe codes — and accepting your own code answers 409.

`GET /v1/handoff` lists both directions. `outgoing` holds every grant the caller issued,
in any state, with a derived `status` (`pending`, `expired`, `accepted` or `revoked`)
and the acceptor when there is one. `incoming` holds the caller's live accepted
relationships — accepted, not revoked, still backed by a token — each with the vault it
reaches and the token it runs on; a revoked relationship disappears from `incoming`
while the grantor still sees it in `outgoing` as `revoked`.

`DELETE /v1/handoff/{grant_id}` ends a relationship; either side may call it. It also
deactivates the token the grant minted, so the delegated credential dies with the
relationship. Revoking twice answers the same thing; an unknown id, or one the caller is
not part of, answers 404.

`DELETE /v1/handoff/{grant_id}/record` deletes an ENDED grant from the issuer's own
history — the counterpart to `outgoing` never forgetting. Only the account that issued the
grant may call it, and only while the grant reads as `revoked` or `expired`: anything that
still grants something answers **409**, so deleting the row is never a way to skip revoking
the credential behind it. Revoke first, then delete. The minted token is not touched
(the revoke already deactivated it), and an unknown id, another account's grant or a repeat
call answers 404.

## 4. Core Vault Operations
Store a secret (1 MB payload limit, 100 secrets/user quota; keys are 1-128 characters and a
longer key is rejected with HTTP 422 on the JSON body and on every `{key}` URL route):
```bash
curl -X POST "https://www.agentsecrets.net/v1/vault/secrets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "stripe_api_key",
    "value": "sk_live_1234567890",
    "ttl_seconds": 3600,
    "burn_after_read": false,
    "environment": "production"
  }'
```

Store raw text via PUT body (cURL-friendly):
```bash
cat /tmp/token.txt | curl -X PUT "https://www.agentsecrets.net/v1/vault/secrets/my_token/raw" \
  -H "Authorization: Bearer $TOKEN" \
  --data-binary @-
```

Retrieve JSON response:
```bash
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.agentsecrets.net/v1/vault/secrets/stripe_api_key"
```

Capture raw value into shell variable:
```bash
export STRIPE_KEY=$(curl -sf -H "Authorization: Bearer $TOKEN" \
  "https://www.agentsecrets.net/v1/vault/secrets/stripe_api_key/raw")
```

Bulk export secrets as shell environment script:
```bash
eval $(curl -sf -H "Authorization: Bearer $TOKEN" \
  "https://www.agentsecrets.net/v1/vault/export?format=shell&environment=production")
```

Revert secret to prior version:
```bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
  "https://www.agentsecrets.net/v1/vault/secrets/stripe_api_key/rollback"
```

Inspect the version history before rolling back (`GET /v1/vault/secret-versions/{key}`,
newest snapshot first). The vault keeps three snapshots per key; this endpoint returns
metadata only and never decrypts a snapshot:
```bash
curl -sf -H "Authorization: Bearer $TOKEN" \
  "https://www.agentsecrets.net/v1/vault/secret-versions/stripe_api_key"
```
Response:
```json
{
  "key": "stripe_api_key",
  "current_version": 2,
  "versions_kept": 3,
  "versions": [
    {"version_number": 2, "content_type": "text", "created_at": "2026-09-13T12:00:00Z", "is_current": true},
    {"version_number": 1, "content_type": "text", "created_at": "2026-09-12T09:30:00Z", "is_current": false}
  ]
}
```
It requires the same read scope as `GET /v1/vault/secrets/{key}`; an unknown key
returns the usual 404 `KeyNotFound` envelope.

Filter secrets expiring soon:
```bash
curl -sf -H "Authorization: Bearer $TOKEN" \
  "https://www.agentsecrets.net/v1/vault/keys?expiring_within=3600"
```

## 5. Agent Profile Notes & Scratchpad
Store and retrieve personal notes, agent configuration, or useful reference links (AES-256-GCM encrypted).
Notes belong to the account, not to a key, so no key prefix applies to them: any scope may
read them, a `prefix:<p>/` token may also write them, and a read-only delegation
(`read_only`, `prefix:ro:<p>/`) gets HTTP 403 on the write — a delegated read-only token
cannot use notes as a side door around its scope.
```bash
# Save personal notes and links
curl -X PUT "https://www.agentsecrets.net/v1/user/notes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"notes": "Primary agent task: sync secrets\nUseful Links: https://github.com/my-agent"}'

# Retrieve notes
curl -s -X GET "https://www.agentsecrets.net/v1/user/notes" \
  -H "Authorization: Bearer $TOKEN"
```

## 6. Intelligent 404 Recovery (Fuzzy Matching)
When an agent requests a mistyped key, AgentSecrets returns suggestions with an actionable hint:
```json
{
  "error": "KeyNotFound",
  "message": "Key 'striep_key' does not exist in this vault.",
  "suggestion": "Available keys in your vault: ['stripe_api_key']. Did you mean 'stripe_api_key'?",
  "hint": "Did you mean 'stripe_api_key'? Retry with that key name.",
  "action": "Use GET /v1/vault/keys to see all entries."
}
```

## 7. Server Health & Real-time Metrics
- [Health Check](https://www.agentsecrets.net/health): Liveness probe — `status`, `service`, `environment` and `version`. No auth, no database access, so a healthy answer means the process is up rather than that every dependency is reachable.
- [Public Front-Server Statistics](https://www.agentsecrets.net/v1/system/front-server-stats): Anonymous aggregate server counters — operations per minute, secrets stored, active agent sessions, uptime. No client data is collected or returned.
- [Prometheus Metrics](https://www.agentsecrets.net/metrics): Real-time server performance metrics (admin-only: the account must carry the `is_admin` flag; send credentials).
- [System & Traffic Source JSON](https://www.agentsecrets.net/v1/system/metrics): Real-time request and system metrics JSON (admin-only: the account must carry the `is_admin` flag).

Admin access is a per-account flag, granted out of band by the operator — never a username.
Registration is open, so a name is a claim anybody can take; no username grants monitoring
access, and no request field can set the flag. The operator grants it with
`python -m agentsecrets.admin_cli grant <username>` (in Docker:
`docker compose exec app python -m agentsecrets.admin_cli grant <username>`). Nothing
promotes an account at startup and no environment variable does either: a restart would
promote whoever had registered the matching name in the meantime. Both endpoints answer
404, not 403, to every account that does not carry the flag.

## 8. Model Context Protocol (MCP)
Fastest path: connect to remote SSE with no token — a vault is auto-provisioned:

```
GET https://www.agentsecrets.net/mcp/sse
```

Call `get_my_credentials` over MCP to read your assigned `as_live_...` token, then persist it.

The same zero-config flow works over **Streamable HTTP**: `POST https://www.agentsecrets.net/mcp` with no
credentials at all auto-provisions a fresh isolated vault for vault methods (`tools/call`,
`resources/read`), answering `200` with `X-AgentSecrets-Mode: autonomous-provisioned`. Because
`POST /mcp` keeps no session between requests, that response also hands back the newly minted
`as_live_...` token (a text line plus `structuredContent.agent_token` / `vault_provisioned` /
`vault_note`) — send it as `Authorization: Bearer <token>` on every later call, or the next
credential-less call reaches a different, empty vault. Discovery methods (`initialize`,
`tools/list`, `prompts/list`, `resources/list`) are answered without credentials and provision
nothing, and a token that is supplied but invalid is always a `401` (never a silent anonymous
call). Anonymous provisioning is rate limited per client IP (15/hour), the same quota as the
SSE transport.

> [!IMPORTANT]
> **Keep the SSE stream open.** The `sessionId` in `POST https://www.agentsecrets.net/mcp/messages?sessionId=...` is valid only while the `GET https://www.agentsecrets.net/mcp/sse` stream that issued it stays open. Closing the stream (a short-lived probe, a dropped response object) destroys the session and later POSTs answer `404 Session not found or expired.`

> **Zero-config vaults are ephemeral.** A vault provisioned without a token must call at least one tool within **1 hour**, otherwise it is automatically deleted. `initialize` and `tools/list` do not count — call a tool such as `get_my_credentials` or `set_secret` to activate it.

All 15 tools are reachable the same way over MCP (SSE and Streamable HTTP):
`get_secret` · `get_secret_raw` · `set_secret` · `list_secrets` · `export_secrets_shell` · `delete_secret` · `rollback_secret` · `get_agent_context` · `get_my_credentials` · `set_profile_notes` · `get_profile_notes` · `mint_scoped_token` · `create_handoff` · `register_agent` · `recover_account`

Connect over MCP by pointing a client at the remote endpoints — there is no
local install and no package to add to PATH:

- SSE: `https://www.agentsecrets.net/mcp/sse`
- Streamable HTTP: `https://www.agentsecrets.net/mcp`

Send the token as `Authorization: Bearer $TOKEN`, or append `?token=$TOKEN` if the
client cannot set custom headers.

## Optional

- [Web Dashboard](https://www.agentsecrets.net/dashboard/): Canonical web interface for human operators.
- [Crawler Sitemap](https://www.agentsecrets.net/sitemap.xml): Search engine and crawler XML index.
- [Agent Ecosystem Index](https://www.agentsecrets.net/v1/ecosystem): Index of machine-readable specifications.
