Skip to main content

Agent Memories

Read, teach, correct and erase the standing facts an agent remembers and the rules it follows on every reply, including the newest facts it carries into every turn without searching.

A memory is one short fact an agent was told to keep, or a rule it was told to follow. These endpoints are the operator's view of that store: see exactly what is remembered, teach a fact or a rule directly, correct one, turn one into the other, and delete anything that should not be there.

The injection window: what the agent reads without asking

Every memory stays searchable forever. The newest of each kind are handed to the agent at the start of a turn, so it acts on them without deciding to look anything up: up to 100 rules, 500 facts you or the agent saved, and 150 facts picked up from chats, each kind in its own window. That set is the injection window, and injected: true marks it on every listed memory.

The window is applied today on the linked personal WhatsApp channel. On every other channel a memory is still remembered and still found by recall_memory; it is simply not placed in the prompt ahead of time, so injected there tells you where a fact sits in the order rather than that it was already read.

Inside the windowOutside it
Newest ...100 rules, 500 saved facts, 150 chat-picked factsEverything older
How the agent gets itAlready in front of it, every turnIt calls recall_memory and the fact is found by meaning, not by keyword
ReliabilityAlways appliedApplied when the conversation gives the agent a reason to search

So a fact does not stop existing when it falls out of the window. It stops being free. If a preference must hold on every single reply, keep it near the top by restating it: memories are ordered newest first, and a fresh statement of the same preference moves it back into the window.

One more bound shapes each window. A memory is injected whole, never cut mid-sentence, and each block has a character budget: 20,000 for rules, 120,000 for saved facts and 30,000 for chat-picked facts. An unusually long run of long memories can fill a budget before its count is reached. injected is positional (the newest rows of each kind) and does not model the character budget. Write memories as one line each and the budget will not bite.

Facts and rules

Every memory has a memory_type.

factrule
What it isSomething the agent knows: "Ravi prefers calls after 6pm"A standing instruction: "Always reply in English", "Never share my address"
How the agent uses itInjected while inside the window, otherwise found by recall_memoryFollowed on every reply, including automatic replies to contacts on the linked personal WhatsApp channel
DefaultYes, when memory_type is omittedOnly when asked for

Write a rule as one instruction, the way you would say it out loud. A fact can be made a rule and a rule moved back to a fact with PATCH (below), without deleting and re-teaching it.

What is listed here

A memory is stored in one of two forms, and this surface serves only the first.

Explicit factsCaptured transcripts
Where it comes fromThe agent's remember tool, a chat command, facts picked up from chats, or a POST hereA finished call or chat, captured whole
Listed by these endpointsYesNo
Editable and deletable by these endpointsYesNo
Reachable by the agentInjected, then searchedSearched, through recall_memory

Transcripts are deliberately absent: a transcript is not something an operator can meaningfully review or correct one line at a time, so it stays retrieval-only rather than becoming a browsable message archive.

Credential class: dashboard JWT or a cm_ key

Authorization: Bearer cm_your_api_key
CallerRequirement
cm_ API keybots:read to list. bots:write to create, change and delete
Dashboard JWTListing for any member. Creating, changing and deleting require owner or admin (403 owner or admin role required otherwise)

A memory is an attribute of a bot rather than a resource class of its own, so it reuses the bots:* scopes and adds none.

Base URL for every example: https://api.callmissed.com. Errors are {"detail": "..."}.

The memory object

{
  "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "fact": "Wholesale orders ship Tuesdays only. Never promise a Friday dispatch.",
  "created_at": "2026-09-08T12:00:00Z",
  "injected": true,
  "captured_by": "remember_tool",
  "memory_type": "fact"
}
FieldTypeNotes
iduuidPass it to DELETE to forget this one fact
factstringThe memory in full. Read from the memory's stored text, not from the 120-character title kept for display, so a long fact comes back whole here
created_atstringWhen it was remembered. The list is ordered by this, newest first
injectedbooleantrue when it is inside its kind's window. See the injection window
captured_bystringHow the fact was captured: remember_tool when the agent saved it mid-conversation, remember_command when the owner saved it with a chat command, console when it was taught through POST, chat_capture when it was picked up from chats. null when the memory records no capture source
memory_typestringfact or rule. See facts and rules

Memories belong to one agent

A memory is scoped to a workspace and a bot. Two agents in the same workspace do not share a fact, and re-pointing a phone number at a different agent gives it a different set of memories, not the same set under a new name. Move a fact by POSTing it to the second agent.

GET /api/v1/agent-memories

Everything one agent has been told to remember, newest first. Requires bots:read.

ParameterTypeNotes
bot_iduuidRequired. The agent whose memories to list
limitinteger1 to 200, default 100
memory_typestringOptional. fact or rule to list only that type. Omit it to list both
curl "https://api.callmissed.com/api/v1/agent-memories?bot_id=b1f2c3d4-5678-90ab-cdef-1234567890ab&limit=50" \
  -H "Authorization: Bearer cm_your_api_key"
{
  "bot_id": "b1f2c3d4-5678-90ab-cdef-1234567890ab",
  "memories": [
    {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "fact": "Wholesale orders ship Tuesdays only. Never promise a Friday dispatch.",
      "created_at": "2026-09-08T12:00:00Z",
      "injected": true,
      "captured_by": "remember_tool",
      "memory_type": "fact"
    }
  ],
  "max_injected": 500
}

max_injected is the size of the injection window. Read it instead of hardcoding 500, so a change to the window does not silently make your own display wrong.

POST /api/v1/agent-memories

Teach the agent a fact or a rule directly, without waiting for it to come up in a conversation. Returns 201 and the memory object. Requires bots:write, or an owner or admin JWT.

FieldTypeNotes
bot_iduuidRequired. The agent that should remember this
factstringRequired. 1 to 160,000 characters are accepted; surrounding whitespace is stripped and the first 16,000 characters are stored. For a rule, this is the instruction text
memory_typestringOptional. fact (default) or rule
curl -X POST https://api.callmissed.com/api/v1/agent-memories \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": "b1f2c3d4-5678-90ab-cdef-1234567890ab",
    "fact": "Wholesale orders ship Tuesdays only. Never promise a Friday dispatch."
  }'

The new memory always comes back with injected: true, because it is the newest, and captured_by: "console", which is how a taught fact is distinguished from one the agent chose to keep.

Write one fact per call, in one line, the way you would say it out loud. The agent is given these verbatim, so "Wholesale orders ship Tuesdays only" steers a reply and a pasted paragraph of policy does not. Anything longer belongs in the knowledge base, which the agent searches instead of carrying.

StatusMeaning
201Remembered
403The key lacks bots:write, or the JWT is neither owner nor admin
404bot_id is not an agent in this workspace. Nothing is written
422fact is empty after stripping, or longer than 160,000 characters, or memory_type is not fact or rule

To teach a rule, send the same request with "memory_type": "rule":

curl -X POST https://api.callmissed.com/api/v1/agent-memories \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": "b1f2c3d4-5678-90ab-cdef-1234567890ab",
    "fact": "Never share my home address.",
    "memory_type": "rule"
  }'

PATCH /api/v1/agent-memories/{memory_id}

Correct a memory's text, make a fact a rule or move a rule back to a fact, or both at once. Returns 200 and the updated memory object. Requires bots:write, or an owner or admin JWT.

FieldTypeNotes
factstringOptional. The corrected text. Surrounding whitespace is stripped; the first 16,000 characters are kept
memory_typestringOptional. fact or rule

Send at least one of the two.

curl -X PATCH https://api.callmissed.com/api/v1/agent-memories/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"memory_type": "rule"}'

To correct the wording instead:

curl -X PATCH https://api.callmissed.com/api/v1/agent-memories/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"fact": "Wholesale orders ship Tuesdays and Thursdays."}'
StatusMeaning
200Changed
402Not enough credits to re-index the corrected text. The memory is unchanged
403The key lacks bots:write, or the JWT is neither owner nor admin
404No memory with this id in this workspace
422Neither field was sent, fact is empty or longer than 160,000 characters, or memory_type is not fact or rule
502The corrected text could not be re-indexed. The memory is unchanged

Either change keeps the memory's created_at, so it stays where it was in the order: correcting a typo never moves a memory into or out of its window. Corrected text is re-indexed in the same step; if that fails, nothing changes.

DELETE /api/v1/agent-memories/{memory_id}

Forget one fact or rule. Returns 204 and no body. Requires bots:write, or an owner or admin JWT.

curl -X DELETE https://api.callmissed.com/api/v1/agent-memories/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
  -H "Authorization: Bearer cm_your_api_key"

Deletion is idempotent: 204 whether the memory was there or not, so a retry after a dropped connection is safe. It is also scoped to memories, so this route cannot be used to remove an ordinary knowledge document by guessing at its id. The fact and its search index go together; there is no way to read a deleted memory back.

These facts are asserted about real people and are put in front of the agent, so treat this endpoint as the erasure path it is. A memory a customer asks you to remove is removed here, in full, not edited into something softer. To fix a wrong detail instead, use PATCH.

Errors

StatusWhen
401No credential, or one that is not valid
403The key is missing bots:read (listing) or bots:write (writing), or the dashboard JWT is not an owner or admin
404bot_id does not name an agent in this workspace, or memory_id (on PATCH) does not name a memory in it
422bot_id is missing or not a UUID, limit is outside 1 to 200, fact is empty or too long, or memory_type is not fact or rule

A bot_id belonging to another workspace returns 404, never 403. The ownership check runs before anything else, so a caller cannot tell "not yours" apart from "does not exist" and cannot use this endpoint to confirm that an id exists somewhere else.

Billing

A memory is embedded when it is written, so that the agent can find it later by meaning rather than by keyword. That embedding is billed like any other embedding on your account, at the rate on the pricing page. Corrected text is re-embedded and billed the same way. Listing and deleting are free.

A memory whose embedding did not complete still appears in the list, with fact falling back to its first 120 characters, because an un-embedded memory is exactly the thing you need to see rather than one that quietly vanishes.