fix(crewai): unwrap Part before DataPart check so structured inputs are used#2231
Open
anxkhn wants to merge 1 commit into
Open
fix(crewai): unwrap Part before DataPart check so structured inputs are used#2231anxkhn wants to merge 1 commit into
anxkhn wants to merge 1 commit into
Conversation
…re used In the CrewAI A2A executor, the loop that pulls structured inputs from the request message guarded on `isinstance(part, DataPart)`. Each element of `Message.parts` is an a2a `Part`, which is a `RootModel[TextPart | FilePart | DataPart]`, so the actual `DataPart` lives at `part.root`. The check was therefore always False, the branch never ran, and `inputs` stayed None: a crew invoked with a structured `DataPart` silently fell back to the free-text `get_user_input()` path and ignored the payload. The very next line already read `part.root.data`, contradicting the guard. Check `isinstance(part.root, DataPart)` instead, matching how every other call site in the codebase (e.g. converters/part_converter.py and event_converter.py) unwraps the part. Add regression tests covering both the DataPart and the text-fallback paths. Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes structured-input extraction in the CrewAI A2A executor by unwrapping Part wrappers before checking for DataPart, ensuring DataPart.data payloads are actually passed through to crew.kickoff_async(...) instead of silently falling back to free-text input.
Changes:
- Update
CrewAIAgentExecutor.executeto checkisinstance(part.root, DataPart)when scanning incomingMessage.parts. - Add end-to-end unit tests covering both
DataPart(structured) andTextPart(fallback) input paths. - Add a test
conftest.pyto set requiredKAGENT_*env vars early to avoid import-time config failures during test collection.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| python/packages/kagent-crewai/src/kagent/crewai/_executor.py | Fixes DataPart detection by checking part.root so structured inputs are used. |
| python/packages/kagent-crewai/tests/test_executor.py | Adds async tests validating DataPart inputs are passed through and TextPart still falls back correctly. |
| python/packages/kagent-crewai/tests/conftest.py | Sets required KAGENT_* env vars before imports to prevent test collection failures. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+25
to
+32
| async def _run(crew: MagicMock, context: RequestContext) -> None: | ||
| executor = CrewAIAgentExecutor( | ||
| crew=crew, | ||
| app_name="test", | ||
| http_client=httpx.AsyncClient(), | ||
| ) | ||
| await executor.execute(context, EventQueue()) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
In the CrewAI A2A executor, the loop that extracts structured inputs from the
incoming request message guarded on
isinstance(part, DataPart):Each element of
Message.partsis an a2aPart, which is aRootModel[TextPart | FilePart | DataPart], so the actualDataPartlives atpart.root. Theisinstance(part, DataPart)check is therefore alwaysFalse:the branch never runs,
inputsstaysNone, and a crew invoked with a structuredDataPartsilently falls back to the free-textget_user_input()path and ignoresthe payload. Note that the very next line already reads
part.root.data, whichcontradicts the guard one line above it.
Fix
Check
isinstance(part.root, DataPart)instead, so the wrapper is unwrapped beforethe type test:
This matches how the rest of the codebase handles
Partwrappers, for exampleconverters/event_converter.py(which checksisinstance(a2a_part.root, DataPart)before reading the data). One-line change; no behavior change for the text-input
path.
Tests
Added
packages/kagent-crewai/tests/test_executor.pywith two tests that driveCrewAIAgentExecutor.executeend to end with a mocked crew:test_execute_passes_datapart_data_as_inputs: sends aDataPartand asserts thecrew is kicked off with
inputs={"topic": "ai"}. This test fails onmain(the crew is kicked off with
inputs={}) and passes with the fix.test_execute_falls_back_to_text_input_without_datapart: sends aTextPartandasserts the existing text-fallback path still yields
inputs={"input": "hello"}.Also added
packages/kagent-crewai/tests/conftest.pyto setKAGENT_URL,KAGENT_NAME, andKAGENT_NAMESPACEbefore import, becauseKAgentConfig()isevaluated at import time (as a default argument in
_a2a.py) and requires them, sotest collection would otherwise fail.
Verification
The change is Python agent-runtime only and is fully covered by unit tests; it does
not touch controllers, CRDs, or require a cluster, so no E2E test is added (per the
CONTRIBUTING note that minor behavior changes can be excepted from E2E).