← AiAkiv MemoryCONTENT HISTORY

Update to AiAkiv Memory

Snapshot Sep 30, 2026 · 23:09 UTC · version 2.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "aiakiv-graph-query",
  "description": "Write graph queries (Cypher subset) against AiAkiv/MWeft memory with query_memory_graph (and query_partner_memory_graph across a link). Use when the user asks HOW memories are connected — shared entities, bridges, threads, timelines, multi-hop paths, \"similar but structurally related\", entity co-occurrence — or when a search hint block contains a `graph_query` example. Not for plain recall (use search_memory).",
  "included_files": [],
  "skill_md_contents": "---\r\nname: aiakiv-graph-query\r\ndescription: >-\r\n  Write graph queries (Cypher subset) against AiAkiv/MWeft memory with\r\n  query_memory_graph (and query_partner_memory_graph across a link). Use when the\r\n  user asks HOW memories are connected — shared entities, bridges, threads,\r\n  timelines, multi-hop paths, \"similar but structurally related\", entity\r\n  co-occurrence — or when a search hint block contains a `graph_query`\r\n  example. Not for plain recall (use search_memory).\r\n---\r\n\r\n# AiAkiv graph query\r\n\r\n`query_memory_graph` runs a **read-only Cypher subset** over the user's memory\r\ngraph. It answers *structure* questions that flat search cannot: which events\r\nshare entities, what bridges two topics, what happened next in a thread, what\r\nis semantically far but structurally connected.\r\n\r\n**When to reach for it** — the question is about connections, paths, shared\r\nparticipants, sequences, or \"one step beyond these search results\". A search\r\nresponse may hand you a ready-made query in `hint.graph_query.example` with\r\n`params` — run it as-is, then adapt.\r\n\r\n**When NOT to** — plain recall (\"what did we decide about X\") is\r\n`search_memory`. If `query_memory_graph` is not in the tool list, the server has\r\nit disabled; say so instead of inventing it.\r\n\r\n## Grammar in one screen\r\n\r\n```\r\nSTART a = events(text: $q, k: 5)        ← anchor set is ALWAYS events\r\nSTART a = events(entity: \"name or id\")\r\nSTART a = events(ids: [$id1, $id2])\r\nMATCH (a)-[s:SHARES {min: 2}]-(b)       ← one or more MATCH clauses\r\nWHERE b.id <> a.id                       ← optional\r\nRETURN b, s.count, s.via ORDER BY s.weight DESC LIMIT 20\r\n```\r\n\r\n- No `WITH`, no `CREATE`/`SET` (read-only). Conditions that would need `WITH`\r\n  go into relation params like `{min: 3}`.\r\n- `$name` params are passed via the `params` argument — always parameterize\r\n  user text; never inline it.\r\n- Aggregates (`count(DISTINCT …)`) live in `RETURN`. `cos(a, b)` gives vector\r\n  cosine between two event variables.\r\n- Variable-length: `-[n:NEXT*1..3]->` (hop count comes back as `n.hops`).\r\n\r\n## Relations (the whole vocabulary)\r\n\r\n| Relation | Between | Meaning / params |\r\n|---|---|---|\r\n| `SHARES {min, min_w}` | event–event | share ≥min entities; carries `s.count`, `s.weight` (rarity-weighted), `s.via` (the shared entities = bridges) |\r\n| `SIMILAR {k, min}` | event–event | vector nearest neighbours; `f.cos` |\r\n| `FAR {max}` | event–event | vector distance filter (cos < max) — pair with SHARES for \"connected but semantically far\" |\r\n| `NEXT` | event→event | conversation/thread order (directional, supports `*1..n`) |\r\n| `PARTICIPATED_IN` | event–entity | membership; walk event→entity→event for co-participation |\r\n| `MEMBER_OF` | event–tag | category/tag membership |\r\n| `CONNECTED` | entity–entity | stored entity co-occurrence edge |\r\n| `SAME_AS` | entity–entity | stored alias edge (exact identity, not fuzzy match) |\r\n\r\n## Recipes\r\n\r\n- **Structurally close but semantically far** (the highest-value walk from\r\n  search results — surfaces non-obvious connections):\r\n  `START a = events(ids: $ids) MATCH (a)-[s:SHARES {min: 2}]-(b)-[f:FAR {max: 0.5}]-(a) RETURN b, s.count, s.via, f.cos ORDER BY s.weight DESC LIMIT 10`\r\n- **What bridges these results** — same query; read `s.via` (shared entities),\r\n  then `find_memories_by_entity` the interesting ones.\r\n- **Thread / what happened next**:\r\n  `START a = events(ids: $ids) MATCH (a)-[n:NEXT*1..3]->(b) RETURN b.id, b.summary, n.hops ORDER BY n.hops LIMIT 30`\r\n- **Entity co-participation ranking**:\r\n  `START a = events(text: $q, k: 5) MATCH (a)-[:PARTICIPATED_IN]-(e)-[:PARTICIPATED_IN]-(b) WHERE b.id <> a.id RETURN e.name, count(DISTINCT b) AS n ORDER BY n DESC LIMIT 15`\r\n\r\nRows are projected small (Event → `{id, summary, timestamp, order_index}`);\r\nopen full content with `get_memory_content`.\r\n\r\n## Reading the response, handling refusals\r\n\r\n- `partial` / `truncated` report budget caps — **never silent**. If truncated,\r\n  narrow instead of retrying the same query: fewer anchors (`k`), tighter\r\n  `SHARES {min}` / `FAR {max}`, smaller `LIMIT`.\r\n- A rejection returns `{error, blocked_by: syntax|grammar|params, hint?,\r\n  allowed_*}` — read `hint` and the `allowed_*` lists, fix the query once;\r\n  do not loop blind retries.\r\n- Budget errors (\"statement timeout\") mean the walk was too wide, not that\r\n  the tool is broken.\r\n\r\n## Across a link (partner org)\r\n\r\n`query_partner_memory_graph(link_id, query, params)` — same language over your org\r\nplus a linked partner org. `link_id` comes from `list_partner_links`. `START`\r\nresolves in YOUR org only; the walk crosses sides through entities the link\r\nhas **aliased** (they count as one entity for `PARTICIPATED_IN`/`SHARES`),\r\nand `SIMILAR`/`FAR` cross by vector. `NEXT`/`MEMBER_OF`/`CONNECTED` stay\r\nwithin a side. Returned events carry `side` (`remote` = partner); open remote\r\ncontent with `get_partner_memory_content`. Remote budgets are tighter —\r\nprefer small `k` and `LIMIT` first. Not every server exposes this tool; if\r\nabsent, only home queries are available.\r\n\r\n## Probe: relation modes and expansion rounds\r\n\r\n`find_memory_connections` walks the same entity-event graph without a query language. It\r\ntakes a `relation` instead of a `MATCH` clause, and its candidates are\r\nunverified pointers — the same standing as anything the recipes above return.\r\n\r\nEntry is not one thing. A sentence-only call rides the vector ranking, so it\r\nrecovers when you have no ids yet; an `anchor_entity_id` call walks from the\r\nentity directly and does not depend on the ranking at all. A useful loop is to\r\nread a bridge entity out of one response and re-call with it as the anchor.\r\nThat chaining is yours to steer — it is not something the API does for you.\r\n\r\nThe relations:\r\n\r\n- `similar` (default) — time-stratified neighbours of what the sentence found.\r\n- `before` / `after` — one side of a point in time. Exactly one of\r\n  `reference_time` (ISO-8601) or `anchor_event_id` is required; there is no\r\n  implicit \"now\".\r\n- `evolution` — stratifies the candidate pool's own timeline into first\r\n  sighting, transition points (the largest content shift between adjacent\r\n  sightings), and latest sighting. It answers \"how did this develop\". It works\r\n  on the pool your sentence built and returns a handful of stratified picks,\r\n  whereas `list_memory_timeline` returns one entity's full chronology.\r\n- `contrast` — narrows by cosine and hands back candidates. The engine does\r\n  not judge opposition: semantic tension lives as small displacements inside\r\n  high cosine, not as opposite vectors, so geometry cannot see it. Read the\r\n  candidates and judge contradiction yourself;\r\n  `grounding_basis.contrast_protocol` restates this per call.\r\n- `explore` — question-free wandering. Requires `anchor_entity_id`, forbids\r\n  `sentence`. There is no cosine axis: candidates are ordered by bridge lift\r\n  (specificity) and recency, with the earliest sighting stratified in, and\r\n  `grounding` comes back as `\"exploration\"` because the existence gate does\r\n  not apply.\r\n\r\n`expansion_rounds=2` re-expands from the round-1 picks through bridges that\r\nround 1 did not use, reaching things two structural steps away. `top_n` caps\r\ncandidates *per round*, so a 2-round call can return up to twice `top_n` in\r\ntotal, and each candidate carries its `round` so you can tell how far out it\r\nsits. Round 2 costs a second walk — reach for it on relational and\r\n`evolution`-shaped questions rather than on direct lookups.\r\n\r\nAcross a link, `find_partner_memory_connections` takes the same inputs plus `link_id`. Entry\r\nhappens in your org only; the partner side is reached through bridges alone,\r\nwhich is why it never reports `absent` — check\r\n`grounding_basis.remote_entry_not_searched` instead.\r\n"
}

SHA-256: aee12c7338dd510717e7fef9d5fa84db78e48ee9ff6d8bd2b78fe9f40564a76d