Memory for agents. It forgets the way people do.

Before every model call, your agent hands over what is new and gets back the request to submit. Old episodes fade with time, their facts stay, and recall brings them back when the conversation turns to them.

Each line loses weight by 1/√age. What keeps being used stays heavy; what fades leaves its facts behind.

An example conversation, oldest message first. Older lines are set in a lighter weight, by one over the square root of their age, except an early line giving the install date, which stays at full weight because the conversation keeps coming back to it.

Around every model call
const request = await memory.chat.decorate(memoryId, newMessages, { model, tools });
const reply = await openai.chat.completions.create(request);
memory.chat.report(memoryId, reply);
npm i @threadlessai/sdkpip install threadlessai

Watch a conversation get decorated.

Turn 41 of a long conversation. The agent sends one new message; the request that comes back has the history in proportion, two facts recalled from weeks ago, and an ask for the facts of what is leaving.

your agentscripted example
await memory.chat.decorate(memoryId, [lastReply, { role: 'user', content: 'Did legal come back…' }], { model, tools: [...tools, memory.chat.noteTool] })

    Highlighted rows are what we add. Your messages come back as you sent them. The model’s reply to this request carries the note, and turns 12–15 leave the view on the next call.

    Three steps around the call you already make.

    1. Decorate before

      Send what is new since the last call. Get back the full request: your instructions, the facts block, the history still in view, recall, and the note ask when history is leaving.

    2. Submit it yourself the call

      Send the request to OpenAI with your own key, from your own process. Chat Completions or Responses, any model, your tools. It never passes through us.

    3. Report after

      Hand over the reply. It returns at once; facts are scored, what left the view is indexed and recall for the next message is prepared in the background.

    About ten lines. Your loop stays yours.

    Wrap the model call, add the note tool to your tools, and answer note calls with NOTE_RESULT. The highlighted lines are the ones you add. When we cannot be reached, the SDK builds the request from a local tail of recent turns and the call goes ahead.

    TypeScript
    import OpenAI from 'openai';
    import { Threadless } from '@threadlessai/sdk';
    
    const openai = new OpenAI();
    const memory = new Threadless(); // reads THREADLESS_API_KEY
    
    const tools = [...yourTools, memory.chat.noteTool];
    const request = await memory.chat.decorate(memoryId, newMessages, { model: 'gpt-5', tools });
    const reply = await openai.chat.completions.create(
      request as unknown as OpenAI.ChatCompletionCreateParamsNonStreaming,
    );
    memory.chat.report(memoryId, reply);

    Forgetting by time and use. Facts kept. Recall on cue.

    Truncation loses the start, summaries drift, and searching everything makes nothing stand out. People forget well instead; so does this.

    Episodes
    The conversation is cut into episodes, one per concept, never splitting a tool call from its output.
    Forgetting by time
    Each episode fades with the square root of real time and rises every time it matters again. The least active leave the view first.
    Facts kept
    Before an episode leaves, your model writes its facts and milestones with the note tool. They stay in view after the turns are gone.
    Recall
    When the conversation touches something old, the facts and passages about it come back, dated, before the model is called.

    After a day of silence the next turn sleeps first: the view fades before the reply, so the agent comes back with the gap accounted for. The mechanism in full

    Benchmark results are coming.

    We are running the public long-memory benchmarks against the hosted service. We will publish the scores with the method and the runs behind them. Until then we publish no numbers. Results will appear in the changelog.

    BenchmarkWhat it measuresScore
    LongMemEvalLong-term memory in chat assistantspending
    LoCoMoVery long conversations across sessionspending

    Two meters. Pricing is being finalised.

    You pay OpenAI for your model calls directly. We meter the memory: the turns it serves and the history it holds. See what each meter covers

    MeterUnitWhat countsPrice
    User turnsper user turnA decorate call that carries a new user message. Calls inside a tool loop are free.to be announced
    Stored memoryper GB-monthWhat each memory holds, measured daily and averaged over the month.to be announced
    Free tiermonthlyA free allowance of turns and memories, no card. Enterprise terms on request.free

    Give your agent a memory that keeps what matters.