How to Fix 'state not updating during development' in CrewAI (TypeScript)
When CrewAI says “state not updating during development”, it usually means your agent or workflow is holding onto stale in-memory state while your TypeScript dev server hot-reloads modules. You’ll see it when tasks keep using old values, memory looks frozen, or a crew run behaves differently after code changes than after a full restart.
This is usually not a CrewAI bug. It’s almost always a lifecycle problem: singleton instances, cached module state, or a dev server that reuses objects across reloads.
The Most Common Cause
The #1 cause is creating your Crew, Agent, or shared state at module scope and then expecting edits to be picked up during development.
That pattern works once, then breaks under hot reload because the old instance stays alive in memory. In TypeScript projects using tsx, ts-node-dev, Next.js, or Vite-backed tooling, this is the first thing to check.
Broken vs fixed pattern
| Broken pattern | Fixed pattern |
|---|---|
| Instantiate once at import time | Create fresh instances per run |
| Shared mutable state outside the function | State passed into the run function |
| Hot reload reuses stale objects | Each execution gets a clean object graph |
// ❌ Broken: module-level singleton keeps stale state
import { Agent, Crew, Task } from "@crew-ai/crewai";
let runCount = 0;
const analyst = new Agent({
role: "Analyst",
goal: "Summarize input",
backstory: "You are precise.",
});
const task = new Task({
description: `Run number ${runCount}`,
agent: analyst,
});
const crew = new Crew({
agents: [analyst],
tasks: [task],
});
export async function runCrew() {
runCount++;
return crew.kickoff();
}
// ✅ Fixed: build everything inside the execution path
import { Agent, Crew, Task } from "@crew-ai/crewai";
export async function runCrew(input: string) {
const analyst = new Agent({
role: "Analyst",
goal: "Summarize input",
backstory: "You are precise.",
});
const task = new Task({
description: `Summarize this input: ${input}`,
agent: analyst,
});
const crew = new Crew({
agents: [analyst],
tasks: [task],
});
return crew.kickoff();
}
If you need shared config, share data, not live instances. Keep Agent, Task, and Crew construction inside a factory function so every invocation starts clean.
Other Possible Causes
1) Dev server cache is preserving old compiled output
If you’re using a watcher with aggressive caching, you may be running code that no longer matches your source.
{
"scripts": {
"dev": "tsx watch src/index.ts"
}
}
Try clearing build artifacts and restarting:
rm -rf dist .turbo .next node_modules/.cache
npm run dev
If the issue disappears after a cold start, it’s cache-related.
2) Mutating objects passed into tasks
CrewAI tasks can read stale values if you mutate an object after creating the task instead of passing a fresh payload.
// ❌ Broken
const payload = { customerId: "123", status: "new" };
const task = new Task({
description: `Process customer ${payload.customerId} with status ${payload.status}`,
agent,
});
payload.status = "approved";
// ✅ Fixed
const task = new Task({
description: `Process customer ${customerId} with status ${status}`,
agent,
});
Use primitives or immutable snapshots when building prompts and task descriptions.
3) Reusing one memory store across runs
If you connect CrewAI to external memory or your own in-memory store, it may persist state between runs during development.
// ❌ Broken
const memoryStore = new Map<string, unknown>();
export function getMemory() {
return memoryStore;
}
Reset per request or per test:
// ✅ Fixed
export function createMemoryStore() {
return new Map<string, unknown>();
}
For debugging, log whether the memory object identity changes between runs.
4) Environment variables loaded too early
If .env values are read at import time, hot reload can keep old config around even after you change the file.
// ❌ Broken
const modelName = process.env.CREWAI_MODEL ?? "gpt-4o-mini";
Load config inside startup code:
// ✅ Fixed
export function getConfig() {
return {
modelName: process.env.CREWAI_MODEL ?? "gpt-4o-mini",
};
}
If you changed .env, restart the process. Most watchers do not fully reload environment state.
How to Debug It
- •
Check whether instances are created once or per run
- •Search for
new Crew(,new Agent(, andnew Task(at file scope. - •If they are outside a function, move them inside the execution path.
- •Search for
- •
Log object identity
- •Add temporary logs for each run:
console.log("crew instance", crew); console.log("task description", task.description);- •If the same instance survives across edits, hot reload is reusing stale state.
- •
Restart with caches cleared
- •Stop the watcher.
- •Delete build caches.
- •Start again from a cold boot.
- •If the issue vanishes, your problem is dev-server persistence rather than CrewAI logic.
- •
Reduce to a minimal file
- •Remove memory layers, custom wrappers, and helper factories.
- •Keep only one agent and one task.
- •If the bug disappears in the minimal version, add pieces back until it breaks again.
Prevention
- •Build
Crew,Agent, andTaskobjects inside functions that execute per request or per job. - •Treat prompt inputs as immutable snapshots; don’t mutate shared objects after task creation.
- •Use explicit restart steps in your dev workflow when changing
.env, model config, or memory wiring.
If you’re seeing errors like CrewAIError, stale outputs after edits, or behavior that only fixes itself on restart, assume lifecycle first and framework second. In TypeScript projects, “state not updating during development” is usually just stale module state wearing a CrewAI mask.
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