How to Fix 'state not updating when scaling' in CrewAI (TypeScript)

By Cyprian AaronsUpdated 2026-04-21
state-not-updating-when-scalingcrewaitypescript

If you’re seeing state not updating when scaling in a CrewAI TypeScript project, the core issue is usually simple: your agent or task state is being mutated in one place, but the scaled workers are reading a different instance. This shows up when you move from a single-run flow to parallel execution, or when you scale tasks across multiple agents and expect shared state to “just work”.

In practice, this usually means one of three things: you’re mutating a local object instead of the canonical store, you’re cloning state before dispatch, or your task context is not being passed through the Crew/Task boundary correctly.

The Most Common Cause

The #1 cause is mutating an object after it has already been handed off to CrewAI. In TypeScript, this often happens when you pass a plain object into Task or Crew, then update that object later and expect workers to see the change.

CrewAI won’t magically track your local variable references across scaled execution. If the worker got a snapshot, it stays a snapshot.

Broken vs fixed pattern

Broken patternFixed pattern
Mutate local state after task creationBuild immutable state and pass it explicitly
Assume shared references survive scalingRecreate task input from current source of truth
Rely on side effects inside callbacksReturn updated state and persist it centrally
// BROKEN
import { Agent, Task, Crew } from "crewai";

type AppState = {
  customerId: string;
  riskScore: number;
};

const state: AppState = {
  customerId: "cust_123",
  riskScore: 42,
};

const analyst = new Agent({
  name: "RiskAnalyst",
  role: "Underwriter",
  goal: "Assess customer risk",
});

const task = new Task({
  description: `Review customer ${state.customerId} with risk score ${state.riskScore}`,
  agent: analyst,
});

// State changes AFTER task creation
state.riskScore = 87;

const crew = new Crew({
  agents: [analyst],
  tasks: [task],
});

await crew.kickoff();
// FIXED
import { Agent, Task, Crew } from "crewai";

type AppState = {
  customerId: string;
  riskScore: number;
};

function buildTask(state: AppState) {
  return new Task({
    description: `Review customer ${state.customerId} with risk score ${state.riskScore}`,
    agent: new Agent({
      name: "RiskAnalyst",
      role: "Underwriter",
      goal: "Assess customer risk",
    }),
  });
}

let state: AppState = {
  customerId: "cust_123",
  riskScore: 42,
};

state = { ...state, riskScore: 87 };

const crew = new Crew({
  agents: [],
  tasks: [buildTask(state)],
});

await crew.kickoff();

The important part is this:

  • don’t mutate objects that were already captured by a task
  • rebuild the task from current data
  • treat input state as immutable once dispatched

Other Possible Causes

1. You are scaling with cloned context objects

If you do something like structuredClone(), spread syntax, or JSON serialization before dispatching work, each worker gets its own copy. That means updates in one branch won’t appear in another.

const baseState = { policyId: "pol_001", step: "review" };
const workerState = structuredClone(baseState);

workerState.step = "approval";

// baseState.step is still "review"

If you need shared updates, store them in a central persistence layer like Redis, Postgres, or your app database.

2. You are using non-deterministic mutable globals

This bites people when they keep workflow data in module-level variables.

let currentCaseId = "";

export function setCase(id: string) {
  currentCaseId = id;
}

In scaled execution, one worker may overwrite another worker’s value. Use request-scoped context instead.

export function buildContext(caseId: string) {
  return { caseId };
}

3. Your task output schema does not match what downstream code expects

Sometimes the error looks like state isn’t updating, but the real problem is that your parser drops fields because the model output doesn’t match your expected shape.

type Result = {
  status: string;
  nextStep?: string;
};

If the agent returns:

{ "status": "approved", "next_step": "notify_customer" }

then nextStep stays undefined. Normalize field names with an explicit parser or schema validator.

4. You are hitting an async race condition in parallel tasks

When multiple tasks update the same record without locking, later writes can overwrite earlier ones.

await Promise.all([
  saveCase({ id: "c1", status: "reviewing" }),
  saveCase({ id: "c1", status: "approved" }),
]);

The final value depends on timing. Use optimistic locking, version checks, or queue writes through a single updater.

How to Debug It

  1. Log the exact state before task creation

    • Print the object right before new Task(...).
    • If the value is already wrong there, the bug is upstream.
  2. Log inside each worker boundary

    • Add debug output at agent/task entry points.
    • Compare what was passed in versus what each scaled worker sees.
  3. Check for cloning or serialization

    • Search for JSON.parse(JSON.stringify(...)), structuredClone, message queue payloads, or API boundaries.
    • If present, assume you have copies, not shared references.
  4. Verify output mapping

    • Inspect raw agent output before parsing.
    • If your code expects nextStep but receives next_step, fix the schema mismatch first.

A good rule here:

  • if logs differ before and after dispatch, it’s a propagation problem
  • if logs match but persisted data is wrong, it’s a write/race problem
  • if logs show missing fields only after parsing, it’s a schema problem

Prevention

  • Treat all CrewAI inputs as immutable once a Task is created.
  • Pass context explicitly into every agent/task instead of relying on module globals.
  • Persist shared workflow state in an external store if more than one worker can touch it.

If you want stable scaling behavior in CrewAI TypeScript projects, design for copy-on-dispatch and explicit state transitions. That keeps your workflow predictable when you move from single-agent execution to parallel crews.


Keep learning

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

Related Guides