Skip to main content

Installation

npm install thrindex
# or
yarn add thrindex
# or
pnpm add thrindex
Requirements: Node.js 18+ (uses native fetch). Zero production dependencies.

Client

import { ThrindexClient } from 'thrindex';

const client = new ThrindexClient({
  apiKey: 'th_live_...',                    // required
  baseUrl: 'https://api.thrindex.com',      // optional, this is the default
  timeoutMs: 30_000,                        // optional, milliseconds (default 30 000)
  maxRetries: 3,                            // optional (default 3)
});
ThrindexClient is safe to share across concurrent requests — create one instance per application.

Constructor options (ClientOptions)

OptionTypeDefaultDescription
apiKeystringrequiredYour API key beginning with th_live_
baseUrlstring"https://api.thrindex.com"Override for self-hosted or test environments
timeoutMsnumber30_000Per-request timeout in milliseconds
maxRetriesnumber3Maximum retry attempts on 5xx and network errors

Methods

All methods are async and return Promise<T>.

add()

Store a memory for asynchronous processing.
const memoryId: string = await client.add({
  content: 'User prefers weekly email digests.',  // required
  agentId: 'support-agent',                        // required
  userId: 'user-42',                               // required
  confidence: 0.95,                                // optional
  metadata: { source: 'preference-survey' },       // optional
  extract: true,                                   // optional, default true
});

console.log(memoryId); // "3f2e1d0c-..."

AddOptions

FieldTypeRequiredDefaultDescription
contentstringyesThe memory text. Max 8192 bytes (≈8 KB).
agentIdstringyesAgent identifier. Max 256 chars. Charset: [A-Za-z0-9._:-]
userIdstringyesUser identifier. Same constraints as agentId.
confidencenumberno1.0 server-sideYour confidence in this memory’s accuracy, 0.01.0.
metadataRecord<string, unknown>noArbitrary key-value pairs stored with the memory.
extractbooleannotrueWhen true, the cognition worker runs LLM extraction on the content. Set to false to store verbatim with no LLM call.

Returns

Promise<string> — the memory UUID.
Retrieve the most relevant memories for a query.
import type { SearchHit } from 'thrindex';

const results: SearchHit[] = await client.search({
  query: 'how does the user want to be contacted',  // required
  agentId: 'support-agent',                          // required
  userId: 'user-42',                                 // required
  k: 10,                                             // optional, default 10
  taskContext: 'composing a notification email',     // optional
  level: undefined,                                  // optional, filter by level
});

for (const hit of results) {
  console.log(`[${hit.score.toFixed(3)}] ${hit.content}`);
}

SearchOptions

FieldTypeRequiredDefaultDescription
querystringyesNatural language query. Max 2048 characters.
agentIdstringyesLimits search to memories belonging to this agent.
userIdstringyesLimits search to memories belonging to this user.
knumberno10Number of results to return. Range: 1100.
taskContextstringnoA sentence describing what the agent is currently doing. Improves ranking for the current task.
levelnumberno— (all levels)Filter to a specific memory level: 0 (raw), 1 (abstraction).

Returns

Promise<SearchHit[]> — ordered by descending relevance score.

SearchHit

FieldTypeDescription
idstringMemory UUID
contentstringThe memory text
agentIdstringAgent that owns the memory
userIdstringUser the memory belongs to
levelnumber0 or 1
statusstring"active" or "deprecated"
importancenumberImportance score 0.01.0
confidencenumberConfidence score 0.01.0
scorenumberMulti-signal fusion score — use to compare results within a single response
createdAtstringISO 8601 creation timestamp

list()

List memories with cursor-based pagination.
import type { ListResponse } from 'thrindex';

let page: ListResponse = await client.list({
  agentId: 'support-agent',  // optional
  userId: 'user-42',         // optional
  limit: 50,                 // optional, default 50
});

for (const record of page.results) {
  console.log(record.id, record.importance);
}

// Iterate through all pages
while (page.nextCursor) {
  page = await client.list({
    agentId: 'support-agent',
    userId: 'user-42',
    cursor: page.nextCursor,
  });
}

ListOptions

FieldTypeRequiredDefaultDescription
agentIdstringnoFilter to a specific agent. Omit for org-wide listing.
userIdstringnoFilter to a specific user. Omit for all users.
limitnumberno50Results per page. Range: 1200.
cursorstringnoOpaque cursor from nextCursor of a previous response. Omit for the first page.

Returns

Promise<ListResponse> with:
  • results: MemoryRecord[] — current page (content excluded)
  • nextCursor?: string — undefined when no more pages
content is excluded from list results. Call get(memoryId) to retrieve the full record including content.

MemoryRecord

FieldTypeDescription
idstringMemory UUID
orgIdstringYour organization identifier
agentIdstringAgent that owns the memory
userIdstringUser the memory belongs to
levelnumber0 or 1
statusstring"active" or "deprecated"
importancenumberImportance score 0.01.0
confidencenumberConfidence score 0.01.0
sourcestringOrigin of the memory (e.g. "agent")
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last updated timestamp

get()

Fetch a single memory by ID, including its content.
import type { MemoryDetail } from 'thrindex';

const memory: MemoryDetail = await client.get('3f2e1d0c-...');
console.log(memory.content);

Parameters

ParameterTypeRequiredDescription
memoryIdstringyesThe memory UUID

Returns

Promise<MemoryDetail> — all fields of MemoryRecord plus content: string. Throws NotFoundError if the memory does not exist.

delete()

Delete a memory by ID.
await client.delete('3f2e1d0c-...');                    // soft delete (default)
await client.delete('3f2e1d0c-...', { hard: true });    // hard delete (GDPR erasure)

Parameters

ParameterTypeRequiredDefaultDescription
memoryIdstringyesThe memory UUID
options.hardbooleannofalsefalse = soft delete. true = permanent erasure from all stores. Irreversible.

Returns

Promise<void>. Throws NotFoundError if the memory does not exist.

batchAdd()

Add multiple memories sequentially with per-item retry.
import type { BatchAddItem } from 'thrindex';

const ids: string[] = await client.batchAdd(
  [
    { content: 'User timezone is Europe/Berlin.' },
    { content: 'User language is German.', confidence: 0.9 },
    { content: 'User prefers dark mode.', extract: false },
  ],
  {
    agentId: 'support-agent',  // default for all items
    userId: 'user-42',         // default for all items
    extract: true,             // default extraction behaviour
  },
);

BatchAddItem

FieldTypeRequiredDescription
contentstringyesThe memory text
agentIdstringnoOverrides the batch-level agentId
userIdstringnoOverrides the batch-level userId
confidencenumbernoPer-item confidence score
metadataRecord<string, unknown>noPer-item metadata
extractbooleannoOverrides the batch-level extract flag

Returns

Promise<string[]> — memory UUIDs in the same order as the input. Throws on the first unretriable failure.

Error handling

import {
  ThrindexError,
  AuthError,
  NotFoundError,
  RateLimitError,
} from 'thrindex';

try {
  const results = await client.search({ query: '...', agentId: '...', userId: '...' });
} catch (err) {
  if (err instanceof AuthError) {
    // 401 — invalid or revoked API key
    console.error('Check your API key.');
  } else if (err instanceof NotFoundError) {
    // 404 — memory does not exist
    console.error('Memory not found.');
  } else if (err instanceof RateLimitError) {
    // 429 — rate limit exceeded (SDK already retried max_retries times)
    console.error(`Rate limited. Retry after ${err.retryAfter}s.`);
  } else if (err instanceof ThrindexError) {
    // All other errors (400, 500, network failures)
    console.error(`Error ${err.statusCode}: ${err.message}`);
  }
}

Error classes

ClassHTTPProperties
ThrindexErroranystatusCode: number | undefined, message: string
AuthError401Extends ThrindexError
NotFoundError404Extends ThrindexError
RateLimitError429retryAfter: number (seconds)

Retry behaviour

The SDK automatically retries transient failures:
  • 5xx errors (500, 502, 503, 504): up to maxRetries times
  • 429 Rate limited: waits Retry-After seconds, then retries
  • Network / timeout errors: retries with exponential backoff
4xx errors (except 429) are never retried. Backoff: min(500ms × 2^attempt + jitter, 30s).

LLM integrations

Drop-in wrappers for OpenAI, Anthropic, and LangChain are available as named exports from subpaths. See Integrations for full details.
import { ThrindexOpenAI } from 'thrindex/integrations/openai';
import { ThrindexAnthropic } from 'thrindex/integrations/anthropic';
import { ThrindexLangChainRetriever } from 'thrindex/integrations/langchain';
Peer dependencies (openai, @anthropic-ai/sdk, @langchain/core) are optional and only required when you use the corresponding integration.