Skip to content

Add AI agent detection to user-agent string#701

Open
simonfaltum wants to merge 5 commits intomainfrom
simonfaltum/agent-detection
Open

Add AI agent detection to user-agent string#701
simonfaltum wants to merge 5 commits intomainfrom
simonfaltum/agent-detection

Conversation

@simonfaltum
Copy link
Member

@simonfaltum simonfaltum commented Mar 12, 2026

Summary

  • Detect known AI coding agents via environment variables and append agent/<name> to the HTTP user-agent header
  • Canonical agent list: Antigravity (ANTIGRAVITY_AGENT), Claude Code (CLAUDECODE), Cline (CLINE_ACTIVE), Codex (CODEX_CI), Copilot CLI (COPILOT_CLI), Cursor (CURSOR_AGENT), Gemini CLI (GEMINI_CLI), OpenCode (OPENCODE)
  • Returns empty string when zero or multiple agents are detected (ambiguity guard)
  • Uses the same double-checked locking pattern as existing CI/CD detection
  • Part of a cross-SDK effort (Go SDK PR #1537, Python SDK PR #1327)

The COPILOT_CLI env var was confirmed by direct testing in Copilot CLI.

Test plan

  • Unit test for each of the 8 agents individually
  • Test: no agent env vars set produces no agent/ segment
  • Test: multiple agent env vars set produces no agent/ segment
  • Test: empty env var value produces no agent/ segment
  • Test: cached value persists after environment change
  • mvn spotless:apply passes
  • mvn -Dtest=UserAgentTest test passes

This pull request was AI-assisted by Isaac.

Detect known AI coding agents (Claude Code, Cursor, Cline, Codex,
Gemini CLI, OpenCode, Antigravity) via environment variables and
append agent/<name> to the user-agent header. Uses the same
double-checked locking pattern as CI/CD detection. Returns empty
when zero or multiple agents are detected (ambiguity guard).

Co-authored-by: Isaac
Move cleanupAgentEnv() to an @AfterEach tearDown method so test
isolation is failure-safe. Previously, if an assertion failed before
the manual cleanup call, static state would leak between tests.

Co-authored-by: Isaac
Copy link
Member Author

@simonfaltum simonfaltum left a comment

Choose a reason for hiding this comment

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

Review (automated, 2 agents)

Verdict: Approved

0 Critical | 0 Major | 2 Gap | 2 Nit | 1 Suggestion

See inline comments for details.

@simonfaltum
Copy link
Member Author

[Gap (Nit)] Existing cicd tests now depend on @AfterEach for agentProvider reset

The PR removes manual UserAgent.env = null cleanup from the three existing cicd tests and relies on @AfterEach. The cicd tests' setup doesn't reset agentProvider, creating implicit coupling.

Suggestion: Add UserAgent.agentProvider = null to existing cicd tests' setup for consistency.

@simonfaltum
Copy link
Member Author

[Gap (Nit)] Missing test that cicd and agent coexist in user-agent string

The PR adds agent detection alongside CI/CD detection, but no test asserts both segments are present together.

Suggestion: Add a test with one CI/CD env var and one agent env var set, then assert both cicd/... and agent/... appear.

Replace AbstractMap.SimpleEntry with AgentDef inner class to match
the CicdProvider/EnvVar style. Add early exit in lookupAgentProvider
when count > 1. Remove redundant null check for agentProvider()
return value to match cicdProvider() pattern.

Co-authored-by: Isaac
@simonfaltum simonfaltum marked this pull request as ready for review March 12, 2026 13:56
We have data from direct testing in Copilot CLI confirming it sets
COPILOT_CLI=1 in its environment. Add it to the canonical agent list.

Co-authored-by: Isaac
@github-actions
Copy link

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/sdk-java

Inputs:

  • PR number: 701
  • Commit SHA: 9fd21275fae65449f15e77ecd515ff982d677cab

Checks will be approved automatically on success.

@simonfaltum simonfaltum deployed to test-trigger-is March 13, 2026 16:15 — with GitHub Actions Active
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