The beliefs SDK has four scoping controls that determine how memory is isolated and shared:
namespace: the developer-facing workspace boundarywriteScope: the authoritative layer you mutatethread: the bound thread ID for thread-scoped memoryagent: 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', distinctagentvalues, sharednamespace. - Per-conversation chat memory? →
writeScope: 'thread'(the default), bindthread: conversationId. - Background worker with its own scratchpad? →
writeScope: 'agent', distinctagentper worker.
Namespace
Namespaces are your top-level isolation boundary. Beliefs in different namespaces never interact.
1const projectA = new Beliefs({
2 apiKey,
3 namespace: 'project-alpha',
4 writeScope: 'space',
5})
6
7const projectB = new Beliefs({
8 apiKey,
9 namespace: 'project-beta',
10 writeScope: 'space',
11})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.
1const beliefs = new Beliefs({
2 apiKey,
3 namespace: 'support',
4 thread: 'conv-a',
5 writeScope: 'thread',
6})- 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.
1const researcher = new Beliefs({
2 apiKey,
3 namespace: 'market-map',
4 agent: 'researcher',
5 writeScope: 'agent',
6})- 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.
1const beliefs = new Beliefs({
2 apiKey,
3 namespace: 'team-alpha',
4 writeScope: 'space',
5})- 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
1const beliefs = new Beliefs({
2 apiKey,
3 namespace: 'support',
4 thread: conversationId,
5 writeScope: 'thread',
6})Bind later with withThread()
1const baseBeliefs = new Beliefs({
2 apiKey,
3 namespace: 'support',
4 writeScope: 'thread',
5})
6
7const 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.
1const researcher = new Beliefs({
2 apiKey,
3 namespace: 'team-alpha',
4 agent: 'researcher',
5 writeScope: 'space',
6})
7
8const reviewer = new Beliefs({
9 apiKey,
10 namespace: 'team-alpha',
11 agent: 'reviewer',
12 writeScope: 'space',
13})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:
1const beliefs = new Beliefs({
2 apiKey,
3 namespace: 'support',
4 thread: conversationId,
5 writeScope: 'thread',
6 contextLayers: ['self', 'space'],
7})Design Patterns
Fastest prototype
Use one shared namespace-wide state.
1const beliefs = new Beliefs({
2 apiKey: process.env.BELIEFS_KEY,
3 namespace: 'prototype',
4 writeScope: 'space',
5})Chat application
Use per-conversation memory.
1function createBeliefs(userId: string, conversationId: string) {
2 return new Beliefs({
3 apiKey: process.env.BELIEFS_KEY,
4 namespace: userId,
5 thread: conversationId,
6 writeScope: 'thread',
7 })
8}Durable per-agent memory with shared background
1const beliefs = new Beliefs({
2 apiKey,
3 namespace: 'research-team',
4 agent: 'analyst',
5 writeScope: 'agent',
6})This keeps one agent's working memory separate while still reading shared namespace context.
Shared workspace or debate
1const optimist = new Beliefs({
2 apiKey,
3 namespace: 'market-debate',
4 agent: 'optimist',
5 writeScope: 'space',
6})
7
8const skeptic = new Beliefs({
9 apiKey,
10 namespace: 'market-debate',
11 agent: 'skeptic',
12 writeScope: 'space',
13})All participants write into the same shared state, so contradictions and supports are visible to everyone.
Environment isolation
1const ENV = process.env.NODE_ENV ?? 'development'
2
3const beliefs = new Beliefs({
4 apiKey: process.env.BELIEFS_KEY,
5 namespace: `${ENV}-${projectId}`,
6 writeScope: 'space',
7})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 |