SDKs (Node, Python, .NET)
Install the Node, Python, and .NET client libraries and run the basic memory loop.
The three client libraries use the same REST contract: recall, write, report the outcome, forget. This page covers installation and the basic loop.
| SDK | Package | Execution model | Coverage |
|---|---|---|---|
| Node | agentmemory 0.4.0 (ESM, Node ≥ 18, no dependencies) | All methods return a Promise | add, search, get, update, share, delete, erasure, operation, explain, outcome, feedback |
| Python | agentmemory 0.4.0 (Python ≥ 3.9, standard library only) | Synchronous | Same as Node |
| .NET | AgentMemory.Client (project reference) | Async + CancellationToken | All of the above + consolidate, blocks |
Consolidation and block operations are not in the Node/Python SDKs; use the MCP tools or the REST endpoints for these.
Installation
The packages are not published on the public npm/PyPI registries. Your service distributes them under /sdk/:
# Node
npm install $API/sdk/agentmemory-0.4.0.tgz
# Python
pip install $API/sdk/agentmemory-0.4.0-py3-none-any.whlIf you are working from the repository, you can also install from a local path: npm install ./clients/node, pip install ./clients/python.
Do not type just npm install agentmemory or pip install agentmemory: a different package with the same name on the public registry may be installed.
The SDKs do not read environment variables; you pass the address, key, and workspace from your code. Read the key from a secret store or an environment variable.
import { AgentMemoryClient } from 'agentmemory'
const memory = new AgentMemoryClient({
apiKey: process.env.AGENT_MEMORY_API_KEY,
baseUrl: process.env.AGENT_MEMORY_URL, // e.g. https://memory.empecta.com
workspaceId: process.env.AGENT_MEMORY_WS,
})
// write — if userId is an end user, the key needs the "act for users" permission
const { id, operationId } = await memory.add('The weekly report is sent as a PDF', {
type: 'preference', userId: 'demo-user', runId: 'run-1', sourceKind: 'user',
idempotencyKey: 'pref-weekly-report',
})
await memory.operation(operationId) // { status: 'pending' | ..., effects: [...] }
// recall — keep the receiptId
const context = await memory.search('weekly report format', { userId: 'demo-user', runId: 'run-1' })
console.log(context.workspaceEntries.map(e => e.content))
// report the outcome — same runId and receiptId
await memory.outcome({ runId: 'run-1', buildSuccess: true, receiptId: context.receiptId })
// forget
const { status } = await memory.delete(id) // 'deleted' | 'pending' | 'blocked' | 'not_found' | 'forbidden'
await memory.erasure(id) // { status: 'complete', ... }Other methods: get(id), update(id, content, { ifMatch }), share(id, visibility), explain(id), feedback(report).
Common rules
- Do not send
agentId. The agent your key is bound to performs the operation. If the key is bound to multiple agents and you want to pick another one, pass it; a name the key is not bound to returns403. userIdis a person, not an agent. Sending it requires the key's act for users permission; otherwise you get403 policy_denied(identity-binding).- A receipt belongs to a run. In
outcome/feedbackcalls, use the samerunIdas the search that produced thereceiptId; reporting a record the receipt did not deliver as "used" returns400 RECEIPT_MISMATCH. - Deletion can be
pending. The record is blanked immediately; derived copies are cleaned up afterwards. Track it witherasure. A record with live derived records returnsblocked; retry withcascade. - Errors. Node and Python throw
AgentMemoryError(status,body) for every unmapped HTTP error; .NET throwsHttpRequestException.
Use agent, user, document, or import for sourceKind. tool and conversation, which appear in the Node type definitions, are not accepted by the server.