@@ -197,6 +197,76 @@ path. No API change — behavior only.
197197 function-tool response path (` on_tool_end ` ) so hosted and function tools
198198 render identically within the same flow.
199199
200+ 5 . ** Reasoning text now appears in derived spans.** ` SpanDeriver ` opened reasoning
201+ spans with empty input and closed them with ` output=None ` , so reasoning/thinking
202+ text never reached the trace (spans showed blank — read as "0 reasoning traces").
203+ It now accumulates the ` ReasoningContentDelta ` / ` ReasoningSummaryDelta ` text (and
204+ any text seeded on the Start content) and records it as the span output. Affects
205+ every harness that streams reasoning, including the Claude Code tap.
206+
207+ 6 . ** Claude Code: no more duplicate text messages.** The ` stream-json ` converter
208+ deduped streamed-vs-materialized blocks by numeric block index and reset that
209+ state after every materialized ` assistant ` envelope. A single streamed message
210+ that materializes as several envelopes (thinking, then text) lost the dedup
211+ marker between envelopes and re-emitted the text. Dedup is now ** content-based**
212+ (match the streamed block's text, consume once), which a numeric index cannot do
213+ reliably.
214+
200215> Action: if you adopted ` OpenAITurn ` for ** reasoning models** (o1/o3/gpt-5) on
201216> the sync path before these fixes, upgrade — fixes 2 and 3 are required for
202- > correct reasoning rendering.
217+ > correct reasoning rendering. Claude Code agents on the unified harness tap should
218+ > upgrade for fixes 5 and 6.
219+
220+ ---
221+
222+ ## 6. Legacy Temporal ` claude_agents ` plugin → unified harness tap
223+
224+ ` agentex.lib.core.temporal.plugins.claude_agents ` (` run_claude_agent_activity ` ,
225+ ` create_streaming_hooks ` , ` TemporalStreamingHooks ` , ` ClaudeMessageHandler ` ) is the
226+ ** original** Claude Code integration: it drives the Python ` claude-agent-sdk `
227+ directly and hand-rolls its own streaming + tracing. It is ** superseded** by the
228+ unified harness tap and slated for removal in a future release. It still works
229+ today, so this migration is ** recommended, not yet required** — but new Claude Code
230+ agents should use the tap, and existing ones should plan to move.
231+
232+ Why migrate: the tap routes Claude Code through the same canonical
233+ ` StreamTaskMessage* ` stream as every other harness, so it gets central span
234+ derivation (tool ** and** reasoning spans), the single delivery path
235+ (` UnifiedEmitter ` ), and fixes like the two above for free. The legacy plugin does
236+ not derive reasoning spans at all and duplicates the streaming/tracing logic.
237+
238+ ** Before — legacy plugin activity:**
239+
240+ ``` python
241+ from agentex.lib.core.temporal.plugins.claude_agents import run_claude_agent_activity
242+
243+ # In the workflow:
244+ result = await workflow.execute_activity(
245+ run_claude_agent_activity,
246+ args = [prompt, workspace_path, allowed_tools, ... ],
247+ start_to_close_timeout = ... ,
248+ )
249+ ```
250+
251+ ** After — unified harness tap.** Run the CLI yourself (`claude -p --output-format
252+ stream-json --include-partial-messages` ), wrap its stdout in ` ClaudeCodeTurn`, and
253+ deliver through ` UnifiedEmitter ` :
254+
255+ ``` python
256+ from agentex.lib.adk import ClaudeCodeTurn, UnifiedEmitter
257+
258+ # `stdout_lines` is an async iterator of the CLI's stdout lines (raw JSON strings
259+ # or pre-parsed dicts) — e.g. read from sandbox.exec() / a subprocess.
260+ turn = ClaudeCodeTurn(stdout_lines)
261+
262+ emitter = UnifiedEmitter(task_id = task_id, trace_id = trace_id, parent_span_id = parent_span_id)
263+ result = await emitter.auto_send_turn(turn, created_at = workflow.now())
264+ # result.final_text — last text segment
265+ # result.usage — TurnUsage (tokens, cost, num_reasoning_blocks, ...)
266+ ```
267+
268+ The golden agent is the reference implementation
269+ (` teams/sgp/agents/golden_agent/project/harness/ ` ): it spawns the CLI in a sandbox,
270+ yields stdout lines into ` ClaudeCodeTurn ` , and drives ` auto_send_turn ` . Known
271+ remaining consumers to migrate: the ` 090_claude_agents_sdk_mvp ` tutorial and the
272+ ` eval_dashboard_agent ` .
0 commit comments