Skip to content

[DO NOT MERGE] Dev/sdk 0.14.0.dev0#439

Open
NiteshDhanpal wants to merge 13 commits into
mainfrom
dev/sdk-0.14.0.dev0
Open

[DO NOT MERGE] Dev/sdk 0.14.0.dev0#439
NiteshDhanpal wants to merge 13 commits into
mainfrom
dev/sdk-0.14.0.dev0

Conversation

@NiteshDhanpal

@NiteshDhanpal NiteshDhanpal commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

⚠️ DO NOT MERGE — dev artifact. Pre-release version bump to build a throwaway wheel for load testing. Not for release.

What

Bumps adk/pyproject.toml (agentex-sdk) 0.13.20.14.0.dev0 so we can uv build a clearly-versioned pre-release wheel off next.

Why

next carries two tracing fixes that aren't in any published agentex-sdk (latest is 0.13.2):

We need these in the rocket_mock_async_agent load-test image now, ahead of a real 0.14.x.

How it's consumed

The wheel built from this branch is vendored into the agent image — see agentex-agents #1736. Nothing here is published to PyPI; .dev0 sorts below a future real 0.14.0.

Cleanup

Close once 0.14.x is cut through the normal release flow.

Greptile Summary

This is a DO NOT MERGE dev artifact cutting agentex-sdk 0.14.0.dev0 off the next branch to produce a vendored wheel for load testing the rocket_mock_async_agent. It bundles two targeted fixes and a large new unified harness surface.

  • PR fix(tracing): fail open temporal span activities #437 (fail-open tracing): TracingModule.start_span / end_span now catch ActivityError and TemporalTimeoutError in Temporal workflows, re-raise cancellations, emit the agentex.tracing.temporal_span_activity.dropped Datadog counter, and return None / the original span instead of failing the workflow. state_machine.py is updated to guard end_span against the newly possible None return.
  • PR feat(tracing): skip Agentex span-start write by default (end-only ingest) #438 (single-INSERT tracing): AgentexTracingProcessor gains a skip-start flag (env AGENTEX_TRACING_SKIP_AGENTEX_SPAN_START, default ON) that turns the previous INSERT-on-start + UPDATE-on-end double-write into a single spans.create on end; the decision is captured once at __init__ to prevent mid-span splits.
  • Unified harness surface (AGX1-375): Adds span_derivation.py, tracer.py, types.py, auto_send.py, emitter.py, and yield_delivery.py under src/agentex/lib/core/harness/, along with new *Turn adapters for LangGraph, pydantic-ai, Claude Code, and Codex; all re-exported from adk.__init__.

Confidence Score: 4/5

Safe to build from for load-testing purposes; both targeted tracing fixes are structurally sound and the state_machine guard is correct.

The two core fixes are narrow and well-tested. The unified harness surface is new code with good test coverage and explicit docstrings for known limitations. Two minor inefficiencies — a per-call counter allocation in the dropped-metric helper and a noisy init-time logger.info on every processor construction — don't affect correctness but are worth addressing before the real 0.14.x release.

agentex_tracing_processor.py (init-time log noise), tracing.py (counter allocation per drop event). All harness surface files look clean.

Important Files Changed

Filename Overview
adk/pyproject.toml Version bump 0.13.2 → 0.14.0.dev0 to produce a clearly-versioned pre-release wheel for load testing.
src/agentex/lib/adk/_modules/tracing.py Adds fail-open handling for Temporal span activities: ActivityError / TemporalTimeoutError are caught, cancellations re-raised, and a Datadog counter emitted on drop. The span context manager already guards end_span with if span:, so the new None return from start_span is handled correctly.
src/agentex/lib/core/tracing/processors/agentex_tracing_processor.py Adds AGENTEX_TRACING_SKIP_AGENTEX_SPAN_START env flag (default ON) to collapse the per-span INSERT+UPDATE into a single INSERT on end. The skip decision is correctly captured once at init to prevent mid-span splits. The logger.info on init fires on every new processor instance, which may be noisy in high-churn environments.
src/agentex/lib/core/harness/span_derivation.py New pure stateful reducer: derives OpenSpan/CloseSpan signals from the canonical StreamTaskMessage* stream; handles both Full-only (LangGraph) and Start+Delta+Done (pydantic-ai, Claude Code) harnesses. flush() closes dangling opens as incomplete on stream end.
src/agentex/lib/core/harness/tracer.py New adapter: consumes SpanSignals and opens/closes adk.tracing child spans. Duplicate OpenSpan keys silently orphan the prior span (acknowledged in the docstring). All errors are caught and logged; tracing never breaks delivery.
src/agentex/lib/core/harness/auto_send.py New async delivery path: drives canonical stream to adk.streaming contexts, derives spans as a side effect. The finally block flushes remaining open contexts and span signals even on exception.
src/agentex/lib/core/harness/emitter.py New UnifiedEmitter facade: ties trace context + delivery mode (yield vs auto-send). usage=turn.usage() is correctly read after auto_send consumes the stream, not before.
src/agentex/lib/sdk/state_machine/state_machine.py Fixes AttributeError introduced by the fail-open change: initialises span = None before the tracing branch and guards end_span with span is not None.
src/agentex/lib/adk/_modules/_langgraph_async.py Rewrites stream_langgraph_events on LangGraphTurn+UnifiedEmitter. Hardcodes trace_id=None (tracing disabled), consistent with the original implementation. Public signature is preserved.
src/agentex/lib/core/harness/types.py New type definitions for the unified harness surface: OpenSpan, CloseSpan, TurnUsage, TurnResult, HarnessTurn Protocol.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph fix437 ["Fix #437 – Temporal fail-open"]
        A["ActivityHelpers.execute_activity()"] -->|"ActivityError / TimeoutError"| B{"is_cancelled?"}
        B -->|Yes| C["re-raise → fail workflow"]
        B -->|No| D["log warning + emit counter"]
        D -->|start_span| E["return None"]
        D -->|end_span| F["return original span"]
        A -->|Success| G["return Span"]
    end

    subgraph fix438 ["Fix #438 – Single-INSERT tracing"]
        H["on_span_start()"] --> I{"_skip_span_start (default ON)"}
        I -->|True| J["no-op"]
        I -->|False| K["spans.create(start kwargs)"]
        L["on_span_end()"] --> M{"_skip_span_start"}
        M -->|True| N["spans.create(full kwargs)"]
        M -->|False| O["spans.update(end kwargs)"]
    end

    subgraph harness ["Unified harness surface (AGX1-375)"]
        P["HarnessTurn"] --> Q["convert_*_to_agentex_events()"]
        Q --> R["SpanDeriver.observe()"]
        R -->|"OpenSpan / CloseSpan"| S["SpanTracer.handle()"]
        S --> T["adk.tracing.start_span / end_span"]
        Q --> U{"Delivery mode"}
        U -->|"Async / Temporal"| V["auto_send() → adk.streaming"]
        U -->|"Sync HTTP ACP"| W["yield_events() → HTTP yield"]
        V --> X["TurnResult"]
        W --> X
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    subgraph fix437 ["Fix #437 – Temporal fail-open"]
        A["ActivityHelpers.execute_activity()"] -->|"ActivityError / TimeoutError"| B{"is_cancelled?"}
        B -->|Yes| C["re-raise → fail workflow"]
        B -->|No| D["log warning + emit counter"]
        D -->|start_span| E["return None"]
        D -->|end_span| F["return original span"]
        A -->|Success| G["return Span"]
    end

    subgraph fix438 ["Fix #438 – Single-INSERT tracing"]
        H["on_span_start()"] --> I{"_skip_span_start (default ON)"}
        I -->|True| J["no-op"]
        I -->|False| K["spans.create(start kwargs)"]
        L["on_span_end()"] --> M{"_skip_span_start"}
        M -->|True| N["spans.create(full kwargs)"]
        M -->|False| O["spans.update(end kwargs)"]
    end

    subgraph harness ["Unified harness surface (AGX1-375)"]
        P["HarnessTurn"] --> Q["convert_*_to_agentex_events()"]
        Q --> R["SpanDeriver.observe()"]
        R -->|"OpenSpan / CloseSpan"| S["SpanTracer.handle()"]
        S --> T["adk.tracing.start_span / end_span"]
        Q --> U{"Delivery mode"}
        U -->|"Async / Temporal"| V["auto_send() → adk.streaming"]
        U -->|"Sync HTTP ACP"| W["yield_events() → HTTP yield"]
        V --> X["TurnResult"]
        W --> X
    end
Loading

Fix All in Cursor Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
src/agentex/lib/core/tracing/processors/agentex_tracing_processor.py:157-165
**Init-time logger.info fires on every new processor instance**

Both `AgentexSyncTracingProcessor.__init__` and `AgentexAsyncTracingProcessor.__init__` call `logger.info(...)` to announce the skip-start decision. In practice the async processor is re-constructed per event loop (the existing `_build_client` / `WeakKeyDictionary` pattern), so in a high-throughput worker this log line can fire thousands of times. Consider using `logger.debug` or logging once at module load time via a module-level call to `_skip_span_start_enabled()`.

### Issue 2 of 2
src/agentex/lib/adk/_modules/tracing.py:34-42
**Counter object recreated on every drop event**

`workflow.metric_meter().create_counter(...)` is called on every invocation rather than reusing a cached counter. Temporal's SDK recommends creating metric objects once and reusing them — each `create_counter` call allocates a new object and may incur SDK-internal bookkeeping. A simple module-level or class-level cache (e.g. using `functools.lru_cache` or a `_counter` sentinel on the function) would avoid the repeated allocation on busy workflows.

Reviews (1): Last reviewed commit: "chore(sdk): bump agentex-sdk to 0.14.0.d..." | Re-trigger Greptile

declan-scale and others added 13 commits June 22, 2026 15:59
…gModel (#355)

Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
Co-authored-by: Declan Brady <declan.brady@scale.com>
Co-authored-by: Nitesh Dhanpal <NiteshDhanpal@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…est) (#438)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Pre-release version for building a dev wheel off `next` (carries the Temporal
tracing fail-open #437 + Agentex span-start-skip #438 fixes) to vendor into the
rocket_mock_async_agent image ahead of a published 0.14.x. Not intended for
PyPI publish as-is; `.dev0` sorts below a future real 0.14.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

This PR is targeting main, but PRs should target the next branch by default.

The main branch is reserved for release-please and Stainless automation. To resolve, pick one of:

  • Re-target the PR to next (recommended). On the PR page, click Edit next to the title and change the base branch to next.
  • Add the target-main label if this is an intentional exception (e.g. an urgent hotfix). The check will re-run and pass.

See CONTRIBUTING.md for the full branch model.

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.

4 participants