Repository navigation
fix(a2a): trace Go server calls through official SDK hooks - #478
Merged
Merged
Conversation
Co-Authored-By: Claude Code <noreply@anthropic.com>
Keep unary status-message capture independent of stream termination. Require a2a-go v2.7.0 so required-extension rejections run completion hooks, with regression and OTLP privacy coverage. Co-Authored-By: Claude Code <noreply@anthropic.com>
Finalize each server call from its context-local state instead of the SDK shared mutable method. Shadow inherited state for untraced nested calls so their responses cannot finish the outer span. Co-Authored-By: Claude Code <noreply@anthropic.com>
Wrap response-rejecting middleware so tracing sees its actual error before the SDK short-circuits remaining callbacks. Preserve policy ordering, response mutation and error identity, with real SDK, nested-call and OTLP regression coverage. Resolve exporter dependencies in the setup instructions. Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Derive error-detail hiding from content flags with an explicit override. Add maintained client and handler completion wrappers because SDK interceptors do not receive iterator EOF; keep active auth-required streams open and distinguish early abandonment. Cover privacy on actual OTLP exports and completion across all three transports. Co-Authored-By: Claude Code <noreply@anthropic.com>
Keep the legacy auth-required completion boundary only for client calls without their own stream-completion hook. Wrapped clients and server streams continue recording active authorization streams. Cover both client APIs across transports and nested completion-slot ownership. Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
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
Add a maintained Go server interceptor so an A2A receiving agent continues the caller's trace without application-owned propagation code.
NewServerInterceptorimplements the officiala2asrv.CallInterceptorhook for the same five protocol methods as the existing client interceptor, across JSON-RPC, REST and gRPC. Existing client entry points remain unchanged.CallContext.Method. Untraced nested methods cannot end an outer span or replace its output.ServerInterceptor.Wrapfor response-rejecting middleware. The SDK skips remainingAfterhooks when middleware returns an error; the adapter records that error and completes the server span before returning it unchanged. It preserves callback ordering and response mutations, without creating another span. Register tracing first, then wrap each interceptor that can return anAftererror.WrapClient/WrapHandlercompletion wrappers for clean EOF (including persisted nonterminal snapshots) and early abandonment. Wrapped clients and server spans stay open across activeauth-requiredevents. Existing interceptor-only clients retain their historical successful completion at anauth-requiredtask or status event, so persisted authorization snapshots do not require a client migration. UseWrapClientto capture events after authorization and observe iterator completion; bare SDK hooks have no EOF callback. Each call must own its completion slot: nested unwrapped calls cannot borrow an outer wrapper. The wrappers complete existing spans without adding spans or changing events/errors. The latest snapshot/status message is retained subject to output redaction; a later status clears stale authorization text.FI_HIDE_ERROR_DETAILSandTraceConfig.HideErrorDetails(optional*bool) on client and server spans. Without an explicit override, input/output, message and text hiding derive error-detail hiding. Explicit false overrides derivation; true removes error text and status descriptions while retaining error class and ERROR status. Constructor options are snapshotted.Verification
Real SDK tests cover all three transports and direct calls, parent chains, streams, task operations, protocol/middleware rejections, disconnects, redaction and nested calls. Response-policy regressions assert that rejected payloads are not captured, earlier policy callbacks remain skipped, and the original error is retained. Removing rejection observation makes the regression tests fail.
The two independent review findings were reproduced before repair on both toolchains: error text reached actual OTLP protobuf despite the privacy flag, and successful persisted auth snapshots remained open or became canceled errors. Both have committed regression coverage. The follow-up interceptor-only compatibility finding was also reproduced on both toolchains before repair. Its unchanged independent public-API reproduction passes 20 race-enabled repetitions per toolchain after repair. Committed tests exercise interceptor-only and wrapped clients against an uninstrumented official server over JSON-RPC, REST and gRPC, plus task/status events on both streaming methods and owned, absent, already-claimed, mismatched and server-only completion slots.
All 416 tests (including subtests; 59 top-level) pass with the race detector on Go 1.26.0 and 1.27.3. The supported minimum and current SDK release are both v2.7.0, not two distinct SDK versions. The privacy/completion/response-policy regressions pass 20 repeated race-enabled runs per toolchain. Tests cover true/false/derived/invalid privacy settings, code precedence, error classes, actual wire payloads, active auth streams, snapshot EOF, early abandonment, empty iterators, errors, panic propagation, context cancellation/deadlines, iterator reuse and duplicate-wrapper safety. Package checks include tidy, verify, vet, the example build, committed-module archives and the release plan. The latest dev base was normally merged; frozen-lockfile TypeScript installation with scripts disabled also passes. Fresh consumers compile the documentation snippets from the install commands without inherited sums or a corrective tidy. Loopback OTLP tests cover protobuf plain/gzip and Collector-encoded JSON plain/gzip; the stock Go exporter itself emits protobuf.
No package-version or changelog edits. The docs-site update remains held until this API is released and should be folded into existing docs PR #969 rather than duplicated.
Generated with Claude Code