Skip to content

feat(events): expose native tool call ids - #7189

Open
z2Ace0107 wants to merge 2 commits into
crewAIInc:mainfrom
z2Ace0107:codex/crewai-tool-call-id
Open

feat(events): expose native tool call ids#7189
z2Ace0107 wants to merge 2 commits into
crewAIInc:mainfrom
z2Ace0107:codex/crewai-tool-call-id

Conversation

@z2Ace0107

Copy link
Copy Markdown

Fixes #7178

Summary

  • Add an optional call_id field to ToolUsageEvent.
  • Populate it for started, finished, and error events emitted by native tool execution paths.
  • Preserve backward compatibility for event producers that do not have a native model call id.

This allows event consumers to correlate a tool execution with the model tool call that initiated it.

Verification

  • Added regression coverage for successful and failing native tool calls.
  • Python 3.12.13: focused native tool tests passed.
  • Ruff check passed.
  • Ruff format check passed.
  • Mypy passed for the changed production files.

Additional context

This PR was prepared with AI assistance. I reviewed the changed implementation and tests. Please apply the required llm-generated label.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 61834c7a-cce0-4770-b6f2-6919c688a709

📥 Commits

Reviewing files that changed from the base of the PR and between c0f4d39 and fa3e126.

📒 Files selected for processing (6)
  • lib/crewai/src/crewai/agents/crew_agent_executor.py
  • lib/crewai/src/crewai/experimental/agent_executor.py
  • lib/crewai/src/crewai/utilities/agent_utils.py
  • lib/crewai/tests/agents/test_agent_executor.py
  • lib/crewai/tests/agents/test_native_tool_calling.py
  • lib/crewai/tests/utilities/test_agent_utils.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Changes

Native tool execution now separates provider call IDs from locally generated message IDs. Started, error, and finished tool usage events report provider IDs when available. Tests cover successful, failed, and missing-ID execution paths.

Native tool call ID propagation

Layer / File(s) Summary
Call ID contract and extraction
lib/crewai/src/crewai/events/types/tool_usage_events.py, lib/crewai/src/crewai/utilities/agent_utils.py
ToolUsageEvent now defines optional call_id data. Utilities extract provider IDs from supported tool-call shapes and retain generated fallback IDs for tool messages.
Native tool executor wiring
lib/crewai/src/crewai/agents/crew_agent_executor.py, lib/crewai/src/crewai/experimental/agent_executor.py, lib/crewai/src/crewai/utilities/agent_utils.py
Native execution parses and threads provider IDs through single and batched paths. Lifecycle events use the provider ID instead of the local fallback ID.
Event correlation coverage
lib/crewai/tests/agents/test_agent_executor.py, lib/crewai/tests/agents/test_native_tool_calling.py, lib/crewai/tests/utilities/test_agent_utils.py
Tests verify provider ID propagation for successful and failed calls. Tests also verify None event IDs and generated fallback message IDs when providers omit an ID.

Suggested reviewers: lorenzejay

Merge Risk: ⚪ Minimal · up to fa3e1

This PR adds an optional native tool-call correlation ID to lifecycle events while preserving existing execution behavior and backward compatibility; no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: exposing native tool call IDs through events.
Description check ✅ Passed The description includes all required template sections, links issue #7178, summarizes the implementation, documents verification results, and provides additional context.
Linked Issues check ✅ Passed The changes satisfy issue #7178 by adding an optional ToolUsageEvent.call_id, populating it at native tool execution emit sites, preserving provider IDs, avoiding exposure of synthetic IDs, and adding…
Out of Scope Changes check ✅ Passed The production and test changes support the linked issue. Updates to agent_utils.py and experimental/agent_executor.py cover additional native event emit sites and are related to the requested correla…
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 30 functions across 7 files.
Full details: Linked Issues check

Explanation

The changes satisfy issue #7178 by adding an optional ToolUsageEvent.call_id, populating it at native tool execution emit sites, preserving provider IDs, avoiding exposure of synthetic IDs, and adding regression coverage.

Full details: Out of Scope Changes check

Explanation

The production and test changes support the linked issue. Updates to agent_utils.py and experimental/agent_executor.py cover additional native event emit sites and are related to the requested correlation behavior. No unrelated changes are evident.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@IdoGol24

IdoGol24 commented Sep 1, 2026

Copy link
Copy Markdown

@z2Ace0107 Thanks for picking this up ,the coverage is broader than I described. I pointed only at _execute_single_native_tool_call, you also caught the emit sites in agent_utils.py and experimental/agent_executor.py.
One gap before it lands. _parse_native_tool_call is unchanged, so it still does:

call_id = getattr(tool_call, "id", f"call_{id(tool_call)}")

The new call_id is therefore sometimes the provider's id and sometimes a value CrewAI invented, with nothing distinguishing them. The synthesized branch derives from id(tool_call) - the object address - which CPython reuses after garbage collection, so two distinct tool calls in a long-running crew can be emitted with the same call_id. A consumer trusting it as a correlation key mis-pairs in exactly the retry and parallel-batch cases the field exists to disambiguate.

Smallest fix (my own suggestion): populate call_id only when the provider supplied one. The semconv treatment for gen_ai.tool.call.id is "when available" - absence is a valid answer, a fabricated id isn't.
Otherwise keep the fallback and add a source marker.

Do the new tests cover the no-provider-id path? From the diff they look like they exercise cases where an id is present

Also, I've accidentally closed the issue by mistake.. Could a maintainer flip back open #7178? It shouldn't read as resolved while this is still in review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Expose the native tool call id on tool usage events

2 participants