# LangChain

LangChain and LangGraph integration for SurrealDB Agent Memory, with retrievers, agent tools, and a LangGraph store.

SurrealDB ships an official integration for the [LangChain.js](https://js.langchain.com) and [LangGraph.js](https://langchain-ai.github.io/langgraphjs/) ecosystems. It wraps the [`@surrealdb/spectron`](https://www.npmjs.com/package/@surrealdb/spectron) client so a chain or agent can retrieve from SurrealDB Agent Memory's knowledge base, expose memory as tools, and read memory through a LangGraph store.

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

The integration is TypeScript. Python applications call SurrealDB Agent Memory through the [Python SDK](/docs/agent-memory/integrations/sdks/python.md) or the [REST API](/docs/agent-memory/integrations/surfaces/rest.md) instead.

## Packages

| Package | What it provides |
| --- | --- |
| `@surrealdb/langchain-core` | Shared SurrealDB client, config, schema and filter helpers, and the SurrealDB Agent Memory HTTP client |
| `@surrealdb/langchain` | `VectorStore`, hybrid `Retriever`, `SpectronRetriever`, agent tools, and a persisting chat model wrapper |
| `@surrealdb/langgraph` | LangGraph `BaseCheckpointSaver`, `BaseStore`, and `SpectronStore`, backed by SurrealDB Agent Memory |

## Requirements

- Node.js 22+ or Bun 1+
- SurrealDB Agent Memory access: endpoint, context, and API key

## Installation

```bash
bun add @surrealdb/langchain @surrealdb/langgraph @surrealdb/spectron
```

## Configure the client

Construct a client directly, or resolve one from the environment:

```typescript
import { Spectron } from "@surrealdb/langchain-core";

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

`resolveSpectron` reads `SPECTRON_ENDPOINT`, `SPECTRON_API_KEY`, and `SPECTRON_CONTEXT`, throwing a clear error if any is missing:

```typescript
import { resolveSpectron } from "@surrealdb/langchain-core";

const spectron = resolveSpectron({}); // all three from the environment
```

| Field | Required | Notes |
| --- | --- | --- |
| `context` | Yes | Context id, for example `"acme-prod"`. Pins every request to `/api/v1/{context}/…`. |
| `apiKey` | Yes | Bearer token, sent as `Authorization: Bearer …`. |
| `endpoint` | Yes | SurrealDB Agent Memory API origin, no trailing slash. There is no implicit default host. |

## Retrieval

`SpectronRetriever` turns knowledge-base hits into LangChain `Document`s, with the chunk text as `pageContent` and document, chunk, score, and graph metadata in `metadata`:

```typescript
import { SpectronRetriever } from "@surrealdb/langchain/retrievers";

const retriever = new SpectronRetriever({
    client: spectron,
    mode: "hybrid_graph", // "vector" | "bm25" | "hybrid" | "hybrid_graph"
    k: 8,
});

const docs = await retriever.invoke("what is the return policy?");
```

## Agent tools

Two `StructuredTool`s wire SurrealDB Agent Memory into an agent. Both accept either an instantiated `client` or a plain config object resolved from `SPECTRON_*` environment variables:

```typescript
import { SpectronQueryTool, SpectronReflectTool } from "@surrealdb/langchain/tools";

const tools = [
    new SpectronQueryTool({ client: spectron }),
    new SpectronReflectTool({ client: spectron }),
];
```

`SpectronQueryTool` takes `{ query, k?, mode?, filter? }` and returns a compact JSON array of hits. `SpectronReflectTool` takes `{ query, persist? }` and returns the reflection.

## LangGraph store

`SpectronStore` is a read-oriented `BaseStore` adapter. Reads delegate to SurrealDB Agent Memory; writes are not supported, because Agent Memory persists memory through sessions and reflections rather than raw key/value puts:

```typescript
import { SpectronStore } from "@surrealdb/langgraph/spectron_store";

const store = new SpectronStore({ spectron });

await store.get(["Person"], "tobie"); // → entities.get
await store.search(["Person"], { query: "who is tobie?", limit: 5 }); // → recall
```

| Method | Backed by | Supported |
| --- | --- | --- |
| `get` | `entities.get` | Yes |
| `search` | `recall` | Yes (requires `query`) |
| `put` / `delete` / `listNamespaces` | n/a | Throws |

## Vector store without agent memory

`@surrealdb/langchain` also exposes a `VectorStore` backed by SurrealDB's native HNSW index, for RAG against a SurrealDB instance you run yourself rather than the hosted agent memory service:

```typescript
import { OpenAIEmbeddings } from "@langchain/openai";
import { VectorStore } from "@surrealdb/langchain";

const store = await VectorStore.initialize(new OpenAIEmbeddings(), {
    surreal: { url: "ws://localhost:8000", username: "root", password: "root", namespace: "app", database: "rag" },
    tableName: "documents",
    dimensions: 1536,
});
```

## When to use MCP or the SDK instead

- If the host is Claude, Cursor, or another MCP-native client, prefer the [MCP server](/docs/agent-memory/integrations/mcp-server/install.md), with no adapter required.
- If your application calls SurrealDB Agent Memory directly rather than through LangChain, use the [JavaScript SDK](/docs/agent-memory/integrations/sdks/javascript-and-typescript.md).
