Skip to content

Reference

Agent guide (AGENTS.md)

This page is written for coding agents (Cursor, Claude Code, Copilot, and similar) building on SurrealDB Agent Memory. Humans can read it too, but the tone is imperative: what to do, what not to do, and where the sharp edges are.

Note

Spectron was the project name for SurrealDB Agent Memory. These type names will be renamed in a future release.

Use it as a Cursor skill: copy this file into .cursor/rules/spectron.mdc, add it as a project rule, or save it under .cursor/skills/spectron/SKILL.md with a short description in the frontmatter so the agent loads it when working on SurrealDB Agent Memory integrations.

Full product docs can be found at SurrealDB Agent Memory documentation. This guide is the minimum viable canon for “vibe coding” without reading all of it.

SurrealDB Agent Memory is a memory and knowledge layer for AI agents backed by SurrealDB. You send turns and documents in; SurrealDB Agent Memory extracts structured facts (entities, attributes, relations), reconciles contradictions, and retrieves context for later queries.

Two streams share one graph:

  • Experiential - chat turns, sessions, reflections.

  • Authoritative - uploaded documents and curated knowledge.

When they disagree, SurrealDB Agent Memory records uncertainty - it does not silently pick a winner.

Every request uses a Bearer token:

Authorization: Bearer sp-…

Do not use API-KEY, X-API-Key, or query-string secrets.

Each key is a data-plane key, bound to a principal with grant regions, and is used for /api/v1/{context_id}/… routes.

Context id is in the URL path, not a header. MCP tools resolve it from the key (see below).

Memory is partitioned by scope - hierarchical paths like org/acme/user/alice. Every read and write is clamped to the caller’s effective grants.

Grant verbs (always noun:verb):

VerbUse for
memory:readRecall, query, chat, document GET/list
memory:writeTurns, fact writes, document upload
memory:forgetForget, entity delete, scoped erasure
scope:readList scope names (no data access)
scope:createRegister scope paths
scope:deleteRemove scope paths
grant:manageGrant/revoke on principals

Rules agents must respect:

  1. Pass scopes on writes and lens on reads when the user or session is scoped. Request fields that the server does not know are ignored without an error, so a misspelt or wrongly cased field (scope on /query, limit instead of k) gives an unscoped or default request.

  2. labels and lens filter within the grant; they never widen access.

  3. Delegation uses X-Spectron-On-Behalf-Of: <principal_id> (depth 1 only). Effective authority is the intersection of caller and target grants.

  4. Flat verb names (read, write, …) are rejected - use namespaced forms (memory:read, memory:write, …).

Introspect the caller without admin access:

GET /api/v1/{context_id}/me

Base path: /api/v1/{context_id}/…

GoalMethodPath
Structured recallPOST/query
LLM-ready context stringPOST/context
Managed chat loopPOST/chat or /sessions/{id}/chat
Record a turnPOST/facts with session_id and role
Upload documentPOST/documents (multipart)
Document-only searchPOST/documents/query
On-demand reflectionPOST/reflect
Semantic forget (preview or apply)POST/forget - use dryRun: true to preview
Trace detailGET/traces/{trace_id}
{
  "query": "What is Alice's role?",
  "lens": ["org/acme/user/alice"],
  "k": 10,
  "include": ["facts", "passages"],
  "asOf": "2025-02-01T00:00:00Z",
  "source": "my-app"
}

The /query body uses camelCase field names: k, lens, scopeView, asOf, sessionId. The /facts write body uses snake_case (session_id, observed_at).

  • asOf - known-time recall (what we believed then). Distinct from valid-time on entities.

  • source - audit label on the retrieval trace only; does not change ranking.

  • mode - hybrid, vector, bm25, or graph only; invalid values → 400.

  • Response includes tier, hits, inline trace, and queryMs.

Create a session, append turns, or let SurrealDB Agent Memory run the full loop:

POST /api/v1/{context_id}/sessions                       # create
GET  /api/v1/{context_id}/sessions/{session_id}/turns    # read the transcript
POST /api/v1/{context_id}/sessions/{session_id}/context  # retrieve for this session
POST /api/v1/{context_id}/facts                          # append a turn (session_id in body)
POST /api/v1/{context_id}/chat                           # full loop (sessionId in body)

Turns are appended through /facts with a session_id, not through a per-session turns route - that route is read-only. Likewise /chat is Context-level and takes sessionId in the body.

Use remember() + sessions.context() when you need your own LLM, tools, or streaming. Use chat() when SurrealDB Agent Memory should retrieve, call the response model, and persist the reply.

Remote MCP endpoint: your instance base URL plus /mcp - for example https://<your-context-host>/mcp. The host is shown in the SurrealDB Studio API keys view.

Headers:

{
  "Authorization": "Bearer <api-key>"
}

context_id is optional on each tool because the bearer key already pins one Context. Scope is per tool: scope on writes such as remember, and lens on reads such as recall and context (slash paths, for example ["org/acme/user/alice"]).

Seven tools: remember, recall, context, reflect, forget, upload, inspect - see MCP tools.

Limits: k / limit on recall and context defaults to 10 and is capped at 50. The retrieval candidate pool is internal and is not widened by raising k. Oversized k returns 400 before retrieval runs.

Errors: operation failures use isError: true with structuredContent.error.status (same codes as REST). JSON-RPC error is for protocol faults only. See MCP error handling.

Install helper (install-mcp - pass the /mcp URL as the first argument, auth via --header):

npx install-mcp https://<your-context-host>/mcp \
  --client cursor \
  --header "Authorization: Bearer <api-key>" --oauth no

See Cursor.

Prefer an official SDK over raw HTTP when available:

from surrealdb.memory import Memory

memory = Memory(context="acme-prod",
    api_key=os.environ["SPECTRON_API_KEY"])
await memory.sessions.create(scopes=["org/acme/user/alice"])
import { AgentMemory } from "@surrealdb/memory";

const memory = new AgentMemory({ context: "acme-prod",
    apiKey: process.env.SPECTRON_API_KEY });

Model assignment is per Context for LLM stages; embedding is deployment-fixed - do not try to set models.embedding in Context configuration.

WhoHow
AdminSurrealDB Studio API keys view, bound to a principal
SurrealDB CloudShort-lived access token brokered by SurrealDB Cloud for a member
MemberPOST /api/v1/{ctx}/keys after holding a brokered key (self-service; grants may only attenuate)

Unbound or “scoped mint in body” key routes are removed. Always bind keys to a principal.

Rotate in place:

POST /api/v1/{context_id}/keys/{name}/rotate?ttl_seconds=2592000
  1. No scope on writes - facts land in the wrong region or get rejected.

  2. Treating labels as scope - labels=["team=platform"] filters; it does not grant access.

  3. Expecting embedding config per Context - the embedding model is fixed to gemini-embedding-2 for the whole deployment.

  4. Ignoring memory_updates / trace - when debugging wrong answers, fetch GET …/traces/{traceId} and check resolutionTier.

  5. Assuming last-write-wins - contradictions become uncertainty records; design UIs accordingly.

  6. Idempotent retries without idempotency keys - duplicate writes may return 409; use idempotency headers where documented.

  7. use_reranker: true without a reranker - depends on the deployment having a reranker provider, or it falls back to bi-encoder order.

  8. MCP JSON-RPC errors for business failures - not-found and auth failures return isError: true with error.status, not JSON-RPC -32603.

  9. POST /forget without checking dry run - pass dryRun: true (or agent-memory forget --dry-run) to preview; omitting it expires records immediately.

  10. Per-Context OCR/STT config - multimodal providers depend on the deployment and are not Context configuration fields.

Error bodies are {"message": "..."}, and the status is the HTTP status code (see Errors). Typical codes:

  • 401 - missing/invalid/expired key

  • 403 - grant does not cover requested scope

  • 400 - invalid mode, grant widening, or limit exceeded

  • 409 - duplicate key name or idempotency conflict

TopicDoc
REST surfaceREST API
Contexts and keys on CloudAgent Memory on SurrealDB Cloud
Scope modelContexts and scope
Retrieval tiersCoherence, retrieval, and cost tiers
Keys and Cloud brokerageKey policy
MCP schemasMCP tools

SurrealDB Agent Memory is designed to be auditable, so verify against traces before changing application logic when behaviour seems wrong.

Was this page helpful?