Brainby arc-labs/docs
Sdk typescriptContext
TypeScript SDK

Context

Reference for recall.context() — assemble a Markdown prompt section, structured per-category breakdown, and optional user summary.

The endpoint behind it is POST /v1/build-context. Where recall.search() returns a ranked list for the application to render, recall.context() returns a fully-assembled prompt section, so the only thing your agent has to do is concatenate it into its system message.

Signature

POST/v1/build-contextAPI keystable
recall.context(input: BuildContextInput, options?: TransportRequestOptions): Promise<BuildContextResult>;

BuildContextInput

ParameterTypeRequired
querystringoptional

Natural-language query or task description. Either query or messages is required (or both). When both are given, query is the canonical signal and messages provides recency.

messagesArray<{ role, content }>optional

Recent conversation turns. When query is omitted, the aggregator derives the effective query from the last two messages — no extra LLM call.

maxTokensnumberoptional

Token budget for the assembled context. Default 4096. The aggregator trims candidates until the rendered Markdown fits — if you set this too low, less-relevant categories are dropped first.

recipe'chat_continuation' | 'task_start' | 'personalization' | 'decision_support' | 'agent_resumption'optional

Named recipe — controls how the token budget is split across categories. See Recipes below. Default is balanced — slightly favouring preferences and recent events.

includeSummarybooleanoptional

When true, prepends a 2–3 sentence LLM-generated narrative about the user. Adds ~1 second of latency on cache miss; cached for 5 minutes per scope. Default false.

BuildContextResult

FieldTypePresence
promptSectionstringalways

Pre-formatted Markdown ready to inject into an LLM system prompt. Has section headers per category and bullet items per memory.

tokenCountnumberalways

Token count of promptSection, computed server-side. Use to budget the rest of your prompt.

sourcesSourceInfo[]always

One entry per memory cited in the prompt. Carries memoryId, category, content, and confidence. Use to render "click to view source" affordances or to inject <source id="…"> markers into the rendered prompt.

categoryCountsCategoryCountsalways

{ activeEntities, preferences, recentEvents, relevantFacts, conventions, constraints } — count of memories included per category.

structuredStructuredContextalways

Machine-readable per-category breakdown. Each category is a StructuredMemory[] with memoryId, content, confidence, relevanceScore, and eventAt?. Use this when your downstream wants the raw memories instead of (or in addition to) the rendered Markdown.

userSummarystring | nullalways

The narrative summary when includeSummary: true. Otherwise null.

traceIdstringalways
latencyMsnumberalways

Recipes

The recipe controls how the token budget is divided across categories. All recipes start from the same retrieval pool — they just emphasise different slices when the budget is tight.

RecipeSkews towardUse when
chat_continuationrecent events, recent messagescontinuing an in-flight chat
task_startfacts, conventionsstarting a new task ("write a report on …")
personalizationactive entities, preferencespersonalising responses for the user
decision_supportfacts, constraints, rerankedthe agent needs to make a recommendation
agent_resumptiona 7-day window of eventsresuming an agent after a long pause

When omitted, the aggregator uses a balanced default that suits chat flows.

Examples

Basic — query only

const ctx = await recall.context({
  query: 'help me plan the trip to Lisbon',
  maxTokens: 2048,
});

system_prompt += '\n\n' + ctx.promptSection;
console.log(`context tokens: ${ctx.tokenCount}, sources: ${ctx.sources.length}`);

Implicit query from recent turns

const ctx = await recall.context({
  messages: [
    { role: 'user', content: 'I think I want to switch to a managed Postgres.' },
    { role: 'assistant', content: 'Got it — any preferences on region?' },
  ],
  recipe: 'decision_support',
});

The aggregator derives the effective query from the last two turns. No extra LLM call is made for the derivation — it's a deterministic concatenation, then the retrieval pipeline runs against that.

Including a user summary

const ctx = await recall.context({
  query: 'design review for the dashboard',
  recipe: 'task_start',
  includeSummary: true,
});

if (ctx.userSummary) {
  system_prompt = `[About the user]\n${ctx.userSummary}\n\n` + ctx.promptSection;
}

includeSummary: true adds ~1 second of latency the first time per scope, then is cached for 5 minutes. Cache invalidates when new memories land for the user.

Programmatic per-category access

const ctx = await recall.context({ query: 'what does the user know about Postgres?' });

console.log('preferences:', ctx.structured.preferences.map((m) => m.content));
console.log('facts:',       ctx.structured.facts.map((m) => m.content));
console.log('constraints:', ctx.structured.constraints.map((m) => m.content));

for (const fact of ctx.structured.facts) {
  if (fact.confidence > 0.8) {
    // surface high-confidence facts in their own UI affordance
  }
}

structured is your escape hatch for applications that want the raw, typed memories without parsing the rendered Markdown.

recall.search() returns a ranked list. Use it when your application is rendering match cards, citation lists, or doing custom post-processing.

recall.context() returns a finished prompt section. Use it when the next step is "feed an LLM" — it does the budgeting, the categorical grouping, and the formatting for you. Calling search() then writing your own Markdown templater is duplicative work.

Token budgeting

maxTokens is a soft cap. The aggregator may slightly over-shoot when an item is mid-trim, but in practice tokenCount is within 5% of the cap.

When the budget is too tight to fit any items, the aggregator returns an empty promptSection and tokenCount: 0. The structured breakdown still contains the top per-category candidates so the application can decide what to render.

For chat applications: a typical good budget is maxTokens: 2000 for an 8 K context window, maxTokens: 4000–8000 for 32 K, and maxTokens: 16000 for 200 K windows.

Caching

Context responses are cached server-side for ~30 seconds per (scope, query, recipe, maxTokens, includeSummary) tuple. Repeating the same call within that window is fast and free. The userSummary is cached for a longer 5 minutes inside the same scope.

Caches invalidate eagerly when recall.remember(), recall.correct(), or recall.forget() runs in the same scope.

Common pitfalls

maxTokens includes only the prompt section — your system prompt, instructions, and the user message are separate. Subtract them from your model's context window before picking a value.

structured and promptSection cover the same memories — do not splice both into the prompt or the LLM will see duplicates. Pick one.

messages is for implicit query derivation only. The aggregator does not run extraction on these messages — they're hints, not writes. To persist them, call recall.remember({ messages }) separately.

Was this page helpful?

On this page