thinkn
  • Product
    Manifesto
    The reason we exist
    Founder Studioprivate beta
    Make better product decisions faster
    Belief SDKinvite only
    Add belief states to your AI system
    Request Access →Join the private beta waitlist
  • Docs
  • Pricing
  • FAQ
  • Docs
  • Pricing
  • FAQ
Sign In
Welcome
  • Start Here
  • Install
  • Quickstart
  • FAQ
  • Why beliefs
  • Claude Agent SDK
  • Vercel AI
  • React
  • DevTools
adapters/claude-agent-sdk.mdx

Claude Agent SDK

Use beliefs with the Anthropic Claude Agent SDK. Automatic belief extraction from agent turns.

Hooks Adapter (recommended)

1npm i beliefs

The adapter integrates with the Claude Agent SDK's hook system. It captures tool results via PostToolUse hooks and injects belief context at SessionStart:

1import { query } from '@anthropic-ai/claude-agent-sdk'
2import Beliefs from 'beliefs'
3import { beliefsHooks } from 'beliefs/claude-agent-sdk'
4
5const beliefs = new Beliefs({
6  apiKey: process.env.BELIEFS_KEY,
7  agent: 'research-agent',
8  namespace: 'claude-sdk',
9  writeScope: 'thread',
10})
11
12// Pass hooks to the Claude Agent SDK query options
13const result = await query({
14  prompt: 'Research the competitive landscape for AI dev tools',
15  options: {
16    hooks: beliefsHooks(beliefs),
17  },
18})

beliefsHooks registers:

  • SessionStart: calls beliefs.before() and injects context via additionalContext
  • PostToolUse: calls beliefs.after(toolResult, {tool}) for each tool invocation

If the client is thread-scoped, beliefsHooks() resolves the thread automatically from Claude's session_id by default.

Capture Modes

1beliefsHooks(beliefs, { capture: 'tools' })    // each tool call result (default)
2beliefsHooks(beliefs, { capture: 'all' })      // tool results + text responses

Configuration

1beliefsHooks(beliefs, {
2  capture: 'all',
3  includeContext: true,
4  toolFilter: 'search|Read',  // regex to filter which tools trigger extraction
5})
OptionDefaultDescription
capture'tools'What to extract beliefs from
includeContexttrueInject belief context at session start
toolFilter—Regex matched against tool names. Example: 'search|Read' extracts only from search and Read; internal tools like Bash would be skipped.
resolveThreadIdinput.session_idOverride how thread IDs are derived. Pass a (input) => threadId function when your thread keying differs from Claude's session id (e.g., per-user threads).

Don't mix manual calls with hooks

When you use beliefsHooks(...), the adapter owns the lifecycle: SessionStart calls before(), PostToolUse calls after(). Calling beliefs.before() or beliefs.after() yourself in the same query produces duplicate extraction and double-counts evidence. Use one path or the other, not both.

Choosing a scope

Use writeScope: 'thread' when each Claude session should keep its own memory. Use writeScope: 'space' when all sessions in a namespace should share one state.


Without the adapter (manual before/after)

If you're not using the Claude Agent SDK's hook system (for example, you're using @anthropic-ai/sdk directly), wrap your calls manually:

1import Anthropic from '@anthropic-ai/sdk'
2import Beliefs from 'beliefs'
3
4const client = new Anthropic()
5const beliefs = new Beliefs({
6  apiKey: process.env.BELIEFS_KEY,
7  agent: 'research-agent',
8  namespace: 'claude-sdk',
9  writeScope: 'space',
10})
11
12async function research(question: string) {
13  const context = await beliefs.before(question)
14
15  const message = await client.messages.create({
16    model: 'claude-sonnet-4-20250514',
17    max_tokens: 4096,
18    system: context.prompt,
19    messages: [{ role: 'user', content: question }],
20  })
21
22  const text = message.content
23    .filter(b => b.type === 'text')
24    .map(b => b.text)
25    .join('')
26
27  const delta = await beliefs.after(text)
28  return { text, delta }
29}

With tool results

Feed each tool result separately so beliefs update mid-turn:

1const context = await beliefs.before(question)
2
3const message = await client.messages.create({
4  model: 'claude-sonnet-4-20250514',
5  max_tokens: 4096,
6  system: context.prompt,
7  messages: [{ role: 'user', content: question }],
8  tools: myTools,
9})
10
11for (const block of message.content) {
12  if (block.type === 'tool_use') {
13    const result = await executeTool(block.name, block.input)
14    await beliefs.after(JSON.stringify(result), { tool: block.name })
15  } else if (block.type === 'text') {
16    await beliefs.after(block.text)
17  }
18}

Multi-turn loop

Run multiple turns and let clarity drive when to stop:

1async function deepResearch(question: string) {
2  for (let turn = 0; turn < 10; turn++) {
3    const context = await beliefs.before(question)
4
5    if (context.clarity > 0.8) {
6      return context.beliefs
7    }
8
9    const message = await client.messages.create({
10      model: 'claude-sonnet-4-20250514',
11      max_tokens: 4096,
12      system: context.prompt,
13      messages: [{ role: 'user', content: question }],
14    })
15
16    const text = message.content
17      .filter(b => b.type === 'text')
18      .map(b => b.text)
19      .join('')
20
21    await beliefs.after(text)
22  }
23}

Patterns

Common integration patterns with the core SDK.

Learn more

Hack Guide

Quick framework recipes for hackathons.

Learn more
PreviousErrors
NextVercel AI

On this page

  • Hooks Adapter (recommended)
  • Capture Modes
  • Configuration
  • Without the adapter (manual before/after)
  • With tool results
  • Multi-turn loop