# JavaScript and TypeScript SDK

Using SurrealDB Agent Memory from JavaScript and TypeScript applications.

Published package: **`@surrealdb/spectron`**, a typed REST client for the SurrealDB Agent Memory end-user API. It uses platform `fetch`, ships no runtime dependencies, and aligns with SurrealDB Agent Memory’s OpenAPI specification.

> [!NOTE]
> `Spectron` was the project name for SurrealDB Agent Memory. These type names
> will be renamed in a future release.

> **npm:** The client is published under the **`@surrealdb`** scope (`@surrealdb/spectron`), so no third party can squat the namespace. The bare name `spectron` on npm is unrelated.

## Installation

```bash
npm install @surrealdb/spectron
# or: pnpm / yarn / bun add @surrealdb/spectron
```

Node.js 18+ or a modern bundler for browser use.

## Client construction

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

const client = new Spectron({
  endpoint: process.env.SPECTRON_ENDPOINT!,
  context: "acme-prod",
  apiKey: process.env.SPECTRON_API_KEY!,
});
```

The client is **async-only** (all methods return Promises). It is pinned to one context and calls `/api/v1/{context}/…`.

| Option | Default | Description |
| --- | --- | --- |
| `context` | required | Context id. |
| `endpoint` | required | SurrealDB Agent Memory host URL. |
| `apiKey` | required | Bearer token. |
| `timeout` | `30000` | Milliseconds per request. |
| `maxRetries` | `3` | Retries for GETs and idempotent writes. |

## Scope

On the wire, scope is a **ScopeSet**: an ordered array of slash-path strings (for example `["org/acme/user/alice"]`). Register paths before first use; see [Contexts and scope](/docs/agent-memory/mental-model/contexts-and-scope.md).

The TypeScript client accepts a path string or an array of paths, and both serialise to the wire `ScopeSet`.

## Remember and recall

```typescript
await client.remember("Alice was promoted to CTO.", {
  infer: "full",
  scope: ["org/acme/user/alice"],
});

await client.rememberMany([
  { role: "user", content: "I was promoted to CTO." },
  { role: "assistant", content: "Congratulations!" },
], { scope: ["org/acme/user/alice"] });

const hits = await client.recall("What is Alice's role?", { k: 10 });

const block = await client.context("What is Alice's role?", { k: 10 });
```

`remember` and `rememberMany` attach an `Idempotency-Key` header for safe retries within a 30-second window.

## Documents and chat

```typescript
const doc = await client.documents.upload({
  file: documentFile,
  title: "Returns policy",
  scope: ["org/acme/team/eng"],
  labels: ["team=eng"],
});

await client.chat("Summarise what you know about Alice", {
  scope: ["user/alice"],
});

const stream = await client.chat("Tell me a story", { stream: true });
for await (const chunk of stream) {
  process.stdout.write(chunk.delta);
}
```

## Other verbs and namespaces

Top-level: `forget`, `consolidate`, `reflect`, `elaborate`, `state`, `profile`, `inspect`, `audit`, `fsck`, `health`.

Namespaces: `client.documents` (including `keywords`), `client.sessions`, `client.entities`, `client.scopes`, `client.principals`, `client.traces`, `client.lifecycle`.

→ Full tables: [JavaScript SDK reference](/docs/agent-memory/reference/sdk-javascript.md)

## Errors and retries

The client throws typed errors so you can branch on failure precisely.

```typescript
import {
  AuthError,
  ConnectionError,
  NotFoundError,
  RateLimitError,
  ScopeError,
  ServerError,
  SpectronError,
  ValidationError,
} from "@surrealdb/spectron";

try {
  const hits = await client.recall("what is my name?", { scope: ["user/alice"] });
} catch (err) {
  if (err instanceof AuthError) { /* 401 */ }
  else if (err instanceof ScopeError) { /* 403 */ }
  else if (err instanceof NotFoundError) { /* 404 */ }
  else if (err instanceof ValidationError) { /* 400 / 422 */ }
  else if (err instanceof RateLimitError) { console.log(err.retryAfter); }
  else if (err instanceof ServerError) { /* 5xx after retries */ }
  else if (err instanceof ConnectionError) { /* network / timeout */ }
  else if (err instanceof SpectronError) { /* other */ }
}
```

| Exception | HTTP | When it occurs |
| --- | --- | --- |
| `SpectronError` | n/a | Base class |
| `AuthError` | 401 | Invalid or missing API key |
| `ScopeError` | 403 | Scope or principal denial |
| `NotFoundError` | 404 | Resource not found |
| `ValidationError` | 400 / 422 | Malformed request |
| `RateLimitError` | 429 | Rate or token budget exceeded (`retryAfter` when provided) |
| `ServerError` | 5xx | Server error, retried for idempotent calls |
| `ConnectionError` | n/a | Network failure or timeout |

`GET` requests and idempotent writes (`remember`, `rememberMany`) retry automatically on connection errors and 5xx responses: up to `maxRetries` attempts (default 3) with 250 ms, 500 ms, 1000 ms backoff. Other writes and 4xx responses are not retried. Tune or disable on the constructor:

```typescript
const client = new Spectron({ ..., maxRetries: 0, timeout: 10000 });
```

The default timeout is 30,000 ms; streaming chat disables the read timeout while tokens arrive. On a 429, read `RateLimitError.retryAfter` and back off before retrying manually. All errors follow [RFC 7807 Problem Details](/docs/agent-memory/reference/errors.md).

## Vercel AI SDK adapter

```bash
npm install @surrealdb/spectron-vercel-ai
```

→ [Vercel AI SDK](/docs/agent-memory/integrations/ai-sdks/vercel-ai-sdk.md)

## Reference

[JavaScript SDK reference](/docs/agent-memory/reference/sdk-javascript.md) · [REST API](/docs/agent-memory/reference/rest-api.md)
