Korely

Core memory operations

Search memories

Semantic search over your memory store. Scope it to one end user and agent, or search across everyone you've stored.

POST /v1/memories/search

SDK: korely.search(query, ...). A search ranks the stored memories by how close their embedding is to the query's, best first, and returns a snippet of each. Each match is a hit with a score. It does not read the facts: for those use Get facts or Get context. A search is a read, so it counts against your monthly query quota. The guide shows what a good query looks like.

Authentication

HTTP header, required: Authorization: Bearer kor_live_.... The key must carry the memories:read permission.

Request body

FieldTypeRequiredDescription
querystringRequiredThe search query. 1-2,000 characters.
user_idstringOptionalSearch one end user. Max 255 chars. When omitted, searches across all end users in the key's project (a key confined to some end users searches only those).
agent_idstringOptionalSearch one agent (agent_id). Max 255 chars.
run_idstringOptionalSearch one run or session (run_id). Max 255 chars.
metadataobjectOptionalFilter on the metadata you stored at write time. Keys are ANDed; each value is compared as text with the stored one, e.g. {"tier": "pro"}: true matches a stored true, 5 a stored 5 (a number also matches an equal number, 5.0), "5" a stored 5 or "5", null a stored null. An object, an array, NaN or an infinity is refused with 422.
limitintegerOptionalMaximum number of results. Default 15, minimum 1, maximum 50.
min_scorenumberOptionalDrop the hits whose score is below this, from 0 to 1. Absent: no floor, every search returns its nearest memories. With a floor, a question whose answer is not stored can return {"results": []}, and fewer than limit results can come back. 0.2 is the value we measured: see Search.
exclude_sessionsbooleanOptionalLeave out the work sessions, the memories written with kind: "session" (what a coding assistant's hooks save), for a search that wants what was said and decided. Default false: everything. See Work sessions.

Any other field is refused with 422 invalid_request (top_k and filters included): field names are snake_case.

Example request

Terminal window
curl -X POST https://api.korely.ai/v1/memories/search \
-H "Authorization: Bearer kor_live_..." \
-H "Content-Type: application/json" \
-d '{
"query": "communication preferences",
"user_id": "customer-giulia-4812",
"agent_id": "onboarding-bot",
"limit": 15
}'

Response

200 OK. A ranked list of matching memories, each with a relevance score and a truncated snippet.

{
"results": [
{
"id": "mem_8f2c1aab4d7e4f0c9a1b2c3d4e5f6a7b",
"score": 0.873,
"snippet": "Giulia prefers async standups and works in CET.",
"user_id": "customer-giulia-4812",
"agent_id": "onboarding-bot",
"metadata": {"source": "slack"}
}
]
}
FieldTypeDescription
resultsarray<SearchResult>Ranked list of matches. Each SearchResult has the fields below.
results[].idstringThe memory id, e.g. mem_8f2c1aab4d7e4f0c9a1b2c3d4e5f6a7b.
results[].scorefloatCosine similarity between the query and the memory, as the Glossary explains. Higher is more relevant.
results[].snippetstringThe memory content, truncated to 280 characters.
results[].user_idstring · nullThe end user this memory belongs to (null if none).
results[].agent_idstring · nullThe agent sub-namespace (null if none).
results[].metadataobjectThe metadata stored with the memory ({} if none).

Errors

StatusCodeCause
401invalid_keyMissing or invalid Authorization header, no valid kor_live_ key.
403forbiddenThe key lacks the memories:read scope.
413payload_too_largeThe body is larger than 2,097,152 bytes. Refused before it is read; nothing was done. On the Cloud a body over 1 MB gets a bare 413 first, without this code.
422invalid_requestValidation failed: an empty or whitespace-only query, a query over 2,000 characters, limit outside the 1-50 range, min_score outside 0-1, a metadata value that is an object, an array, NaN or an infinity, a metadata filter with more than 32 keys or over 8,192 bytes, or an unknown field.
429quota_exceededMonthly query quota reached. No Retry-After; resets on the 1st of the month (UTC), or upgrade.
429rate_limit_exceededPer-plan minute, hour or day request ceiling exceeded (rate limit); the message names the window, and Retry-After gives the seconds until it resets.
503search_unavailableThe query could not be turned into an embedding: the embedding model did not answer, or, where an install embeds on its own server, a burst from one account made this search wait 20 seconds for its turn. The answer carries Retry-After: 5. It is not an empty result: retry. It takes no query of the month.
503service_pausedThe service itself does not call the models now (a spending stop or a provider brake), so the query cannot be embedded. Carries Retry-After: 3600: a retry within the hour cannot succeed. It takes no query of the month.
503unavailableThe database did not answer while the key was checked, or the request waited more than 5 seconds for another change to the same records. Retry after the seconds in Retry-After.
408request_timeoutThe body did not arrive whole within 30 seconds. Send it again.
500internal_errorThe server failed on this request; the message holds no detail.

Notes

  • Counts as one query. Each search that answers counts against your monthly query quota. A search that ends in a 503 or a 422 does not.
  • A forgotten memory is never returned. A deleted memory drops out of search at once.
  • Snippets are truncated. The snippet is the memory content cut to 280 characters. Read the full text with Get a memory.
  • Omit user_id to search everyone. Leaving user_id out searches across all end users in the key's project. Pass it to scope recall to a single end user.

Related