> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.recursiv.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.recursiv.io/_mcp/server.

# Brain & Memory

## Overview

The SDK provides three related resources for AI agent memory and project intelligence:

* **`r.memory`** -- Persistent facts and decisions that survive across sessions. Network-scoped.
* **`r.brain`** -- Send messages to the Brain AI (response streams via WebSocket).
* **`r.projectBrain`** -- Per-project dashboard: tasks, milestones, team activity, usage stats.

## Memory (`r.memory`)

### Facts

Store and retrieve facts -- things worth remembering across sessions such as patterns, conventions, preferences, and gotchas.

#### Store a fact

```typescript
const { data: fact } = await r.memory.facts.add({
  fact: 'This project uses Hono, not Express',
  project_id: 'proj_123',
  source: 'manual',
  tags: ['architecture', 'routing'],
});

console.log(fact.id);
console.log(fact.fact);
console.log(fact.tags);
```

**Input fields:**

| Field             | Type                                 | Required | Description                                       |
| ----------------- | ------------------------------------ | -------- | ------------------------------------------------- |
| `fact`            | `string`                             | Yes      | The fact to remember.                             |
| `project_id`      | `string?`                            | No       | Scope to a project.                               |
| `organization_id` | `string?`                            | No       | Scope to an organization.                         |
| `agent_id`        | `string?`                            | No       | Associate with a specific agent.                  |
| `user_id`         | `string?`                            | No       | Associate with a specific user.                   |
| `source`          | `'auto' \| 'manual' \| 'extraction'` | No       | How the fact was discovered. Default: `'manual'`. |
| `tags`            | `string[]?`                          | No       | Tags for categorization.                          |

> **Note**
>
> Memory rejects facts that appear to contain secrets (API keys, passwords, tokens). Store secrets in environment variables instead.

#### List facts

```typescript
const { data: facts } = await r.memory.facts.list({
  project_id: 'proj_123',
});

for (const fact of facts) {
  console.log(`[${fact.source}] ${fact.fact}`);
  console.log(`  Tags: ${fact.tags.join(', ')}`);
}
```

**Filter parameters:**

| Parameter         | Type      | Description                    |
| ----------------- | --------- | ------------------------------ |
| `project_id`      | `string?` | Filter by project.             |
| `organization_id` | `string?` | Filter by organization.        |
| `agent_id`        | `string?` | Filter by agent.               |
| `user_id`         | `string?` | Filter by user.                |
| `query`           | `string?` | Full-text search within facts. |

#### Remove a fact

```typescript
await r.memory.facts.remove('fact_123');
```

### Decisions

Log architectural, strategic, or technical decisions with context. Decisions are searchable and shared across the organization.

#### Log a decision

```typescript
const { data: decision } = await r.memory.decisions.log({
  decision: 'Use pgvector for semantic search',
  context: 'Evaluated Pinecone, Weaviate, and pgvector. Chose pgvector for simplicity -- it runs in our existing Postgres instance with no additional infrastructure.',
  tags: ['architecture', 'database', 'search'],
  project_id: 'proj_123',
});

console.log(decision.id);
console.log(decision.decision);
```

**Input fields:**

| Field             | Type        | Required | Description                                         |
| ----------------- | ----------- | -------- | --------------------------------------------------- |
| `decision`        | `string`    | Yes      | The decision that was made.                         |
| `context`         | `string?`   | No       | Why the decision was made, alternatives considered. |
| `tags`            | `string[]?` | No       | Tags for categorization.                            |
| `project_id`      | `string?`   | No       | Scope to a project.                                 |
| `organization_id` | `string?`   | No       | Scope to an organization.                           |
| `agent_id`        | `string?`   | No       | Associate with an agent.                            |

#### List decisions

```typescript
const { data: decisions } = await r.memory.decisions.list({
  project_id: 'proj_123',
  topic: 'database',
  limit: 10,
});

for (const d of decisions) {
  console.log(`Decision: ${d.decision}`);
  console.log(`Context: ${d.context}`);
  console.log(`Tags: ${d.tags.join(', ')}`);
}
```

### Search memory

Search across all memory types (facts, decisions, and conversations) with relevance ranking.

```typescript
const { data: results } = await r.memory.search({
  query: 'authentication approach',
  project_id: 'proj_123',
  limit: 10,
});

for (const result of results) {
  console.log(`[${result.type}] Score: ${result.score}`);
  console.log(`  ${result.content}`);
}
```

**Input fields:**

| Field             | Type      | Required | Description               |
| ----------------- | --------- | -------- | ------------------------- |
| `query`           | `string`  | Yes      | Search query.             |
| `project_id`      | `string?` | No       | Scope to a project.       |
| `organization_id` | `string?` | No       | Scope to an organization. |
| `agent_id`        | `string?` | No       | Filter by agent.          |
| `limit`           | `number?` | No       | Max results (default 10). |

**Returns:** `SingleResponse<MemorySearchResult[]>`

```typescript
interface MemorySearchResult {
  type: 'fact' | 'decision' | 'conversation';
  id: string;
  content: string;
  score: number;
  metadata: Record<string, unknown>;
}
```

### Build context injection

Build a formatted context block from relevant memories for a given message. Use this to enrich system prompts with past knowledge.

```typescript
const { data: { context } } = await r.memory.context({
  message: 'How should I implement the payment flow?',
  project_id: 'proj_123',
  max_tokens: 2000,
});

// Use the context in a system prompt
const systemPrompt = `You are a helpful assistant.

## Relevant context from memory:
${context}

Now answer the user's question.`;
```

**Input fields:**

| Field             | Type      | Required | Description                                         |
| ----------------- | --------- | -------- | --------------------------------------------------- |
| `message`         | `string`  | Yes      | The current message/task to find context for.       |
| `project_id`      | `string?` | No       | Scope to a project.                                 |
| `organization_id` | `string?` | No       | Scope to an organization.                           |
| `agent_id`        | `string?` | No       | Filter by agent.                                    |
| `max_tokens`      | `number?` | No       | Token budget for the context string (default 2000). |

### Purge memory

Delete all memory (facts and decisions) for a project. This is irreversible.

```typescript
const { data: result } = await r.memory.purge('proj_123');

console.log(`Deleted ${result.factsDeleted} facts and ${result.decisionsDeleted} decisions`);
```

> **Warning**
>
> Purging memory is irreversible. All facts and decisions for the project will be permanently deleted.

## Brain (`r.brain`)

Send messages to the Brain AI. The response streams back via WebSocket.

```typescript
const { data: { message_id } } = await r.brain.sendMessage({
  message: 'What should I work on next?',
  history: [
    { role: 'user', content: 'I just finished the auth module.' },
    { role: 'assistant', content: 'Great! The next priority is the billing integration.' },
  ],
  context: {
    current_route: '/dashboard',
    org_slug: 'my-org',
  },
});

console.log('Message ID:', message_id);
// Listen on WebSocket for the streamed response
```

## Project Brain (`r.projectBrain`)

Per-project intelligence dashboard with tasks, milestones, team activity, and usage stats.

### List tasks

```typescript
const { data: tasks } = await r.projectBrain.tasks('proj_123', {
  status: 'pending',
  milestone: 'v1-launch',
});

for (const task of tasks) {
  console.log(`${task.title} [${task.status}] — effort: ${task.effort}`);
}
```

### Get project stats

```typescript
const { data: stats } = await r.projectBrain.stats('proj_123');
console.log(stats);
```

### List milestones

```typescript
const { data: milestones } = await r.projectBrain.milestones('proj_123');

for (const m of milestones) {
  console.log(`${m.name}: ${m.task_progress.completed}/${m.task_progress.total} tasks`);
  console.log(`  ${m.task_progress.percentage}% complete`);
}
```

### List project decisions

```typescript
const { data: decisions } = await r.projectBrain.decisions('proj_123', {
  limit: 5,
});
```

### List project agents

```typescript
const { data: agents } = await r.projectBrain.agents('proj_123');

for (const agent of agents) {
  console.log(`${agent.name} (@${agent.username}) — ${agent.model}`);
}
```

### Team activity

```typescript
const { data: activity } = await r.projectBrain.teamActivity('proj_123');

for (const member of activity.team) {
  console.log(`${member.name}: ${member.completed_count} completed, ${member.active_claim_count} active`);
  if (member.current_work) {
    for (const work of member.current_work) {
      console.log(`  Working on: ${work.task_title}`);
    }
  }
}

console.log('\nActive claims:');
for (const claim of activity.active_claims) {
  console.log(`  ${claim.task_title} — claimed by ${claim.agent_id}`);
}
```

### Complete a task

```typescript
await r.projectBrain.completeTask('proj_123', 'task_456', 'Implemented and tested');
```

### Get usage stats

```typescript
const { data: usage } = await r.projectBrain.usage('proj_123');

console.log(`Total requests: ${usage.total_requests}`);
console.log(`Input tokens: ${usage.input_tokens}`);
console.log(`Output tokens: ${usage.output_tokens}`);
console.log(`Cost: $${usage.cost_dollars.toFixed(4)}`);
```

## Golden path: agent with persistent memory

Here is a complete example of an agent that uses memory to maintain context across sessions:

```typescript
import { Recursiv } from '@recursiv/sdk';

const r = new Recursiv();

const PROJECT_ID = 'proj_123';
const AGENT_ID = 'agent_456';

// 1. Load relevant context from memory
const { data: { context } } = await r.memory.context({
  message: 'Review the latest code changes',
  project_id: PROJECT_ID,
  agent_id: AGENT_ID,
  max_tokens: 1500,
});

// 2. Chat with the agent, injecting memory context
const { data: reply } = await r.agents.chat(AGENT_ID, {
  message: `Context from memory:\n${context}\n\nPlease review the latest code changes and suggest improvements.`,
});

console.log('Agent response:', reply.content);

// 3. Store what the agent learned
await r.memory.facts.add({
  fact: 'Code review completed on 2025-01-15. Found 3 issues in auth module.',
  project_id: PROJECT_ID,
  agent_id: AGENT_ID,
  source: 'auto',
  tags: ['code-review', 'auth'],
});

// 4. Log the decision
await r.memory.decisions.log({
  decision: 'Refactor auth middleware to use async validation',
  context: 'Current sync validation blocks the event loop under load. Agent review identified this as the primary performance bottleneck.',
  project_id: PROJECT_ID,
  agent_id: AGENT_ID,
  tags: ['auth', 'performance'],
});
```