Linking memories: a small graph that keeps decisions connected
Memory links are directed edges with a kind and optional weight. They are idempotent to write, visible only when both ends are, and capped at 1,000 per memory.

A memory link is a durable, directed edge from a memory you own to any memory you can see. Each link has a kind, related by default, and an optional weight from 0 to 1. Writing the same link twice changes nothing. A memory can hold up to 1,000 outgoing links, and the dashboard draws the graph.
What is a memory link?
Memories are saved one at a time: a preference, a decision, a constraint, a named relationship. The useful ones depend on each other. A release-day decision rests on a customer constraint. A preference belongs to a person. A runbook applies to one service. A link records that dependency as data instead of leaving it in the prose of each memory.
A link is named by its two ids and a kind. It runs from a memory you own to any memory you can see, so you can point your own memory at a teammate's shared one, and you cannot attach edges to a memory that is not yours. The related_ids argument of memory__remember, memory__ingest and memory__update_memory writes related links at save time. memory__link_memories writes any kind, such as depends-on, with an optional weight.
| Field | Values | Notes |
|---|---|---|
| direction | from a memory you own, to a memory you can see | one edge, one direction |
kind | related by default, or any name you choose | supersedes is reserved |
weight | 0 to 1, optional | a new weight replaces the old one |
| outgoing links per memory | up to 1,000 | link_capacity_exceeded past the bound |
| kinds toward one other memory | up to 16 | the same bound applies |
One kind is reserved. supersedes is written by memory__archive_memory when a memory is retired in favor of another, and only by it. The memory page documents every field.
Writing a link is idempotent, and that is deliberate. Agents retry. A client times out, a session restarts, the same instruction runs twice. If a link call created a new edge each time, the graph would fill with duplicates that mean nothing and cost capacity.
So the same call again changes nothing. A call with a new weight replaces the old weight on the same edge. memory__unlink_memories removes exactly the link its key names, and no other. An agent can link at the end of every session without checking first whether it already did.
Who can see a link?
A link is visible only when both of its memories are. memory__list_memory_links reads a memory's links back, newest first, outbound or inbound, and lists only links whose two memories you can see. A link to a teammate's private memory stays invisible to you, as that memory does.
This is the same boundary memory itself has, applied to the edges. Identity comes from the credential on the request, every memory carries a scope, and the database enforces it. A link cannot leak the existence of a private memory, because the link is filtered by the same rule as the row.
What are the limits?
A memory can hold up to 1,000 outgoing links and up to 16 kinds toward any one other memory. Past either bound the call answers an isError result:
{ "error": { "code": "link_capacity_exceeded" } }
Treat it like the other tool-level codes in the errors reference: branch on structuredContent.error.code, and do not retry, because the bound does not move. Unlink something, or link from a different memory.
The bound is generous for the intended use. A memory with a thousand outgoing edges is a hub, and a hub usually means something is being used as an index that should be a search instead.
When should you link?
Link when a memory is only correct in the light of another one. A decision and the constraint behind it. A preference and the person it belongs to. An operating rule and the service it covers. These are the categories the docs say belong in memory in the first place, and the link is what lets an agent that found one of them find the reason for it.
Do not link to build an archive. Memory is for context that improves a later action, and the graph serves that. Transcripts, application data and secrets do not belong in memory, and linking them does not change that.
Two patterns work well:
- At save time, pass
related_idsso a new decision points at the constraint or preference it depends on. - When a memory is retired, let archive write the
supersedeslink, so an agent holding the old id follows the pointer forward.
How does the dashboard show it?
Dashboard → Memory draws every link you can see. The graph view is where a person reads what the agents have been connecting: which decisions cluster around one constraint, which memory has become a hub, which old memory still has a supersedes pointer to follow. The same page opens a memory's detail view, where you can inspect and delete content.
Memory operations, links included, cost 0 credits per call. The graph is part of the org-owned memory described in the Introducing CoreSpeed post: it belongs to the organization, and every agent you sign in works from the same one.
FAQ
Can I link to a teammate's memory? Yes, if you can see it, which means a shared one. The link runs from a memory you own. You cannot attach a link to a memory you do not own.
What happens if my agent links the same two memories twice? Nothing. The same call again is a no-op, and a call with a new weight only updates the weight.
Can I write a supersedes link myself?
No. supersedes is reserved for memory__archive_memory, which writes it when a memory is retired with a named successor.
What does link_capacity_exceeded mean?
The memory already has 1,000 outgoing links, or 16 kinds toward the same target. Remove a link or link from another memory; retrying does not help.
Do links show in search results?
Search returns memories. Read a memory's links with memory__list_memory_links, or look at the graph in Dashboard → Memory.