LlamaIndex Hands You the Context Object. Your Cron Job Still Wakes Up Blank.
LlamaIndex Hands You the Context Object. Your Cron Job Still Wakes Up Blank. Most agent frameworks dodge the memory question. Their docs talk about "sessions" and "threads" and let you discover the amnesia at 3 a.m. when the nightly job repeats a mistake you watched it make yesterday. LlamaIndex does the opposite. Its documentation opens the state chapter with a sentence most vendors would bury: "By default, the AgentWorkflow is stateless between runs. This means that the agent will not have an
LlamaIndex Hands You the Context Object. Your Cron Job Still Wakes Up Blank.
Most agent frameworks dodge the memory question. Their docs talk about "sessions" and "threads" and let you discover the amnesia at 3 a.m. when the nightly job repeats a mistake you watched it make yesterday. LlamaIndex does the opposite. Its documentation opens the state chapter with a sentence most vendors would bury: "By default, the AgentWorkflow is stateless between runs. This means that the agent will not have any memory of previous runs."
That honesty is refreshing. It is also only half the story, because LlamaIndex then hands you the best-designed escape hatch in the framework world — a Context object that is serializable by design — and leaves the entire job of operating it to you. If you run LlamaIndex agents on a schedule, here is what that object does, what it cannot do, and why your 6 a.m. run still wakes up blank.
What the Context object actually holds
In LlamaIndex, a Workflow is an event-driven system: steps emit events, the Context routes them, and state flows between steps through that Context. For agents, the pattern is explicit. You create a Context from your agent or workflow, then pass it into every run:
from llama_index.core.workflow import Context
ctx = Context(workflow)
response = await workflow.run(user_msg="Check the staging deploy", ctx=ctx)
Pass the same ctx into the next run and the agent keeps going where it left off. Inside that object lives the working state: the chat history, the in-flight events, and any values your steps stored with ctx.set and read back with ctx.get. It is real memory, in the precise sense that matters during a run — the agent does not re-ask, re-derive, or re-fetch what the Context already holds.
Notice the shape of it, though. This is working memory for one workflow, inside one process. It remembers the conversation so the current task can proceed. It is not a record of what the agent learned across a week of runs, and it was never designed to be shared with anything outside that workflow.
Serializable is not the same as saved
Here is where LlamaIndex pulls ahead of most frameworks. The docs state it plainly: "The context is serializable, so it can be saved to a database, file, etc. and loaded back in later." The framework ships two serializers for the job — JsonSerializer for plain JSON state and JsonPickleSerializer for contexts holding objects JSON cannot express — and the round trip is two calls:
ctx_dict = ctx.to_dict(serializer=JsonSerializer())
# ... later, possibly on another machine ...
restored_ctx = Context.from_dict(workflow, ctx_dict, serializer=JsonSerializer())
Read that sentence from the docs the way an operator should: "can be saved to a database, file, etc." Somebody has to write the code that saves it. Somebody has to choose the database, handle the write at the end of the run, handle the load at the start of the next one, deal with the corrupted blob, and decide what happens when the schema of your stored state drifts three refactors later. LlamaIndex built the door. You are the one who has to walk through it every single run, forever.
This is the honest-engineering version of the memory problem. Compare it with frameworks that offer no serialization at all and the LlamaIndex design is clearly better. But "better than nothing" is not the same as "solved." A serializable context is a capability. A memory system is a capability plus the operations around it: writes that happen reliably at the end of every run, reads at the start, pruning when state grows stale, and conflict handling when two runs disagree.
The cron problem: a fresh process every tick
Now put that workflow on a schedule. Your orchestrator — cron, a queue worker, a scheduled container — starts a fresh process for each run. A fresh process means a fresh Context, unless the first thing your job does is load yesterday's serialized blob and the last thing it does is save today's.
In practice, scheduled LlamaIndex operators hit three failure modes:
The save never got written. The happy path works in the notebook: you keep ctx alive in memory across runs and everything remembers. Then the job moves to production, where each tick is a new process, and nobody added the serialize-on-exit step. The agent wakes up blank every morning and nobody notices for a week because each individual run looks fine in isolation.
The state grows without a gardener. A Context that survives across runs accumulates: every chat message, every stored value, every intermediate artifact. Nothing in the framework decides what is worth keeping. Your nightly research sweep starts each run slower and more confused than the last, carrying the full transcript of every dead end it ever explored, because pruning was never anyone's job.
The memory is trapped in one workflow. Even a perfectly persisted Context belongs to one workflow on one machine. The coding agent on your laptop cannot read it. The n8n flow that consumes the workflow's output cannot see how the output was produced. The second LlamaIndex workflow you spin up for a different client starts from zero. You solved amnesia inside one process and left it standing everywhere else.
Give the run a memory outside the process
The fix is to stop treating persistence as a side quest of each workflow and give your agents a memory layer that lives outside any single process, framework, or machine. Vilix AI is cloud-hosted, so there is zero infrastructure to provision or maintain — no database to choose, no serializer to babysit, no save-on-exit hook to remember. It connects over MCP, which means the same memory follows your agents across LlamaIndex, your coding tools, and your other scheduled runners: one memory, every tool, every device.
And it keeps full conversation history, not extracted facts. That distinction matters for scheduled work. A serialized Context stores state; a memory layer stores the story — the full transcript of the run where the agent learned that the staging deploy check has to happen before the migration, including the failed attempt that taught it. When the next run starts, the agent does not just load a state blob. It recalls why.
Your data stays yours: export everything or delete it at any time, in a portable format. The free plan never expires, and the 7-day Pro trial does not ask for a credit card.
LlamaIndex deserves credit for the clearest memory story in the framework world: stateless by default, stated upfront, with a serializable Context for operators willing to do the plumbing. If you build on it, do the plumbing — serialize the Context, store it somewhere durable, restore it every tick, and prune it on a schedule. And when you are tired of being the memory operator for every workflow you own, give the job to a layer whose whole purpose is remembering. Keep LlamaIndex's Context for the run. Give the 6 a.m. run a memory of what the 6 a.m. run did yesterday.