Skip to content

feat(agent): identify Go SDK traffic in user agent - #7

Merged
LukasParke merged 1 commit into
mainfrom
feat/user-agent-go-agent
Aug 26, 2026
Merged

feat(agent): identify Go SDK traffic in user agent#7
LukasParke merged 1 commit into
mainfrom
feat/user-agent-go-agent

Conversation

@LukasParke

Copy link
Copy Markdown
Contributor

Appends the go-agent module path to the generated SDK's User-Agent so agent traffic is distinguishable from plain go-sdk traffic.

speakeasy-sdk/go 0.5.4 2.879.6 1.0.0 github.com/OpenRouterTeam/go-sdk github.com/OpenRouterTeam/go-agent/0.8.0

Behavior

  • The token is resolved once in NewOpenRouter via debug.ReadBuildInfo(), checking the main module then deps. A consumer build yields github.com/OpenRouterTeam/go-agent/<version>; a (devel) or version-less build yields the bare module path.
  • The header is set before the before-request hooks run, so caller middleware that rewrites User-Agent still wins.
  • Appending is idempotent — a retried *http.Request does not accumulate duplicate tokens.

Language-specific identity

.upstreamer/upstreamer.md gains divergence #7: Go appends the module path, TypeScript the npm package name (@openrouter/agent), Python the PyPI distribution name (openrouter-agent-sdk). The porting automation must not converge this token toward the TypeScript literal.

Tests

Four unit tests cover append, idempotence, caller override, and agentUserAgentTokenFromBuildInfo across five build-info shapes.

Added on top of the original patch: TestNewOpenRouterSendsAgentUserAgentOnTheWire. The four unit tests construct middlewareClient directly with a hardcoded token, so none of them exercise NewOpenRouter's wiring or prove the header survives the full SDK path. The new test drives NewOpenRouter through CallModel against a recording transport and asserts the agent token arrives last with the generated SDK token preserved.

Mutation-checked for teeth: deleting the req.Header.Set in Do fails both it and the unit test. Note that removing agentToken: agentUserAgentToken() from NewOpenRouter does not fail anything — Do's if agentToken == "" fallback recomputes it, so the constructor assignment is a per-request optimization rather than a correctness path.

Verification

gofmt -l .                                    clean
go build ./... / go vet ./...                 pass
go test -race -shuffle=on -count=1 ./...      pass
staticcheck ./...                             clean
.upstreamer/scripts/verify.sh                 PASS: 0 failures (coverage 72.4% >= 72.0%)
env -u OPENROUTER_API_KEY go test -run TestE2E  SKIP (not fail)

Append the go-agent module path (and version, when the build carries one)
to the generated SDK's User-Agent so agent traffic is distinguishable from
plain go-sdk traffic. Caller middleware still wins: the token is set before
the before-request hooks run, so a hook that rewrites User-Agent overrides it.

Adds a wire-level regression test that drives NewOpenRouter through
CallModel and asserts the token reaches the transport, covering the
constructor wiring the unit tests bypass.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LukasParke
LukasParke merged commit a364988 into main Aug 26, 2026
4 checks passed
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.

1 participant