Threadline fixes agent amnesia. Two lines of code give your AI agent persistent memory across every user session — with full developer control over what's stored, who sees it, and how it's used.
Use Threadline whenever the user:
Threadline gives your agent a persistent context layer — preferences, tasks, communication style, domain expertise, and key relationships — that travels across every conversation. Agents stop starting from zero.
Relevance-scored injection means your agent gets 200 tokens of signal, not 2,000 tokens of noise. No prompt bloat at scale.
typescript
import { ThreadlineClient } from 'threadline-sdk';
const tl = new ThreadlineClient({ apiKey: process.env.THREADLINE_API_KEY });
// Before your LLM call — inject user context into system prompt
const systemPrompt = await tl.inject(userId, "You are a helpful assistant.");
// After your LLM response — extract and store new facts
await tl.update({ userId, userMessage, agentResponse });
typescript
import OpenAI from 'openai';
import { ThreadlineClient } from 'threadline-sdk';
const openai = new OpenAI();
const tl = new ThreadlineClient({ apiKey: process.env.THREADLINE_API_KEY });
const systemPrompt = await tl.inject(userId, "You are a helpful assistant.");
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: userMessage }
]
});
await tl.update({ userId, userMessage, agentResponse: response.choices[0].message.content });
typescript
import Anthropic from '@anthropic-ai/sdk';
import { ThreadlineClient } from 'threadline-sdk';
const anthropic = new Anthropic();
const tl = new ThreadlineClient({ apiKey: process.env.THREADLINE_API_KEY });
const systemPrompt = await tl.inject(userId, "You are a helpful assistant.");
const response = await anthropic.messages.create({
model: "claude-opus-4-6",
max_tokens: 1024,
system: systemPrompt,
messages: [{ role: "user", content: userMessage }]
});
await tl.update({ userId, userMessage, agentResponse: response.content[0].text });
typescript
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { ThreadlineClient } from 'threadline-sdk';
const tl = new ThreadlineClient({ apiKey: process.env.THREADLINE_API_KEY });
const systemPrompt = await tl.inject(userId, "You are a helpful assistant.");
const result = await streamText({
model: openai('gpt-4o'),
system: systemPrompt,
messages,
onFinish: async ({ text }) => {
await tl.update({ userId, userMessage, agentResponse: text });
}
});
typescript
import { ChatOpenAI } from '@langchain/openai';
import { SystemMessage, HumanMessage } from '@langchain/core/messages';
import { ThreadlineClient } from 'threadline-sdk';
const tl = new ThreadlineClient({ apiKey: process.env.THREADLINE_API_KEY });
const llm = new ChatOpenAI({ model: "gpt-4o" });
const systemPrompt = await tl.inject(userId, "You are a helpful assistant.");
const response = await llm.invoke([
new SystemMessage(systemPrompt),
new HumanMessage(userMessage)
]);
await tl.update({ userId, userMessage, agentResponse: response.content });
Threadline extracts and stores context across 7 scopes:
ScopeWhat it capturescommunication_styleTone, verbosity, format preferencesongoing_tasksActive projects, deadlines, blockerskey_relationshipsTeam members, clients, collaboratorsdomain_expertiseTech stack, industry knowledge, skillspreferencesTools, workflows, working styleemotional_stateStress signals, motivation, sentimentgeneralEverything else worth remembering
Agents only see the scopes they're explicitly granted. A coding assistant
sees domain_expertise and ongoing_tasks. A writing assistant sees
communication_style and preferences. No agent sees everything by default.
typescript
await tl.grant({
agentId: "coding-assistant",
userId: userId,
scopes: ["domain_expertise", "ongoing_tasks"]
});
inject() before the LLM call, never afterupdate() after receiving the agent responseuserId — this is how context is scoped per userbash
# Inject
POST https://api.threadline.to/api/inject
Authorization: Bearer YOUR_API_KEY
{ "userId": "user_123", "basePrompt": "You are a helpful assistant." }
# Update
POST https://api.threadline.to/api/update
Authorization: Bearer YOUR_API_KEY
{ "userId": "user_123", "userMessage": "...", "agentResponse": "..." }
IssueFixinject() returns base prompt unchangedCheck API key is set correctlyContext not persistingConfirm update() is being called after every responseSlow injectionRedis-cached — first call ~200ms, subsequent calls <50msWrong user contextEnsure userId is stable and unique per user