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

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

When AutoGen state stops updating during scaling, you usually have a mismatch between where the state lives and how your workers are running. In TypeScript, this shows up most often when you move from a single-process agent loop to multiple instances, containers, or parallel tool calls.

The symptom is simple: one agent updates state, but another instance keeps reading stale data. In practice, you’ll see errors like state not found, Cannot read properties of undefined, or your own logs showing the AssistantAgent and UserProxyAgent are operating on different in-memory objects.

The Most Common Cause

The #1 cause is keeping mutable state in memory inside a class instance while scaling horizontally.

AutoGen agents like AssistantAgent, UserProxyAgent, or your own wrapper class are often created per request or per worker. If you store conversation state, tool state, or workflow progress in a local variable, each process gets its own copy. That works locally and fails as soon as you add concurrency or more than one replica.

Broken pattern vs fixed pattern

BrokenFixed
State stored in process memoryState stored in shared persistence
Each worker mutates its own copyAll workers read/write the same record
Works on one nodeBreaks when scaled
// BROKEN: state lives in memory inside the worker
import { AssistantAgent } from "@autogen/core";

type WorkflowState = {
  step: number;
  approved: boolean;
};

class LoanWorkflow {
  private state: WorkflowState = { step: 0, approved: false };

  constructor(private agent: AssistantAgent) {}

  async run() {
    this.state.step += 1;

    const result = await this.agent.run({
      messages: [{ role: "user", content: "Check loan eligibility" }],
    });

    // Another worker will never see this update
    this.state.approved = result.messages.length > 0;
    return this.state;
  }
}
// FIXED: persist state outside the process
import { AssistantAgent } from "@autogen/core";

type WorkflowState = {
  step: number;
  approved: boolean;
};

interface StateStore {
  get(id: string): Promise<WorkflowState | null>;
  set(id: string, value: WorkflowState): Promise<void>;
}

class LoanWorkflow {
  constructor(
    private agent: AssistantAgent,
    private store: StateStore,
    private workflowId: string
  ) {}

  async run() {
    const current =
      (await this.store.get(this.workflowId)) ?? { step: 0, approved: false };

    const nextState = { ...current, step: current.step + 1 };

    const result = await this.agent.run({
      messages: [{ role: "user", content: "Check loan eligibility" }],
    });

    nextState.approved = result.messages.length > 0;

    await this.store.set(this.workflowId, nextState);
    return nextState;
  }
}

If you are using Redis, Postgres, DynamoDB, or even a durable file-backed store for dev, the key point is the same: do not trust in-memory object state across scaled workers.

Other Possible Causes

1. You recreate the agent on every request

If you instantiate AssistantAgent inside the handler, any attached runtime context may reset every time.

// BAD
export async function POST(req: Request) {
  const agent = new AssistantAgent({ name: "support" });
  return agent.run({ messages: await req.json() });
}
// GOOD
const agent = new AssistantAgent({ name: "support" });

export async function POST(req: Request) {
  return agent.run({ messages: await req.json() });
}

If the agent needs request-specific context, pass that context explicitly instead of rebuilding the whole object graph.

2. You are relying on non-atomic updates

Two workers can read the same old value and overwrite each other. That looks like “state not updating” when it is really a race condition.

// BAD
const current = await store.get(id);
current.step += 1;
await store.set(id, current);

Use compare-and-swap semantics or versioned writes.

// BETTER
await store.update(id, (current) => ({
  ...current,
  step: current.step + 1,
}));

If your storage does not support atomic updates, add a version field and reject stale writes.

3. Your tool handler mutates a copied payload

AutoGen message/tool payloads are often cloned or serialized. If you mutate an object after passing it into an agent call, those changes may never be observed by later steps.

// BAD
const context = { status: "pending" };
await agent.run({ messages });
context.status = "approved"; // too late for downstream logic

Pass updated context into the next turn explicitly:

// GOOD
let context = { status: "pending" };

const first = await agent.run({ messages });
context = { ...context, status: "approved" };

await agent.run({
  messages,
});

4. Your deployment has sticky-session assumptions

If one request lands on worker A and the next lands on worker B, any local cache will look broken. This happens behind load balancers, serverless platforms, and Kubernetes replicas.

# Problematic if your app expects local memory to persist:
replicas: 3

Fix by moving session/state data to shared storage and using a stable workflow/session key for every turn.

How to Debug It

  1. Log the workflow ID and process identity

    • Print workflowId, process.pid, pod name, or container ID.
    • If updates happen on different workers with no shared store, that’s your bug.
  2. Trace every read/write to state

    • Log before and after each get() and set().
    • Look for stale reads immediately after writes from another instance.
  3. Check whether your state survives a restart

    • Restart one pod or kill the process.
    • If state disappears, it was never durable.
  4. Inspect where AutoGen gets instantiated

    • Search for new AssistantAgent(...), new UserProxyAgent(...), or custom wrappers.
    • If they’re created inside request handlers or tool callbacks without shared persistence behind them, scaling will break.

Prevention

  • Keep conversation/workflow state in Redis, Postgres, DynamoDB, or another shared store.
  • Use atomic updates or versioned writes for any mutable workflow state.
  • Treat AutoGen agents as stateless execution units unless you have verified durable backing storage.
  • Add logs for workflowId, worker identity, and state version before shipping to production.

If you want one rule to remember it’s this:

AutoGen can orchestrate agents; it will not magically synchronize your application state across replicas.


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