feat(adk): Revamp run_claude_agent_activity to use more streaming#309
Merged
declan-scale merged 15 commits intonextfrom Apr 7, 2026
Merged
feat(adk): Revamp run_claude_agent_activity to use more streaming#309declan-scale merged 15 commits intonextfrom
declan-scale merged 15 commits intonextfrom
Conversation
…hooks for rich responses
0205e2e to
4c265b2
Compare
4c265b2 to
91f1f6e
Compare
11ed880 to
464cd2d
Compare
danielmillerp
approved these changes
Apr 7, 2026
Merged
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
Revamps
run_claude_agent_activityto stream all content block types directly from the Claude SDK message stream, replacing the previousClaudeMessageHandlerindirection.Streaming changes (
activities.py):AssistantMessagecontent blocks (TextBlock, ThinkingBlock, ToolUseBlock) in iteration order with correct timestampsReasoningContent(with summary extraction)ToolRequestContentwith subagent span tracingHooks refactor (
hooks/hooks.py):activities.pyintoTemporalStreamingHooksclassauto_allow_hook(PreToolUse): auto-allows all tool permissionspost_tool_use_hook(PostToolUse): streams tool results to UI, closes subagent spanspost_tool_use_failure_hook(PostToolUseFailure): streams tool errors to UI, closes subagent spansHookInput,HookContext,SyncHookJSONOutput, etc.)create_streaming_hooks()accepts sharedsubagent_spansdict so hooks and message-level streaming share stateclaude_optionsare merged with the activity hooksTests (
test_claude_agents_hooks.py):Test plan
rye run pytest tests/lib/test_claude_agents_hooks.py— 24 passrye run pytest tests/lib/test_claude_agents_activities.py -k "not TestRunClaudeAgentActivity"— 13 pass🤖 Generated with Claude Code
Greptile Summary
This PR replaces the
ClaudeMessageHandlerindirection inrun_claude_agent_activitywith direct inline streaming of allAssistantMessagecontent blocks (TextBlock → text deltas, ThinkingBlock → ReasoningContent, ToolUseBlock → ToolRequestContent), and extracts the hook closures into a typedTemporalStreamingHooksclass backed by proper Claude SDK types (HookInput,HookContext,HookJSONOutput). The subagent span lifecycle is now correctly split — spans are opened instream_tool_requestand closed in PostToolUse/PostToolUseFailure hooks or in the exception handler — resolving the span-leak concerns raised in previous review rounds.Confidence Score: 5/5
Safe to merge; the refactor is well-structured with solid test coverage and previous P1 span-leak concerns are fully resolved
No P0 or P1 issues remain. The only finding is a minor P2 style inconsistency (duplicate ToolRequestContent construction in stream_tool_request vs. the shared-variable pattern already used in hooks). 24 new hook tests and updated activity tests provide good regression coverage.
No files require special attention
Important Files Changed
Sequence Diagram
sequenceDiagram participant W as Temporal Workflow participant A as run_claude_agent_activity participant SDK as ClaudeSDKClient participant H as TemporalStreamingHooks participant UI as AgentEx UI W->>A: invoke(prompt, options) A->>SDK: query(prompt) loop receive_response() SDK-->>A: AssistantMessage alt TextBlock A->>UI: stream_update(TextDelta) else ThinkingBlock A->>UI: stream_update(ReasoningContent) else ToolUseBlock A->>UI: stream_update(ToolRequestContent) A->>A: open subagent span (if Task tool) end SDK-->>H: PostToolUse hook H->>H: pop + close subagent span (if Task) H->>UI: stream_update(ToolResponseContent) SDK-->>H: PostToolUseFailure hook H->>H: pop + close subagent span (if Task) H->>UI: stream_update(ToolResponseContent Error) SDK-->>A: ResultMessage A->>A: record usage/cost/session_id end A->>UI: close_text_stream() A-->>W: {messages, session_id, usage, cost_usd}Comments Outside Diff (1)
tests/lib/test_claude_agents_activities.py, line 231-446 (link)@patchdecorators breakTestRunClaudeAgentActivityAll three test methods patch
agentex.lib.core.temporal.plugins.claude_agents.activities.ClaudeMessageHandler, butClaudeMessageHandleris no longer imported inactivities.pyafter this PR. By default,unittest.mock.patchraisesAttributeErrorwhen the target attribute doesn't exist on the module. The PR test plan explicitly works around this with-k "not TestRunClaudeAgentActivity", confirming these tests are currently broken and provide no coverage for the new streaming logic.Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (6): Last reviewed commit: "Add task_id gaurd when None" | Re-trigger Greptile