# AgentCache API

AgentCache is a semantic answer cache for AI agents. Before calling a model or API, ask AgentCache whether you have already answered the same or a similar question. A hit returns the saved answer in milliseconds for $0.002; a miss is free; saving answers is free. It shares API keys and the prepaid wallet with Freshness Validator (https://api.myuiaf.com) and AgentPay (https://agentpay.myuiaf.com).

- Base URL: `https://cache.myuiaf.com`
- HTML docs: https://myuiaf.com/agentcache/docs
- OpenAPI: https://myuiaf.com/agentcache/openapi.json
- Overview and pricing: https://myuiaf.com/agentcache

## MCP server

`https://cache.myuiaf.com/mcp` (Streamable HTTP). Same features as MCP tools; send `Authorization: Bearer fv1...`. Setup for Claude, OpenAI, Gemini, Grok and others: https://myuiaf.com/integrations

## Authentication

Send your key (`fv1.<agent_id>.<key_id>.<secret>`) in one of:

```
X-Agent-API-Key: fv1.acme-bot.k1.xxxxx
X-Api-Key: fv1.acme-bot.k1.xxxxx
Authorization: Bearer fv1.acme-bot.k1.xxxxx
```

Get a key by buying credits: https://myuiaf.com/pricing#buy, or as an agent with `POST https://api.myuiaf.com/api/v1/credits`.

## The pattern

1. Before calling your model, `POST /v1/lookup` with the question.
2. If `hit` is `true`, use `answer`.
3. Otherwise call your model, then `POST /v1/store` with the question and answer.

Send the question itself as `prompt`, not the whole conversation. Put what changes the answer but isn't the question (model, system prompt version) in `context`.

## POST /v1/lookup

Body: `prompt` (required, up to 8,000 characters), `namespace` (optional, default `default`, 1-48 of `A-Z a-z 0-9 _ . : -`), `context` (optional, up to 4,000 characters, must match exactly), `min_similarity` (optional, 0.92-1, default 0.95; 1 = exact repeats only).

Hit (200, charged $0.002):

```json
{"hit": true, "match": "similar", "similarity": 0.9984, "entry_id": "…", "namespace": "support",
 "cached_prompt": "How do I reset my password?", "answer": "Go to Settings, then Security, then Reset password.",
 "cached_at": "2026-11-08T12:00:00.000Z", "expires_at": "2026-11-09T12:00:00.000Z",
 "charged_usd": 0.002, "original_cost_usd": 0.012, "saved_usd": 0.01}
```

Miss (200, free): `{"hit": false, "charged_usd": 0, "next": "…"}`. A miss may include `degraded` (`similar_matching_unavailable`, `storage_unavailable`, `wallet_unavailable`); carry on as for any miss.

Headers: `X-AgentCache-Hit` (`exact`, `similar`, `miss`), `X-AgentCache-Charged-USD`.

If a hit is found but the wallet can't cover $0.002: 402 `insufficient_credits` with a `topup` object; the answer is not returned.

## POST /v1/store

Body: `prompt` (required), `answer` (required: string or any JSON value, up to 60,000 bytes as JSON), `namespace`, `context`, `ttl_seconds` (60-2,592,000; default 86,400), `original_cost_usd` (optional; hits then report `saved_usd`).

Returns 201 with `entry_id`, `expires_at`, `exact_match: "ready"` and `similar_match` (`indexing` (reworded questions match in about 1-2 minutes), `too_long` for prompts over 2,000 characters, or `unavailable`). Saving the same question again replaces the answer. Free.

## Matching

1. Exact: the same prompt after whitespace clean-up.
2. Similar: bge-m3 embeddings (run inside Cloudflare, multilingual), cosine similarity >= `min_similarity`, AND the same numbers in both prompts ("order 12345" never matches "order 12346").

Measured: rewordings score 0.95-0.998; the closest different questions scored up to 0.92. Prompts over 2,000 characters match exactly only. Only cache answers that are the same for everyone in the namespace; don't cache personal data.

## Isolation

Each answer belongs to one agent + namespace + context. Lookups search only that space; other agents can never see your answers.

## Idempotency

Optional `Idempotency-Key` header on lookups (1-250 printable characters): a retry with the same key and question returns the same answer with `Idempotent-Replayed: true` and no second charge, for 24 hours. Same key, different question: 422 `idempotency_key_reused`.

## DELETE /v1/entries/{entry_id}

Removes one answer. 404 if it isn't yours.

## POST /v1/purge

Body: `namespace`, optional `context`. Removes up to 500 answers per call; repeat while `more` is `true`.

## Limits

Requests per minute, counted separately from the other services: Early Testing 120, Growing Product 300, Scale Revenue 1,000, Enterprise 3,000. Bodies up to 128 KB.

## Errors

JSON `{"error": "...", "code": "..."}`. 400 invalid input, 401 key problems, 402 `insufficient_credits`, 404 `entry_not_found`, 409/422 idempotency, 413 too large, 429 `rate_limited`, 503 temporarily unavailable (nothing charged).

## Health

`GET /v1/health` → `{"status":"ok","service":"agentcache","checks":{...}}`. Status page: https://myuiaf.com/status
