Skip to content

Remember and recall a user fact

We enable memory on an agent, then write, recall and forget a user-scoped fact through memory-api. The record we write is the one the agent’s memory__remember tool writes for a verified user.

flowchart LR
C[curl] -->|/api/v1/memories| M[memory-api]
R[Agent runtime] -->|memory__remember, memory__recall| M
M --> P[(PostgreSQL)]
  • An Omnia cluster with a Workspace that has a managed default service group, and an existing AgentRuntime in that Workspace.
  • kubectl, curl and jq.
  • internalServiceAuth.enabled=false in the Helm release, so memory-api accepts a request that names a user without a ServiceAccount token. For an authenticated install, see Query memory from your own service.

We read the Workspace UID and namespace, then port-forward the service:

Terminal window
export WORKSPACE=<workspace-name>
export WORKSPACE_ID=$(kubectl get workspace $WORKSPACE -o jsonpath='{.metadata.uid}')
export NS=$(kubectl get workspace $WORKSPACE -o jsonpath='{.spec.namespace.name}')
export USER_ID=user-alex
kubectl -n $NS port-forward svc/memory-$WORKSPACE-default 18080:8080

In a second terminal:

Terminal window
export MEMORY_API=http://127.0.0.1:18080
curl -fsS $MEMORY_API/healthz

The command prints ok. We use the Workspace UID in every request below because the runtime scopes the agent’s memories by UID.

We patch the agent’s spec.memory with ambient retrieval and the memory tools both on:

Terminal window
kubectl -n $NS patch agentruntime <agent-name> --type merge -p '
spec:
memory:
enabled: true
retrieval:
enabled: true
strategy: composite
limit: 5
tools:
enabled: true
'
kubectl -n $NS get agentruntime <agent-name>

The command lists the agent. The runtime registers memory__remember and memory__recall only for a verified user: the facade must have exchanged the caller’s own credential for a session token. Anonymous and API-key conversations get no memory tools. USER_ID is a stable pseudonym, never an email address or other raw identifier.

The agent calls memory__remember for a verified user. We save the equivalent record directly:

Terminal window
MEMORY_ID=$(curl -fsS -X POST "$MEMORY_API/api/v1/memories" \
-H 'Content-Type: application/json' \
-d "$(cat <<JSON
{
"type": "preference",
"content": "Alex prefers metric units in measurements.",
"confidence": 0.95,
"scope": {
"workspace_id": "$WORKSPACE_ID",
"virtual_user_id": "$USER_ID"
},
"metadata": {
"provenance": "user_requested",
"source": "memory-basics"
}
}
JSON
)" | jq -r '.memory.id')
echo "saved memory: $MEMORY_ID"

The command prints the new memory ID.

We retrieve with the same workspace and user:

Terminal window
curl -fsS -X POST "$MEMORY_API/api/v1/memories/retrieve" \
-H 'Content-Type: application/json' \
-d "{
\"workspace_id\": \"$WORKSPACE_ID\",
\"user_id\": \"$USER_ID\",
\"query\": \"What units does Alex prefer?\",
\"limit\": 5
}"

The response lists the saved memory in memories. With an embedding provider configured, recall is hybrid lexical and vector. Without one it falls back to full-text search. Embeddings are generated asynchronously after a write.

We list the user’s records, then read the complete memory by its ID:

Terminal window
curl -fsS "$MEMORY_API/api/v1/memories?workspace=$WORKSPACE_ID&virtual_user_id=$USER_ID"
curl -fsS "$MEMORY_API/api/v1/memories/$MEMORY_ID?workspace=$WORKSPACE_ID&virtual_user_id=$USER_ID"

Both responses contain the memory. These routes take the user as virtual_user_id. A user_id query parameter returns 400 and names the right one; the retrieve body above is the only place the field is user_id.

We forget it with the delete operation:

Terminal window
curl -fsS -X DELETE \
"$MEMORY_API/api/v1/memories/$MEMORY_ID?workspace=$WORKSPACE_ID&virtual_user_id=$USER_ID"
curl -fsS "$MEMORY_API/api/v1/memories?workspace=$WORKSPACE_ID&virtual_user_id=$USER_ID"

The second list is empty because forgetting soft-deletes the memory.