Skip to content

Force-flush trace spans before the A2A response completes for substrate#2176

Open
iplay88keys wants to merge 11 commits into
mainfrom
iplay88keys/substrate-updates
Open

Force-flush trace spans before the A2A response completes for substrate#2176
iplay88keys wants to merge 11 commits into
mainfrom
iplay88keys/substrate-updates

Conversation

@iplay88keys

@iplay88keys iplay88keys commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Description

Agent Substrate checkpoints an actor as soon as its A2A response completes. Spans still buffered by OpenTelemetry's BatchSpanProcessor at that point remain frozen until the actor resumes, or can be lost when the snapshot does not preserve process state. This makes the session's latest trace delayed or missing.

The flush must happen after HTTP instrumentation ends the inbound server span, but before the terminal response message triggers checkpointing. Flushing from the agent executor is too early because the server span is still open.

Changes

Go ADK

  • Add telemetry.ForceFlush(ctx) to flush providers that support it.
  • Wrap the instrumented A2A handler so flushing happens after the otelhttp server span ends and before ServeHTTP returns.
  • Use a detached timeout because the request context may already be canceled.
  • Skip health and agent-card requests.

Python ADK

  • Add kagent.core.tracing.force_flush().
  • Wrap the FastAPI ASGI stack and hold only the terminal response body or trailer message.
  • Let the instrumented application return and end its server span, flush in a worker thread, then send the held terminal message.
  • Skip health, thread-dump, and agent-card requests.

Both implementations default to a 3-second flush timeout, configurable with KAGENT_TRACE_FLUSH_TIMEOUT_MS. Unsupported tracer providers are a no-op, and exporter failures do not fail the A2A response. Streaming response chunks are unaffected; only response completion waits for the bounded flush.

Helm image helpers

  • Include the optional image.name segment in the grafana-mcp and querydoc image helpers.
  • Preserve existing two-segment image references when image.name is unset.

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
@iplay88keys
iplay88keys marked this pull request as ready for review July 7, 2026 21:12
@iplay88keys
iplay88keys requested review from a team and supreme-gg-gg as code owners July 7, 2026 21:12
Copilot AI review requested due to automatic review settings July 7, 2026 21:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ensures OpenTelemetry spans are force-flushed before an A2A response completes on Agent Substrate (to avoid buffered spans being checkpoint-frozen and exported only on the next resume), and updates Helm helper templates to optionally include an image.name segment when constructing image references.

Changes:

  • Add Go telemetry.ForceFlush(ctx) and invoke it after the root invocation span ends in the Go A2A executor.
  • Add Python kagent.core.tracing.force_flush() and invoke it at the end of the Python ADK executor via asyncio.to_thread to avoid blocking the event loop.
  • Update grafana-mcp and querydoc Helm image helpers to include an optional image.name segment in the image path.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/packages/kagent-core/tests/test_tracing_configure.py Adds unit tests for the new Python tracing force-flush helper behavior.
python/packages/kagent-core/src/kagent/core/tracing/_utils.py Introduces force_flush() to flush buffered spans with a bounded timeout and swallow exporter errors.
python/packages/kagent-core/src/kagent/core/tracing/init.py Exports force_flush from the tracing package public API.
python/packages/kagent-adk/src/kagent/adk/_agent_executor.py Calls tracing force-flush in execute() cleanup using asyncio.to_thread.
helm/tools/querydoc/templates/_helpers.tpl Extends image reference construction to include optional image.name.
helm/tools/grafana-mcp/templates/_helpers.tpl Extends image reference construction to include optional image.name.
go/adk/pkg/telemetry/tracing.go Adds ForceFlush helper that detaches from request cancellation and flushes spans with a 3s timeout.
go/adk/pkg/telemetry/tracing_test.go Adds test ensuring buffered spans are exported on flush and that no-op providers don’t panic.
go/adk/pkg/a2a/executor.go Flushes spans after ending the invocation span in deferred executor cleanup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread python/packages/kagent-adk/src/kagent/adk/_agent_executor.py Outdated
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
…-updates

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Comment thread python/packages/kagent-adk/src/kagent/adk/_agent_executor.py Outdated
Comment thread go/adk/pkg/a2a/executor.go Outdated
Comment thread go/adk/pkg/telemetry/tracing.go Outdated
…t configurable

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
…-updates

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Comment thread go/adk/pkg/a2a/server/server.go Outdated
Comment thread go/adk/pkg/a2a/executor.go Outdated
Comment thread go/adk/pkg/a2a/server/server.go
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
…-updates

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
EItanya pushed a commit that referenced this pull request Jul 20, 2026
# Description

Raises the minimum supported Python version from 3.10 to 3.11 across the
Python workspace. `kagent-adk` already calls `asyncio.Task.uncancel()`
(added in Python 3.11) in its A2A agent executor (#2176), so 3.10 was
broken in practice; this makes the declared floor match. 3.10 also
reaches [end of life](https://devguide.python.org/versions/) in October
2026.

- `requires-python`: `>=3.10` → `>=3.11` in all 15 workspace pyprojects
(root, packages, samples). The existing `<3.14` caps on the crewai
packages are unchanged.
- ruff/black `target-version`: `py310` → `py311` where set.
- CI: `python-test` matrix drops 3.10 (now 3.11/3.12/3.13);
`python-lint` installs 3.11.
- `uv.lock` regenerated: removes `async-timeout`, `exceptiongroup`, and
`backports-asyncio-runner` (3.10-only stdlib backports) and collapses
the numpy 2.2.6/2.3.2 split resolution to 2.3.2 only.
- Removes the now-dead `from datetime import UTC` try/except 3.10
fallbacks in `kagent-langgraph` and `kagent-openai` (ruff UP017 flags
them at the py311 target; its autofix mangles the fallback branch, so
they are deleted instead). The `typing.override` fallbacks stay — those
need 3.12.
- CLI Python scaffolding template
(`go/core/cli/internal/mcp/frameworks/python/templates/pyproject.toml.tmpl`):
ruff/black `target-version` and mypy `python_version` bumped
`py310`/`3.10` → `py312`/`3.12` to match the template's own
`requires-python = ">=3.12"`.

## Test plan

- CI `python-test` matrix (3.11–3.13) runs the full test suite.
- `uv lock` resolves cleanly (272 packages).

---------

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>

@krisztianfekete krisztianfekete left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we gate this to substrate only?

Comment thread python/packages/kagent-core/src/kagent/core/tracing/_utils.py Outdated
…-updates

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
…ubstrate actors only

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
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