DS DevShelfHub Projects · AI tools
Tutorials / CrewAI / Reference / Decorators / @after_tool_call_crew
Decorator crewai.hooks

@after_tool_call_crew: Reference Guide

By DevShelfHub

Runs after every tool call within the crew — transform results, validate, or persist.

See the CrewAI API reference index, CrewAI introduction, hooks and events tutorial, and core concepts for surrounding context.

What is @after_tool_call_crew?

Once a tool finishes, @after_tool_call_crew receives the ToolCallHookContext populated with the result string or structured payload. Return a new string to replace what the agent reads — ideal for trimming verbose HTTP bodies, masking tokens, or normalizing JSON. Returning None keeps the original output.

This hook is the right place to implement cross-cutting observability for tools without modifying each BaseTool subclass. Keep transformations loss-aware: if you truncate HTML, append a marker so the model knows content was clipped. Combine with sanitize_tool_result helpers when you want shared scrubbers across crews.

Do not confuse this with Task.output_file or callbacks that run per task — after_tool_call_crew fires for every tool invocation regardless of which task scheduled it, making it ideal for centralized policy but unsuitable for task-specific business rules that belong next to the Task definition.

When to Use

Trimming/redacting/caching tool output before the agent sees it.

Use Cases

  • • Trim verbose output
  • • Cache results
  • • Redact sensitive fields

Key Features

  • ✓ Crew-scoped
  • ✓ Can rewrite the result

When NOT to Use

Tool-internal cleanup — do it in _run().

Notes

None versus unchanged

Returning None preserves the tool output; returning an empty string removes content entirely and can confuse agents — prefer explicit truncation messages.

Binary payloads

Some tools return serialized blobs. Confirm whether ctx.result is text before running regex replacements.

Ordering with LLM hooks

Tool hooks fire around tool execution, independent of LLM hook ordering. Do not rely on interleaving for correctness.

Import

python
from crewai.hooks import after_tool_call_crew

How to Apply

python
@after_tool_call_crew
def cache(ctx):
    cache[ctx.tool_name] = ctx.result

What It Enables

  • ✓ Result post-processing
  • ✓ Caching

Code Examples

Trim

python
@after_tool_call_crew
def trim(ctx):
    return ctx.result[:2000]

Redact API keys in text

python
import re

_TOKEN = re.compile(r'sk-[A-Za-z0-9]{16,}')

@after_tool_call_crew
def mask(ctx):
    return _TOKEN.sub('sk-REDACTED', ctx.result or '')

Cache idempotent reads

python
@after_tool_call_crew
def memo(ctx):
    if ctx.tool_name == 'lookup_customer':
        cache[getattr(ctx, 'tool_input', '')] = ctx.result
    return None

Integration Patterns

Pairs with @before_tool_call_crew

Common Mistakes

❌ Forgetting to return the (possibly-trimmed) string

✅ Return the new result; returning None leaves the original untouched.

Related: Task class reference, Agent class reference, and the first Crew tutorial.

@after_tool_call_crew FAQ

What is @after_tool_call_crew in CrewAI?

Runs after every tool call within the crew — transform results, validate, or persist. Once a tool finishes, @after_tool_call_crew receives the ToolCallHookContext populated with the result string or structured payload. Return a new string to replace what the agent reads — ideal for trimming verbose HTTP bodies, masking tokens, or normalizing JSON. Returning None keeps the original output. This hook is the right place to implement cross-cutting observability for tools without modifying each BaseTool subclass. Keep transformations loss-aware: if you truncate HT…

Which module defines the CrewAI decorator @after_tool_call_crew?

DevShelfHub maps @after_tool_call_crew to Python module crewai.hooks. Pin your installed crewai version and match imports to the import snippet on this page.

When should I use @after_tool_call_crew?

Trimming/redacting/caching tool output before the agent sees it.

When should I avoid @after_tool_call_crew?

Tool-internal cleanup — do it in _run().

How do I apply @after_tool_call_crew in Python?

@after_tool_call_crew def cache(ctx): cache[ctx.tool_name] = ctx.result

Where can I explore more CrewAI API reference pages?

Open the CrewAI API reference index on DevShelfHub to search classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.