ad4m_write_memory
Write signed semantic links (source-predicate-target) to a persistent Perspective, auto-optimizing memory every 10 writes for efficient cross-session context.
Instructions
Write a signed LinkExpression (source → predicate → target) to a Perspective. Auto-optimizes the graph every 10 writes across all terminals.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| perspective_uuid | Yes | Target Perspective UUID | |
| source | Yes | Source URI — e.g. 'agent://session/2026-03-22' | |
| predicate | No | Predicate URI — e.g. 'ad4m://knows' (default: ad4m://relates) | |
| target | Yes | Target URI or literal — e.g. 'literal://decision text' |
Implementation Reference
- src/index.ts:304-324 (registration)Registration of the ad4m_write_memory tool with the MCP server, including its schema (perspective_uuid, source, predicate, target) and the handler that calls the AD4M GraphQL perspectiveAddLink mutation.
server.tool("ad4m_write_memory", "Write a signed LinkExpression (source → predicate → target) to a Perspective. Auto-optimizes the graph every 10 writes across all terminals.", { perspective_uuid: z.string().describe("Target Perspective UUID"), source: z.string().describe("Source URI — e.g. 'agent://session/2026-03-22'"), predicate: z.string().optional().describe("Predicate URI — e.g. 'ad4m://knows' (default: ad4m://relates)"), target: z.string().describe("Target URI or literal — e.g. 'literal://decision text'"), }, async ({ perspective_uuid, source, predicate = "ad4m://relates", target }) => { const data = await gql( `mutation M($uuid: String!, $link: LinkInput!) { perspectiveAddLink(uuid: $uuid, link: $link) { author timestamp data { source predicate target } } }`, { uuid: perspective_uuid, link: { source, predicate, target } } ); tickWriteCounter(perspective_uuid).catch(() => {}); return ok(data.perspectiveAddLink); } ); - src/index.ts:306-311 (schema)Zod input schema for ad4m_write_memory: perspective_uuid (string), source (string), predicate (optional string, default ad4m://relates), target (string).
{ perspective_uuid: z.string().describe("Target Perspective UUID"), source: z.string().describe("Source URI — e.g. 'agent://session/2026-03-22'"), predicate: z.string().optional().describe("Predicate URI — e.g. 'ad4m://knows' (default: ad4m://relates)"), target: z.string().describe("Target URI or literal — e.g. 'literal://decision text'"), }, - src/index.ts:132-152 (helper)The gql() helper function used by the handler to send GraphQL mutations to the AD4M executor.
async function gql(query: string, variables: Record<string, unknown> = {}): Promise<GqlResult> { const resp = await fetch(AD4M_GQL, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, variables }), signal: AbortSignal.timeout(10_000), }); if (!resp.ok) throw new Error(`AD4M HTTP ${resp.status}: ${await resp.text()}`); const json = await resp.json() as { data?: GqlResult; errors?: { message: string }[] }; if (json.errors?.length) { const msg = json.errors[0].message; if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) { throw new Error("AD4M executor not reachable. Start it with: ad4m serve --port 4000"); } if (msg.includes("Unauthorized") || msg.includes("not unlocked")) { throw new Error(`Agent is locked. Unlock with:\ncurl -X POST ${AD4M_GQL} -H 'Content-Type: application/json' -d '{"query":"mutation { agentUnlock(passphrase: \\"YOUR_PASSPHRASE\\") { isUnlocked } }"}'`); } throw new Error(msg); } return json.data ?? {}; } - src/index.ts:193-207 (helper)The tickWriteCounter() helper called after each write to auto-optimize the perspective every 10 writes.
async function tickWriteCounter(uuid: string): Promise<void> { const { link: old, count } = await getSharedCount(uuid); if (old) await removeLink(uuid, old).catch(() => {}); const next = count + 1; if (next >= OPTIMIZE_THRESHOLD) { optimizePerspective(uuid, false).catch(() => {}); } else { await gql( `mutation A($uuid: String!, $link: LinkInput!) { perspectiveAddLink(uuid: $uuid, link: $link) { author timestamp } }`, { uuid, link: { source: CTR_SOURCE, predicate: CTR_PRED, target: `literal://${next}` } } ).catch(() => {}); } } - src/index.ts:312-323 (handler)The handler function for ad4m_write_memory: executes the GraphQL perspectiveAddLink mutation and triggers the write counter.
async ({ perspective_uuid, source, predicate = "ad4m://relates", target }) => { const data = await gql( `mutation M($uuid: String!, $link: LinkInput!) { perspectiveAddLink(uuid: $uuid, link: $link) { author timestamp data { source predicate target } } }`, { uuid: perspective_uuid, link: { source, predicate, target } } ); tickWriteCounter(perspective_uuid).catch(() => {}); return ok(data.perspectiveAddLink); }