---
title: Scoping & Isolation
description: "How namespace, writeScope, thread, and contextLayers shape belief state."
---

The beliefs SDK has four scoping controls that determine how memory is isolated and shared:

- `namespace`: the developer-facing workspace boundary
- `writeScope`: the authoritative layer you mutate
- `thread`: the bound thread ID for thread-scoped memory
- `agent`: who contributed the mutation

`contextLayers` then controls what `before()` and `read()` merge back into the prompt context.

### Quick decision tree

- **Single app or prototype?** → `writeScope: 'space'`, share one namespace.
- **Multi-agent collaborating on the same problem?** → `writeScope: 'space'`, distinct `agent` values, shared `namespace`.
- **Per-conversation chat memory?** → `writeScope: 'thread'` (the default), bind `thread: conversationId`.
- **Background worker with its own scratchpad?** → `writeScope: 'agent'`, distinct `agent` per worker.

## Namespace

Namespaces are your top-level isolation boundary. Beliefs in different namespaces never interact.

```ts
const projectA = new Beliefs({
  apiKey,
  namespace: 'project-alpha',
  writeScope: 'space',
})

const projectB = new Beliefs({
  apiKey,
  namespace: 'project-beta',
  writeScope: 'space',
})
```

**Default:** `'default'`

**Use for:** per-customer isolation, per-project separation, or per-environment separation.

## Authoritative Write Scopes

### `thread`

Per-conversation or per-task memory. This is the SDK default.

```ts
const beliefs = new Beliefs({
  apiKey,
  namespace: 'support',
  thread: 'conv-a',
  writeScope: 'thread',
})
```

- Requires a bound `thread`
- Best for chat apps, workflow runs, and task-specific reasoning
- Default read layers: `['self', 'agent', 'space']`. `'self'` is the current thread, `'agent'` is this agent's durable memory, `'space'` is the shared namespace state. Reads merge all three.

### `agent`

Durable per-agent memory inside a namespace.

```ts
const researcher = new Beliefs({
  apiKey,
  namespace: 'market-map',
  agent: 'researcher',
  writeScope: 'agent',
})
```

- Best for long-lived worker identity or agent-specific scratchpads
- Keeps one agent's memory separate from another's
- Default read layers: `['self', 'space']`

### `space`

One shared memory for the whole namespace.

```ts
const beliefs = new Beliefs({
  apiKey,
  namespace: 'team-alpha',
  writeScope: 'space',
})
```

- Best for the simplest prototype or shared-team state
- All callers in the namespace read and write the same authoritative layer
- Default read layers: `['self']`

## Thread Binding

If you use `writeScope: 'thread'`, bind a thread either in the constructor or later with `withThread()`.

### Bind in the constructor

```ts
const beliefs = new Beliefs({
  apiKey,
  namespace: 'support',
  thread: conversationId,
  writeScope: 'thread',
})
```

### Bind later with `withThread()`

```ts
const baseBeliefs = new Beliefs({
  apiKey,
  namespace: 'support',
  writeScope: 'thread',
})

const beliefs = baseBeliefs.withThread(conversationId)
```

This is useful when the framework gives you the thread or session ID at request time.

## Agent Identity

`agent` answers "who said this?" It affects attribution and how contributions are weighted when sources disagree. It does **not** by itself decide whether memory is shared.

```ts
const researcher = new Beliefs({
  apiKey,
  namespace: 'team-alpha',
  agent: 'researcher',
  writeScope: 'space',
})

const reviewer = new Beliefs({
  apiKey,
  namespace: 'team-alpha',
  agent: 'reviewer',
  writeScope: 'space',
})
```

These two agents share the same authoritative state because they share the same `namespace` and `writeScope: 'space'`.

## Context Layers

`contextLayers` controls what `before()` and `read()` merge together.

| Write scope | Default read layers | What gets merged |
|-------------|---------------------|------------------|
| `thread` | `['self', 'agent', 'space']` | Current thread + this agent's memory + namespace-wide state |
| `agent` | `['self', 'space']` | This agent's durable memory + namespace-wide state |
| `space` | `['self']` | Just the namespace-wide shared state |

The available layer values are `'self'`, `'agent'`, `'space'`, `'studio'`, and `'org'`. `'studio'` and `'org'` are reserved for hosted-platform integrations and don't apply to most app-builder consumers.

You can override the defaults when you need a narrower or wider context:

```ts
const beliefs = new Beliefs({
  apiKey,
  namespace: 'support',
  thread: conversationId,
  writeScope: 'thread',
  contextLayers: ['self', 'space'],
})
```

## Design Patterns

### Fastest prototype

Use one shared namespace-wide state.

```ts
const beliefs = new Beliefs({
  apiKey: process.env.BELIEFS_KEY,
  namespace: 'prototype',
  writeScope: 'space',
})
```

### Chat application

Use per-conversation memory.

```ts
function createBeliefs(userId: string, conversationId: string) {
  return new Beliefs({
    apiKey: process.env.BELIEFS_KEY,
    namespace: userId,
    thread: conversationId,
    writeScope: 'thread',
  })
}
```

### Durable per-agent memory with shared background

```ts
const beliefs = new Beliefs({
  apiKey,
  namespace: 'research-team',
  agent: 'analyst',
  writeScope: 'agent',
})
```

This keeps one agent's working memory separate while still reading shared namespace context.

### Shared workspace or debate

```ts
const optimist = new Beliefs({
  apiKey,
  namespace: 'market-debate',
  agent: 'optimist',
  writeScope: 'space',
})

const skeptic = new Beliefs({
  apiKey,
  namespace: 'market-debate',
  agent: 'skeptic',
  writeScope: 'space',
})
```

All participants write into the same shared state, so contradictions and supports are visible to everyone.

### Environment isolation

```ts
const ENV = process.env.NODE_ENV ?? 'development'

const beliefs = new Beliefs({
  apiKey: process.env.BELIEFS_KEY,
  namespace: `${ENV}-${projectId}`,
  writeScope: 'space',
})
```

## Rules of Thumb

| Question | Recommendation |
|----------|----------------|
| Do I want separate memory per conversation? | Use `writeScope: 'thread'` and bind a thread |
| Do I want one shared state for a whole project or team? | Use `writeScope: 'space'` |
| Do I want each agent to keep its own durable memory? | Use `writeScope: 'agent'` with distinct `agent` values |
| Do I need to scope one project away from another? | Use different `namespace` values |
| Do I need broader background context than the current write scope? | Override `contextLayers` |

<CardGroup cols={2}>
  <DocsCard title="Loop Patterns" description="How to structure your agent loop." href="/dev/sdk/patterns" />
  <DocsCard title="Core API" description="Constructor options and method reference." href="/dev/sdk/core-api" />
</CardGroup>
