How to Fix 'callback not firing in production' in CrewAI (Python)
What this error usually means
If your CrewAI callback works locally but never fires in production, the issue is usually not CrewAI itself. It means the callback was registered in a way that only works for one execution path, or the process running in production never reaches the event where the callback is invoked.
In practice, this shows up when you move from a local script to Docker, FastAPI, Celery, serverless, or a multi-process setup and suddenly your Task or Crew callback stops being called.
The Most Common Cause
The #1 cause is passing the callback in the wrong place or relying on an object that gets recreated in production.
In CrewAI, callbacks are typically attached to Task, Agent, or Crew depending on what event you want to capture. A common mistake is defining a function correctly but never wiring it to the actual Task that runs, or creating the callback inside a request scope that disappears before execution finishes.
Broken vs fixed pattern
| Broken pattern | Fixed pattern |
|---|---|
| Callback defined, but not attached to the executed task | Callback attached directly to the task that runs |
| Callback object recreated per request | Stable callback instance passed into crew/task construction |
| Local sync script works, async/prod worker loses reference | Explicit wiring at startup |
# BROKEN
from crewai import Agent, Task, Crew
def on_complete(output):
print("Task completed:", output)
agent = Agent(
role="Researcher",
goal="Research company info",
backstory="You research facts."
)
task = Task(
description="Summarize ACME Corp",
agent=agent,
)
crew = Crew(
agents=[agent],
tasks=[task],
)
result = crew.kickoff()
# on_complete never fires because it was never attached anywhere
# FIXED
from crewai import Agent, Task, Crew
def on_complete(output):
print("Task completed:", output)
agent = Agent(
role="Researcher",
goal="Research company info",
backstory="You research facts."
)
task = Task(
description="Summarize ACME Corp",
agent=agent,
callback=on_complete, # attach it here
)
crew = Crew(
agents=[agent],
tasks=[task],
)
result = crew.kickoff()
If you’re using a crew-level callback pattern in your version of CrewAI, make sure you’re using the exact supported signature for that version. A mismatch between your installed package and the docs can produce behavior like:
- •no callback execution
- •silent failures
- •
TypeError: on_complete() takes 1 positional argument but 2 were given
Other Possible Causes
1) Production is running a different CrewAI version
This is common when local pip install crewai differs from your Docker image or deployed lockfile.
Local: crewai==0.80.x
Prod: crewai==0.70.x
A version mismatch can change:
- •callback parameter names
- •whether callbacks are supported on
Task - •whether callbacks are sync-only
Check with:
pip show crewai
pip freeze | grep crewai
2) Your process exits before the callback runs
This happens in short-lived jobs and serverless handlers.
from crewai import Crew
result = crew.kickoff()
return {"status": "started"} # process/request ends too early in some deployments
If your execution model is asynchronous or backgrounded, make sure you await completion or keep the worker alive until kickoff returns.
3) Exceptions inside the callback are swallowed by logging
Your callback may fire and fail immediately.
def on_complete(output):
raise RuntimeError("callback broke")
In production, this can look like “callback not firing” because you only see upstream logs. Wrap it:
def on_complete(output):
try:
print(output)
# send metrics / webhook / DB write
except Exception as e:
logger.exception("callback failed: %s", e)
4) Multiprocessing / Celery / Gunicorn worker isolation
If you register callbacks in one process and execute CrewAI in another, the function reference may not survive serialization.
Bad pattern:
# created in web process, executed in worker process
task = Task(description="...", agent=agent, callback=on_complete)
If on_complete closes over non-picklable objects like DB sessions or request context, workers may drop it or fail silently. Use module-level functions and pass primitive data only.
5) You attached the callback to the wrong object
CrewAI has multiple layers:
- •
Agent - •
Task - •
Crew
If you expect task completion output but attach a crew-level handler meant for another event type, nothing useful happens.
Example:
crew = Crew(
agents=[agent],
tasks=[task],
# wrong place for this specific event in your version/setup
)
Check which lifecycle hook your installed version actually supports.
How to Debug It
- •
Print every lifecycle boundary Add logs before kickoff, inside the task definition path, and inside the callback. If you don’t see the “before kickoff” log in prod, your code path isn’t even reaching CrewAI.
- •
Verify exact installed versions Run this in production startup logs:
import crewai print(crewai.__version__)Compare it with local. If they differ, fix your lockfile and rebuild.
- •
Reduce to a module-level sync example Remove FastAPI/Celery/background workers and run a plain Python script. If it works there but not in prod, the problem is process lifecycle or serialization.
- •
Make the callback fail loudly Put explicit logging at entry:
def on_complete(output): print("CALLBACK HIT") print(type(output), output)If even this doesn’t show up, the callback isn’t wired correctly or isn’t surviving deployment boundaries.
Prevention
- •Define callbacks as module-level functions, not nested closures inside request handlers.
- •Pin CrewAI versions with a lockfile and test deployment images against local installs.
- •Keep callbacks simple: log first, then enqueue work to another system if needed.
- •Add an integration test that runs
crew.kickoff()and asserts callback side effects happened.
If you’re seeing callback not firing in production, start by checking wiring first, then runtime model second. In most cases it’s not a CrewAI bug; it’s a mismatch between how Python objects behave locally and how your production worker actually executes them.
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