How to Fix 'callback not firing during development' in CrewAI (TypeScript)

By Cyprian AaronsUpdated 2026-04-21
callback-not-firing-during-developmentcrewaitypescript

If you’re seeing callback not firing during development in CrewAI TypeScript, it usually means your task completed but the callback never executed in the path you expected. In practice, this shows up during local runs when the agent finishes, but your handler never logs, persists, or returns anything.

Most of the time, this is not a CrewAI bug. It’s a lifecycle issue: the callback is either attached to the wrong object, not awaited, or gets lost because the process exits before async work completes.

The Most Common Cause

The #1 cause is wiring the callback incorrectly on a Task or Agent, then expecting it to behave like a normal event listener. In CrewAI TypeScript, callbacks need to be attached where the framework actually invokes them, and async callbacks must be awaited all the way through.

Here’s the broken pattern:

BrokenFixed
Callback attached too late / not awaitedCallback passed into the right execution path and awaited
// broken.ts
import { Agent, Task, Crew } from "crewai";

const agent = new Agent({
  role: "Researcher",
  goal: "Summarize customer complaints",
});

const task = new Task({
  description: "Summarize support tickets",
  agent,
});

task.callback = async (result) => {
  console.log("Callback fired:", result);
  await saveToDb(result);
};

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

crew.kickoff(); // not awaited
// fixed.ts
import { Agent, Task, Crew } from "crewai";

const agent = new Agent({
  role: "Researcher",
  goal: "Summarize customer complaints",
});

const task = new Task({
  description: "Summarize support tickets",
  agent,
  callback: async (result) => {
    console.log("Callback fired:", result);
    await saveToDb(result);
  },
});

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

await crew.kickoff(); // wait for task lifecycle to complete

The important part is that crew.kickoff() must stay alive long enough for the callback chain to complete. If you start execution and immediately let Node exit, your callback can look “missing” even though it was scheduled.

If your callback does I/O like DB writes, file writes, or HTTP calls, make sure those promises are awaited inside the callback too.

Other Possible Causes

1. You’re using an inline callback with a stale closure

If your callback captures variables that are mutated later, it may look like it didn’t fire because it wrote bad data or hit an exception.

let runId = "";

const task = new Task({
  description: "Process invoice",
  agent,
  callback: async (result) => {
    console.log("runId:", runId); // empty if set later
    await audit(runId, result);
  },
});

runId = crypto.randomUUID();

Fix by setting state before creating the task:

const runId = crypto.randomUUID();

const task = new Task({
  description: "Process invoice",
  agent,
  callback: async (result) => {
    await audit(runId, result);
  },
});

2. The callback throws before logging anything useful

A thrown error inside callback can make it seem like it never ran. In dev mode, you may only see a generic failure around Crew.kickoff().

callback: async (result) => {
  const parsed = JSON.parse(result.output); // throws if output is not JSON
  await persist(parsed);
}

Wrap it explicitly:

callback: async (result) => {
  try {
    const parsed = JSON.parse(result.output);
    await persist(parsed);
    console.log("callback completed");
  } catch (err) {
    console.error("callback failed", err);
    throw err;
  }
}

3. You attached the callback to Agent when your version expects it on Task

CrewAI TypeScript APIs have changed across versions. If you’re following Python examples or older TS docs, you may be putting hooks on the wrong class.

// wrong for many TS setups
const agent = new Agent({
  role: "Analyst",
  goal: "Review claims",
  callback: async () => {
    console.log("never called");
  },
});

Prefer attaching at task execution time:

const task = new Task({
  description: "Review claims",
  agent,
  callback: async (result) => {
    console.log("task callback called", result);
  },
});

4. Your dev server hot reload is killing the process mid-run

With tsx, nodemon, or Next.js API routes, file changes can restart Node before your callback finishes.

{
  "scripts": {
    "dev": "nodemon src/index.ts"
  }
}

If a long-running task is involved, run it outside hot reload first:

{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "start": "node dist/index.js"
  }
}

And test with a plain one-shot process:

node dist/index.js

How to Debug It

  1. Confirm whether kickoff() is awaited

    • Search for crew.kickoff() and make sure every call site uses await.
    • If you’re in an Express route or serverless function, return only after the promise resolves.
  2. Add logs at three points

    • Before kickoff.
    • Inside the callback.
    • After kickoff.
    console.log("before kickoff");
    const result = await crew.kickoff();
    console.log("after kickoff", result);
    
    // inside callback:
    console.log("inside callback");
    
  3. Force a failure inside the callback

    • Temporarily throw an error:
    callback: async () => {
      throw new Error("test callback path");
    }
    

    If you don’t see that error surface from Crew.kickoff(), your hook isn’t wired into execution.

  4. Check package version and API shape

    • Verify whether your installed version supports callbacks on Task, Agent, or only at crew level.
    • Inspect types directly:
    npm ls crewai
    

    Then check IntelliSense on new Task({ ... }) instead of trusting blog snippets.

Prevention

  • Always await both crew.kickoff() and any async work inside callbacks.
  • Keep callbacks small; move persistence and network calls into dedicated services.
  • Pin your CrewAI version and verify API examples against that exact release.
  • In dev environments with hot reload, test long-running flows in a plain Node process first.

If you still see callback not firing during development, treat it as a wiring problem first, not an orchestration problem. In CrewAI TypeScript, most “missing” callbacks are really promises that were never awaited or hooks attached to the wrong object.


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