Korely

Core memory operations

Add a memory

Store a memory. Korely extracts typed facts and resolves contradictions server-side; you just send the text and a scope.

POST /v1/memories

SDK: korely.add(content, ...). The write path runs the intelligence, embeddings, entity and typed-fact extraction, contradiction checking with bi-temporal validity, server-side. You never write supersede logic.

Authentication

HTTP header, required: Authorization: Bearer kor_live_.... The key must carry the memories:write scope.

Request body

FieldTypeRequiredDescription
contentstringRequiredThe memory text. 1-16,000 characters; leading and trailing whitespace is removed, and a blank text is refused.
user_idstringOptionalThe end user this memory belongs to. 1 to 255 characters, no /, no control characters, not . or ... Omit it for the shared namespace; an empty string is refused.
agent_idstringOptionalYour application's namespace. Same rule as user_id. Omit it for the default namespace, which never counts toward your agent cap.
run_idstringOptionalOne session or conversation. Max 255 chars.
metadataobjectOptionalArbitrary JSON stored alongside the memory and echoed back on reads. At most 8,192 bytes once serialized, with finite numbers only: NaN and Infinity are refused.
timestampstringOptionalISO 8601 date or datetime of the event (a date is midnight UTC, no offset means UTC, omitted or blank means now). Sets the bi-temporal valid_from on facts extracted from this memory, use it when backfilling historical memories so the timeline stays correct.

Any other field is refused with 422 invalid_request (for example userId: Extra inputs are not permitted): field names are snake_case.

Example request

Terminal window
curl -X POST https://api.korely.ai/v1/memories \
-H "Authorization: Bearer kor_live_..." \
-H "Content-Type: application/json" \
-d '{
"content": "User prefers email follow-ups, not phone",
"user_id": "customer-giulia-4812",
"agent_id": "support-bot"
}'

Response

201 Created. The stored memory, with status processing and an empty facts list: the typed facts are derived a few seconds later (see the note below).

{
"id": "mem_8f2c1a",
"content": "User prefers email follow-ups, not phone",
"user_id": "customer-giulia-4812",
"agent_id": "support-bot",
"run_id": null,
"metadata": {},
"status": "processing",
"created_at": "2026-06-17T10:22:00.412345+00:00",
"updated_at": null,
"facts": []
}
FieldTypeDescription
idstringThe memory id, e.g. mem_8f2c1a.
contentstringThe text you stored, echoed back.
user_id / agent_id / run_idstring · nullThe scope you sent, echoed back (null if omitted).
metadataobjectThe metadata you sent ({} if omitted).
statusstringprocessing while the facts are being extracted, then ready (or error). Read it later with Get memory.
created_atstringISO 8601 timestamp of the write.
updated_atstring · nullnull until the memory is edited with Update a memory; then the ISO 8601 timestamp of the last edit.
factsarrayTyped (subject, predicate, object) facts extracted from this memory, when extraction ran inside the call. Each has id, subject, predicate, object, predicate_family (string · null), valid_from (string · null), invalidated (the fct_ ids it superseded), tense, invalid_at (string · null) and observation_count (above 1 when the write restated a fact the store already held). See the note on async extraction below.

Facts extract asynchronously. In production the add returns as soon as the memory is stored and embedded, with facts: []; the extraction pipeline (entity + typed-fact extraction, contradiction checking) lands the facts a few seconds later. Read them back with Get facts or Get context on the next turn, don't block on them in the same request.

Errors

StatusCodeCause
401invalid_keyMissing or invalid Authorization header.
403forbiddenThe key lacks the memories:write scope.
403agent_cap_exceededA new agent_id beyond your plan's agent cap. Nothing is written or counted: reuse one from List agents, or upgrade.
422invalid_requestValidation failed: content missing, not a string, blank or over 16,000 chars; user_id or agent_id breaking the id rule; run_id over 255; metadata over 8,192 bytes or holding NaN or Infinity; timestamp not ISO 8601; malformed JSON; an unknown field.
429quota_exceededMonthly writes used up, 10% grace included; nothing is written. The body adds limit, used and resets_at (00:00 UTC on the 1st) to code and message. No Retry-After: read resets_at, top up the month on a paid plan, or upgrade.
429rate_limit_exceededPer-minute, per-hour or per-day request limit. Carries Retry-After.

Notes

  • One write per 6,000 characters. An add of up to 6,000 characters counts one write against your monthly write quota, however many facts it produces. A longer one counts one write per 6,000 characters, because the engine reads it in windows of that size, one model call each: 16,000 characters, the most a memory can hold, count 3. A memory that does not fit in the writes left this month is refused whole with 429 quota_exceeded.
  • Contradictions are automatic. If this memory conflicts with an earlier fact (same predicate, different object), the old fact is superseded, invalidated, not deleted, and stays queryable via as_of.
  • Messages, too. The SDKs accept a list of chat messages as content and join them into one block before sending.

Related