# Agent guide (AGENTS.md)

Instructions for coding agents integrating with SurrealDB Agent Memory - copy into Cursor rules or skills.

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](/docs/agent-memory.md). This guide is the minimum viable canon for “vibe coding” without reading all of it.

---

## What Agent Memory is

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.

---

## Authentication

Every request uses a Bearer token:

```http
Authorization: Bearer sk-…
```

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

- **Data-plane keys** - bound to a **principal** with grant regions. Used for `/api/v1/{context_id}/…` routes.
- **Management keys** - control plane only (`/api/v1/contexts/…`). Never embed in client apps or MCP configs shipped to end users.

Context id is in the **URL path**, not a header (except MCP - see below).

---

## Scope and grants

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`):

| Verb | Use for |
| --- | --- |
| `memory:read` | Recall, query, chat, document GET/list |
| `memory:write` | Turns, fact writes, document upload |
| `memory:forget` | Forget, entity delete, scoped erasure |
| `scope:read` | List scope names (no data access) |
| `scope:create` | Register scope paths |
| `scope:delete` | Remove scope paths |
| `grant:manage` | Grant/revoke on principals |

**Rules agents must respect:**

1. Pass **`scope`** on reads/writes when the user or session is scoped - never assume Context-wide access.
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:

```http
GET /api/v1/{context_id}/me
```

---

## Core HTTP surfaces

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

| Goal | Method | Path |
| --- | --- | --- |
| Structured recall | `POST` | `/query` |
| LLM-ready context string | `POST` | `/context` |
| Managed chat loop | `POST` | `/chat` or `/sessions/{id}/chat` |
| Record a turn | `POST` | `/sessions/{id}/turns` |
| Upload document | `POST` | `/documents` (multipart) |
| Document-only search | `POST` | `/documents/query` |
| On-demand reflection | `POST` | `/reflect` |
| Semantic forget (preview or apply) | `POST` | `/forget` - use `dryRun: true` to preview |
| Trace detail | `GET` | `/traces/{trace_id}` |

### `/query` essentials

```json
{
  "query": "What is Alice's role?",
  "scope": ["org/acme/user/alice"],
  "limit": 10,
  "include": ["facts", "passages"],
  "as_of": "2025-02-01T00:00:00Z",
  "source": "my-app"
}
```

- **`as_of`** - 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`**.

### Sessions

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

```http
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.

---

## MCP (Cursor, Claude Desktop, …)

Remote MCP endpoint: your instance base URL plus `/mcp` - for example `https://abc123.spectron.cloud/mcp` (SurrealDB Cloud: host from SurrealDB Studio **API keys**) or `http://localhost:9090/mcp` (self-hosted).

Headers:

```json
{
  "Authorization": "Bearer <api-key>",
  "X-Spectron-Context": "<context_id>"
}
```

`X-Spectron-Context` is a client-side convenience - **`context_id` is optional** on each tool because the bearer key already pins one Context. Scope is per tool via a **`scope`** argument (slash paths, for example `["org/acme/user/alice"]`).

Seven tools: `remember`, `recall`, `context`, `reflect`, `forget`, `upload`, `inspect` - see [MCP tools](/docs/agent-memory/reference/mcp-tools.md).

**Limits:** `k` / `limit` on `recall` and `context` defaults to **10** and is capped at **50** (`SPECTRON_MAX_QUERY_K`, clamp-down only). The retrieval candidate pool is internal (`SPECTRON_RETRIEVAL_POOL_SIZE`, default 256) 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](/docs/agent-memory/reference/mcp-tools.md#error-handling).

Install helper ([`install-mcp`](https://github.com/supermemoryai/install-mcp) - pass the `/mcp` URL as the first argument, auth via `--header`):

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

See [Cursor](/docs/agent-memory/integrations/mcp-server/coding-assistants/cursor.md).

---

## SDKs

Prefer an official SDK over raw HTTP when available:

```python
from surrealdb import Spectron

memory = Spectron(context="acme-prod",
    api_key=os.environ["SPECTRON_API_KEY"])
await memory.sessions.create(scopes=["org/acme/user/alice"])
```

```javascript
import { Spectron } from "@surrealdb/spectron";

const memory = new Spectron({ 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 config patches.

---

## Keys: minting patterns

| Who | How |
| --- | --- |
| Operator | `POST /api/v1/contexts/{ctx}/principals/{principal_id}/keys/{name}` (management key) |
| Cloud proxy | `POST /api/v1/contexts/{ctx}/access-tokens` with `external_id` + required `ttl_seconds` |
| Member | `POST /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:

```http
POST /api/v1/{context_id}/keys/{name}/rotate?ttl_seconds=2592000
```

---

## Common agent mistakes

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. **Using management keys in the app** - use principal-bound data-plane keys.
4. **Expecting embedding config per Context** - set `SPECTRON_MODEL_EMBEDDING` on the server; reindex after model changes.
5. **Ignoring `memory_updates` / trace** - when debugging wrong answers, fetch `GET …/traces/{traceId}` and check `resolutionTier`.
6. **Assuming last-write-wins** - contradictions become **`uncertainty`** records; design UIs accordingly.
7. **Idempotent retries without idempotency keys** - duplicate writes may return **`409`**; use idempotency headers where documented.
8. **`use_reranker: true` without server reranker** - requires `SPECTRON_RERANKER_URL` + `SPECTRON_RERANKER_MODEL` or it falls back to bi-encoder order.
9. **MCP JSON-RPC errors for business failures** - not-found and auth failures return **`isError: true`** with `error.status`, not JSON-RPC `-32603`.
10. **`POST /forget` without checking dry run** - pass **`dryRun: true`** (or `spectron forget --dry-run`) to preview; omitting it expires records immediately.
11. **Per-Context OCR/STT config** - multimodal HTTP providers are **deployment env vars** (`SPECTRON_OCR_*`, `SPECTRON_CLIP_*`, `SPECTRON_STT_*`), not Context patch fields.

---

## Idempotency and errors

Errors are [RFC 7807 problem details](/docs/agent-memory/reference/errors.md). 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

---

## What to read next

| Topic | Doc |
| --- | --- |
| REST surface | [REST API](/docs/agent-memory/reference/rest-api.md) |
| Control plane | [Management API](/docs/agent-memory/reference/management-api.md) |
| Scope model | [Contexts and scope](/docs/agent-memory/mental-model/contexts-and-scope.md) |
| Retrieval tiers | [Coherence, retrieval, and cost tiers](/docs/agent-memory/architecture/coherence-retrieval-and-tiers.md) |
| Keys and Cloud brokerage | [Key policy](/docs/agent-memory/reference/configuration.md#key-policy) |
| MCP schemas | [MCP tools](/docs/agent-memory/reference/mcp-tools.md) |

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