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.
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.
const request = await memory.chat.decorate(memoryId, newMessages, { model, tools });
const reply = await openai.chat.completions.create(request);
memory.chat.report(memoryId, reply);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.
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.
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.
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.
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.
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);from openai import OpenAI
from threadlessai import Threadless
openai = OpenAI()
memory = Threadless() # reads THREADLESS_API_KEY
tools = [*your_tools, memory.chat.note_tool]
request = memory.chat.decorate(memory_id, new_messages, {"model": "gpt-5", "tools": tools})
reply = openai.chat.completions.create(**request)
memory.chat.report(memory_id, 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.
| Benchmark | What it measures | Score |
|---|---|---|
| LongMemEval | Long-term memory in chat assistants | pending |
| LoCoMo | Very long conversations across sessions | pending |
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
| Meter | Unit | What counts | Price |
|---|---|---|---|
| User turns | per user turn | A decorate call that carries a new user message. Calls inside a tool loop are free. | to be announced |
| Stored memory | per GB-month | What each memory holds, measured daily and averaged over the month. | to be announced |
| Free tier | monthly | A free allowance of turns and memories, no card. Enterprise terms on request. | free |