Quickstart

Get Threadline running in your project in under 5 minutes.

Installation

Install the SDK from npm, or skip it entirely and call the REST API.

TypeScript

npm install threadline-sdk

cURL

# no install required
curl https://app.threadline.to/api/health

Authentication

Initialize Threadline with your API key from the dashboard. Over HTTP, pass it as a bearer token.

TypeScript

import { Threadline } from "threadline-sdk"

const tl = new Threadline({
  apiKey: process.env.THREADLINE_API_KEY!
})

cURL

export THREADLINE_API_KEY=tl_live_...

curl https://app.threadline.to/api/context/inject \
  -H "Authorization: Bearer $THREADLINE_API_KEY" \
  -H "Content-Type: application/json"

Context Objects

Context objects are the unit of memory Threadline stores per user — facts, preferences, and conversational history that persist across sessions.

Scopes & Grants

Scopes control which agents can read or write to a user's context. Grants are scoped permissions you issue to specific agents or tools. See Governance for the full model.

Your first run

On a brand-new user the store is empty, so start with update() — write one real exchange, then call inject() and watch the context come back.

TypeScript

// 1. Write first — one real exchange
await tl.update({
  userId: "user_42",
  userMessage: "I just moved to Lisbon and I prefer short answers.",
  agentResponse: "Welcome to Lisbon! I'll keep things brief."
})

// 2. Now inject — the prompt comes back enriched
const { injectedPrompt } = await tl.inject("user_42", "You are a helpful assistant.")
console.log(injectedPrompt)

cURL

# 1. Write first
curl -X POST https://app.threadline.to/api/context/update \
  -H "Authorization: Bearer $THREADLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user_42",
    "userMessage": "I just moved to Lisbon and I prefer short answers.",
    "agentResponse": "Welcome to Lisbon! I will keep things brief."
  }'

# 2. Then inject
curl -X POST https://app.threadline.to/api/context/inject \
  -H "Authorization: Bearer $THREADLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user_42",
    "basePrompt": "You are a helpful assistant."
  }'

Expected, not an error. If you call inject() before any update(), you get your basePrompt back unchanged with reason: "empty" and a notice telling you to call update() first. There is simply nothing stored for that user yet.

{
  "injectedPrompt": "You are a helpful assistant.",
  "reason": "empty",
  "notice": "No context stored for this user yet. Call update() first."
}

Every reason value is documented on Response reasons.

The loop

Once a user has context, the steady-state loop is: inject before the LLM call, update after it.

TypeScript

const { injectedPrompt } = await tl.inject(userId, basePrompt)

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "system", content: injectedPrompt }],
})

await tl.update({ userId, userMessage, agentResponse })

cURL

# before the LLM call
curl -X POST https://app.threadline.to/api/context/inject \
  -H "Authorization: Bearer $THREADLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "user_42", "basePrompt": "You are a helpful assistant." }'

# after the LLM call
curl -X POST https://app.threadline.to/api/context/update \
  -H "Authorization: Bearer $THREADLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user_42",
    "userMessage": "...",
    "agentResponse": "..."
  }'

That's it. Your agent now has persistent context for every user — stored until the user deletes it or the grant is revoked. For the full API reference and SDK options, browse the sidebar.