Record agentic invocations in User-Agent header#13023
Conversation
| ) | ||
|
|
||
| const ( | ||
| accept = "Accept" |
c1daf35 to
d1a2ae7
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds lightweight agent detection (via well-known environment variables) and threads the detected agent name into API client construction so that gh includes an Agent/<name> suffix in the User-Agent header for GitHub API requests, improving visibility into agentic CLI usage.
Changes:
- Introduces
internal/agentswithDetect()plus tests for supported agent environment variable signals and precedence. - Extends factory and HTTP client plumbing to pass an
invokingAgentvalue intoapi.NewHTTPClient, appending it to theUser-Agent. - Updates call sites and tests for the new factory/HTTP client function signatures.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
internal/agents/detect.go |
Adds agent detection + validation for AI_AGENT values. |
internal/agents/detect_test.go |
Adds unit tests covering detection signals and precedence. |
internal/ghcmd/cmd.go |
Wires detected agent into factory creation at CLI entrypoint. |
api/http_client.go |
Adds InvokingAgent option and appends it to User-Agent. |
api/http_client_test.go |
Adds test asserting agent suffix is included in User-Agent. |
pkg/cmd/factory/default.go |
Threads invokingAgent through factory into HTTP client options. |
pkg/cmd/factory/default_test.go |
Updates factory constructor usage for new parameter. |
pkg/cmd/search/shared/shared_test.go |
Updates factory constructor usage for new parameter. |
pkg/cmd/attestation/verify/verify_integration_test.go |
Updates factory constructor usage for new parameter. |
api/client.go |
Removes an unused header constant. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ua := fmt.Sprintf("GitHub CLI %s", opts.AppVersion) | ||
| if opts.InvokingAgent != "" { | ||
| ua = fmt.Sprintf("%s Agent/%s", ua, opts.InvokingAgent) | ||
| } |
There was a problem hiding this comment.
opts.InvokingAgent is appended to the User-Agent verbatim. If a future caller passes an untrusted/unsanitized value (e.g. containing \r/\n or other invalid header characters), requests can fail with "invalid header field value" and this undermines the stated header-injection hardening. Consider validating/sanitizing opts.InvokingAgent inside NewHTTPClient (e.g. allow only [A-Za-z0-9_-]+ and otherwise omit the agent suffix), and add a small test for the invalid-value case.
There was a problem hiding this comment.
Nah we sanitize at the agent layer. I don't want to create a gh.AgentName just to deal with this.
| agentOpencode AgentName = "opencode" | ||
| ) | ||
|
|
||
| var validAgentName = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`) |
There was a problem hiding this comment.
Maybe also dots, slashes (/ and ), and brackets? As some agent may decide to add versions (in brackets).
There was a problem hiding this comment.
Purely based on what we've seen so far out in the wild, I'm inclined to leave this alone until we see something otherwise.
Detect which AI coding agent is invoking gh by checking well-known environment variables and include the agent name in the User-Agent header sent to GitHub APIs. Supported agents: Codex, Gemini CLI, Copilot CLI, OpenCode, Claude Code, and Amp. Generic AI_AGENT env var is also supported with validation to prevent header injection. Fixes github/cli#1111 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
d1a2ae7 to
c51769c
Compare
|
Bypassing package security review cause it's not that interesting. |
Description
There has been a significant increase in agentic use of
ghin the last few months and it's important we are able to identify that usage. This PR tries to detect which agent is invokingghby checking well-known environment variables and includes the agent name in theUser-Agentheader sent to GitHub APIs.Supported agents: Codex, Gemini CLI, Copilot CLI, OpenCode, Claude Code, and Amp. The generic
AI_AGENTenv var is also supported with validation ([a-zA-Z0-9_-]) to prevent header injection.Format
Acceptance Criteria
Given I set
GH_DEBUG=apiin the environmentWhen I invoke
ghin a shell tool in Claude Code CLI, Gemini CLI, Codex CLI, Copilot CLI, Amp, or OpenCodeThen I see that the
User-Agentheader in http requests contains the agent nameRunning in
copilotCLI:Given I set
GH_DEBUG=apiin the environmentWhen I invoke
ghdirectly (in copilot CLI, run withCOPILOT_CLIunset in the environment)Then I see that the
User-Agentheader in http requests does not contain an agent nameRunning in shell: