LlamaIndex Tutorial (TypeScript): persisting agent state for intermediate developers
This tutorial shows you how to persist LlamaIndex agent state in TypeScript so an agent can resume with the same conversation, tools, and memory after a process restart. You need this when you cannot afford to lose context between requests, deploys, or worker crashes.
What You'll Need
- •Node.js 18+ and npm
- •A TypeScript project initialized with
tsconfig.json - •An OpenAI API key
- •
llamaindexinstalled - •A writable local directory for persisted state
- •Basic familiarity with async/await and LlamaIndex agents
Install the package first:
npm install llamaindex
Set your API key:
export OPENAI_API_KEY="your-key-here"
Step-by-Step
- •Create a small project setup that can load environment variables and talk to OpenAI through LlamaIndex. The important part here is that the same runtime will later create, save, and restore the agent.
import "dotenv/config";
import {
FunctionTool,
OpenAIAgent,
OpenAI,
storageContextFromDefaults,
} from "llamaindex";
const llm = new OpenAI({ model: "gpt-4o-mini" });
const timeTool = FunctionTool.from(
async () => new Date().toISOString(),
{
name: "current_time",
description: "Returns the current ISO timestamp",
}
);
- •Build an agent with memory-backed chat state. This is what gives you continuity across turns; without persistence, every restart begins from zero.
const agent = new OpenAIAgent({
tools: [timeTool],
llm,
systemPrompt: "You are a helpful assistant that can report the current time.",
});
const firstReply = await agent.chat({
message: "What time is it right now?",
});
console.log(firstReply.response);
- •Persist the agent state to disk using a storage context. In TypeScript, the clean pattern is to write the agent’s storage artifacts into a directory you control, then reload them later in another process.
const storageContext = await storageContextFromDefaults({
persistDir: "./agent-state",
});
await agent.persist(storageContext);
console.log("Agent state persisted to ./agent-state");
- •Restore the same agent from disk in a fresh runtime. This is the step people usually miss: you do not recreate “memory” manually; you reload the persisted store and rehydrate the agent from it.
import { loadIndexFromStorage } from "llamaindex";
const restoredStorage = await storageContextFromDefaults({
persistDir: "./agent-state",
});
const restoredAgent = await OpenAIAgent.fromPersisted({
storageContext: restoredStorage,
llm,
});
const secondReply = await restoredAgent.chat({
message: "What did I ask you earlier?",
});
console.log(secondReply.response);
- •Wrap persistence around a real request flow. In production, you usually persist after each successful turn so a crash only loses at most one message.
async function runConversation() {
const storage = await storageContextFromDefaults({
persistDir: "./agent-state",
});
const activeAgent = await OpenAIAgent.fromPersisted({
storageContext: storage,
llm,
});
const reply = await activeAgent.chat({
message: "Summarize our last exchange in one sentence.",
});
console.log(reply.response);
await activeAgent.persist(storage);
}
runConversation();
- •If you need multiple users, isolate persistence per user or session ID. Do not share one persisted directory across all users unless you want their histories mixed together.
async function getAgentForSession(sessionId: string) {
const storage = await storageContextFromDefaults({
persistDir: `./agent-state/${sessionId}`,
});
return OpenAIAgent.fromPersisted({
storageContext: storage,
llm,
});
}
Testing It
Run your script once, ask the agent something specific, and confirm that ./agent-state gets created on disk. Then stop the process completely, rerun it, and ask a follow-up question that depends on previous context.
If restoration works, the second response should reflect prior conversation state instead of acting like a new session. If it does not, check three things first: your persistDir, your OPENAI_API_KEY, and whether you are actually calling persist() after the turn completes.
For extra confidence, delete your Node process between turns rather than testing in one long-running session. That catches bugs where memory only appears to work because it was still in RAM.
Next Steps
- •Add per-user session routing with Redis or Postgres instead of local disk
- •Persist tool outputs separately if your workflow needs auditability
- •Combine this with chat history trimming so long-running agents stay within token limits
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit