Fix Claude Code provider response capture for subtype=success messages#263
Closed
santoshkumarradha wants to merge 3 commits into
Closed
Fix Claude Code provider response capture for subtype=success messages#263santoshkumarradha wants to merge 3 commits into
santoshkumarradha wants to merge 3 commits into
Conversation
added 3 commits
March 13, 2026 03:25
…message format in ClaudeCodeProvider
|
SWE-AF seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
Member
Author
|
|
Contributor
Performance
✓ No regressions detected |
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.
Summary
Changes
Test plan
........................................................................ [ 19%]
........................................................................ [ 29%]
........................................................................ [ 39%]
........................................................................ [ 49%]
........................................................................ [ 58%]
........................................................................ [ 68%]
........................................................................ [ 78%]
........................................................................ [ 88%]
........................................................................ [ 98%]
............. [100%]
=============================== warnings summary ===============================
tests/test_harness_schema.py:23
/workspaces/agentfield/sdk/python/tests/test_harness_schema.py:23: PytestCollectionWarning: cannot collect test class 'TestSchema' because it has a init constructor (from: tests/test_harness_schema.py)
class TestSchema(BaseModel):
tests/test_agent_field_handler.py::test_register_with_agentfield_applies_discovery_payload
/usr/local/lib/python3.12/site-packages/pydantic/v1/json.py:12: RuntimeWarning: coroutine 'test_call_function_async..async_func' was never awaited
from pydantic.v1.color import Color
Enable tracemalloc to get traceback where the object was allocated.
See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info.
tests/test_agent_field_handler.py::test_register_with_agentfield_applies_discovery_payload
tests/test_agent_integration.py::test_agent_reasoner_routing_and_workflow
tests/test_agent_integration.py::test_callback_url_precedence_and_env
tests/test_agent_integration.py::test_callback_url_precedence_and_env
tests/test_agent_networking.py::test_build_callback_discovery_payload_marks_container
/workspaces/agentfield/sdk/python/agentfield/agent.py:1503: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
"submitted_at": datetime.utcnow().isoformat() + "Z",
tests/test_client.py: 4 warnings
tests/test_client_auth.py: 5 warnings
tests/test_client_execution_paths.py: 12 warnings
/workspaces/agentfield/sdk/python/agentfield/client.py:1020: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
metadata["timestamp"] = datetime.datetime.utcnow().isoformat()
tests/test_client_unit.py::test_generate_id_prefix_and_uniqueness
tests/test_client_unit.py::test_generate_id_prefix_and_uniqueness
/workspaces/agentfield/sdk/python/agentfield/client.py:169: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp = datetime.datetime.utcnow().strftime("%Y%m%d_%H%M%S")
tests/test_did_manager.py::test_create_execution_context
/workspaces/agentfield/sdk/python/agentfield/did_manager.py:195: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp=datetime.utcnow(),
tests/test_http_connection_manager.py::test_connection_manager_start_close
tests/test_http_connection_manager.py::test_connection_manager_context_manager
tests/test_http_connection_manager.py::test_connection_manager_double_start
tests/test_http_connection_manager.py::test_connection_manager_start_after_close
tests/test_http_connection_manager.py::test_connection_manager_get_session
tests/test_http_connection_manager.py::test_connection_manager_request_timeout
tests/test_http_connection_manager.py::test_connection_manager_batch_request
tests/test_http_connection_manager.py::test_connection_manager_health_check
tests/test_http_connection_manager.py::test_connection_manager_properties
/usr/local/lib/python3.12/site-packages/aiohttp/connector.py:993: DeprecationWarning: enable_cleanup_closed ignored because python/cpython#118960 is fixed in Python version sys.version_info(major=3, minor=12, micro=13, releaselevel='final', serial=0)
super().init(
tests/test_vc_generator.py::test_generate_execution_vc_success
/workspaces/agentfield/sdk/python/tests/test_vc_generator.py:37: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
"created_at": datetime.utcnow().isoformat() + "Z",
tests/test_vc_generator.py::test_generate_execution_vc_success
tests/test_vc_generator.py::test_generate_execution_vc_disabled
/workspaces/agentfield/sdk/python/tests/test_vc_generator.py:16: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp=datetime.utcnow(),
tests/test_vc_generator.py::test_create_workflow_vc
/workspaces/agentfield/sdk/python/tests/test_vc_generator.py:82: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
"start_time": datetime.utcnow().isoformat() + "Z",
tests/test_vc_generator.py::test_create_workflow_vc
/workspaces/agentfield/sdk/python/tests/test_vc_generator.py:83: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
"end_time": datetime.utcnow().isoformat() + "Z",
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
---------- coverage: platform linux, python 3.12.13-final-0 ----------
Name Stmts Miss Cover Missing
agentfield/agent_field_handler.py 163 47 71% 142-148, 161, 193-221, 229, 234, 282-284, 333, 529-554
agentfield/client.py 788 263 67% 72, 76, 83-86, 98-99, 200, 202, 226, 239, 244, 249, 262-263, 285-286, 291-293, 334, 349, 352, 354, 361, 363, 365, 367, 421, 441, 445-453, 462, 464, 498, 506-509, 518, 522, 542, 548, 556-567, 585, 637, 677, 692-693, 696, 700-702, 777, 781, 785, 789, 811-812, 826-827, 854-855, 865-873, 906, 930-932, 949, 973-984, 993, 1016, 1018, 1028-1029, 1045-1048, 1099-1100, 1150-1151, 1194, 1235, 1251-1252, 1255-1268, 1273-1282, 1293-1303, 1333-1382, 1404-1423, 1449-1484, 1508-1528, 1551-1570, 1593-1614, 1631-1647, 1664-1679, 1723, 1734-1735, 1775-1776, 1847-1854
agentfield/execution_context.py 119 1 99% 79
agentfield/execution_state.py 213 24 89% 113, 117, 230, 262, 279-280, 348-349, 353, 450, 454-457, 461-464, 468-470, 474, 478, 482
agentfield/memory.py 254 35 86% 116-119, 127, 272, 284, 338-339, 342, 413, 424, 462, 491, 504, 608, 690-720, 844, 856, 870, 882, 894
agentfield/result_cache.py 207 36 83% 41, 47, 73, 143-144, 162, 173-174, 194-195, 229, 238, 265-269, 273-276, 310-311, 325-331, 404-405, 420-421, 429-430, 434-435
TOTAL 1849 406 78%
1 file skipped due to complete coverage.
=========================== short test summary info ============================
SKIPPED [1] tests/integration/test_agentfield_end_to_end.py:41: AgentField server sources not available in this checkout
SKIPPED [1] tests/integration/test_agentfield_end_to_end.py:74: AgentField server sources not available in this checkout
SKIPPED [1] tests/integration/test_agentfield_end_to_end.py:114: AgentField server sources not available in this checkout
SKIPPED [1] tests/test_agent_cli.py:286: Complex argparse mocking - functionality tested in integration
729 passed, 4 skipped, 12 deselected, 45 warnings in 11.40s
2. Verify 6 tests pass including 2 new test cases:
Related Issues
Closes #252
🤖 Built with AgentField SWE-AF
🔌 Powered by AgentField
📋 PRD (Product Requirements Document)
PRD: Fix Issue #252 - Claude Code Provider Does Not Capture Response Text
Validated Description
The Claude Code Provider in
sdk/python/agentfield/harness/providers/claude.pyfails to capture the response text because it checks formsg_type == "result", but the Claude Agent SDK sends messages withsubtype == "success"instead (notypefield present). This causesHarnessResult.resultto always beNonebecause the extraction condition never matches.Current State Analysis
/workspaces/agentfield/sdk/python/agentfield/harness/providers/claude.pyif msg_type == "result":subtype: "success"to indicate the final result message, nottype: "result"result: Nonein theRawResult, even when the SDK successfully completesRequired Changes
The message type detection logic at line 91 must be expanded to recognize both:
type == "result"subtype == "success"The result extraction logic (lines 92-106) must work correctly when triggered by either condition.
Test Coverage Requirements
Existing test at
/workspaces/agentfield/sdk/python/tests/test_harness_provider_claude.pyusestype: "result"mock. New test cases must verify:subtype: "success"messages correctly extract resulttype: "result"messages continue workingScope Definitions
Must Have
if msg_type == "result" or msg_dict.get("subtype") == "success":test_harness_provider_claude.pycoveringsubtype: "success"message formattype: "result"formatNice to Have
subtypeinstead oftypeOut of Scope
RawResultorHarnessResultdata structuresAssumptions
subtype: "success"for final result messagesresultortextfield in the message dictRisks
Risk: Claude Agent SDK may have other message variations not captured by this fix
type: "result"andsubtype: "success"to maximize compatibilityRisk: Field names for result data may differ between formats
result,text,session_id,cost_usd,num_turns)Risk: Messages with
subtype: "success"may not contain the expected result data structureSuccess Metrics
resultwhen SDK completes successfullysubtype: "success"test cases🏗️ Architecture
Architecture Document: Claude Code Provider Message Detection Fix
Summary
Fix message type detection in the Claude Code Provider to recognize both the legacy
type: "result"format and the SDK-nativesubtype: "success"format. This ensures result extraction works correctly regardless of which message format the Claude Agent SDK returns.Context
The Claude Code Provider (
sdk/python/agentfield/harness/providers/claude.py) uses the nativeclaude_agent_sdkto communicate with Claude. The provider streams messages from the SDK and extracts result text when it encounters a message indicating completion.Currently, the provider only checks for
msg_type == "result"(line 91). However, the Claude Agent SDK sends completion messages withsubtype == "success"instead, causing the result extraction logic to never execute andHarnessResult.resultto remainNone.Component Structure
Component: ClaudeCodeProvider (Modified)
File:
sdk/python/agentfield/harness/providers/claude.pyResponsibility:
Execute prompts via Claude Code SDK and extract result text from streaming messages. Modified to support both message format variants.
Key Interface:
Dependencies:
agentfield.harness._result.RawResult- Return typeagentfield.harness._result.Metrics- Metrics data structureclaude_agent_sdk(lazy import) - External SDK for Claude communicationMessage Detection Logic (Line 91 modification):
Current condition:
New condition:
Result Extraction Block (Lines 92-106):
The existing extraction logic remains unchanged but now triggers on either condition:
resultortextfield asresult_textsession_idfor session trackingcost_usdortotal_cost_usdfor billingnum_turnsfor turn countingData Flow Example:
Scenario A: Legacy format (
type: "result")Scenario B: SDK format (
subtype: "success")Scenario C: Mixed messages
Test Coverage
Component: ClaudeProviderTests (Extended)
File:
sdk/python/tests/test_harness_provider_claude.pyResponsibility:
Verify Claude Code Provider behavior including new message format support.
New Test Cases:
test_execute_extracts_result_from_subtype_success
subtype='success'messageraw.resultequals expected textsession_id,cost_usd,num_turnsextractiontest_execute_handles_mixed_message_formats
type: 'result'andsubtype: 'success'messagesTest Pattern (SDK message mock):
Architectural Decisions
Decision 1: OR-based condition rather than separate handlers
Decision: Use a single conditional with OR logic rather than separate if blocks for each format.
Rationale:
Alternative rejected: Separate
if msg_type == "result":andif msg_subtype == "success":blocks would duplicate the extraction code.Decision 2: Preserve backward compatibility
Decision: Keep existing
type: "result"detection while addingsubtype: "success"support.Rationale:
Decision 3: No changes to message data structures
Decision: Do not modify
_result.pyor_schema.py.Rationale:
Decision 4: Subtype checked via .get() with default
Decision: Use
msg_dict.get("subtype", "")rather than direct key access.Rationale:
subtypefield (backward compatibility)typefield access patternError Handling
Error Path 1: Neither format detected
type == "result"norsubtype == "success"matchesresult_textremains NoneError Path 2: SDK throws exception
is_error=Trueand error messageError Path 3: Missing extraction fields
.get()with sensible defaultsresultfalls back totextfieldcost_usdfalls back tototal_cost_usdPerformance Considerations
Budget: < 1ms additional overhead per message
Breakdown:
.get("subtype")call: ~0.1μs (dict lookup)Optimization: None needed - change adds minimal overhead to existing hot path.
Module Dependency Graph
File Changes Summary
sdk/python/agentfield/harness/providers/claude.py (Modified)
if msg_type == "result":toif msg_type == "result" or msg_dict.get("subtype") == "success":sdk/python/tests/test_harness_provider_claude.py (Extended)
test_execute_extracts_result_from_subtype_success(~40 lines)test_execute_handles_mixed_message_formats(~50 lines)Verification Checklist
pytest -xvs sdk/python/tests/test_harness_provider_claude.py::test_execute_maps_options_and_extracts_resultpassespytest -xvs sdk/python/tests/test_harness_provider_claude.py::test_execute_returns_error_result_on_query_failurepassespytest -xvs sdk/python/tests/test_harness_provider_claude.py::test_execute_extracts_result_from_subtype_successpasses (new)pytest -xvs sdk/python/tests/test_harness_provider_claude.py::test_execute_handles_mixed_message_formatspasses (new)grep -n 'subtype.*success\|type.*result' sdk/python/agentfield/harness/providers/claude.pyshows both conditionspython -c "from agentfield.harness.providers.claude import ClaudeCodeProvider"