feat: log AI coding agents in user-agent, telemetry, and tracing#550
feat: log AI coding agents in user-agent, telemetry, and tracing#550mwbrooks wants to merge 10 commits into
Conversation
When the Slack CLI is invoked by an AI coding agent (Claude Code, Codex, Gemini CLI, Cline, Cursor, Goose, Amp, or others), detect the agent via environment variables and append an AI-Agent product token to the HTTP user-agent header. Also propagates the agent name to telemetry events and Jaeger tracing spans. User-Agent format: slack-cli/2.38.1 (os: darwin) AI-Agent (name=claude-code, entry=cli)
Removes duplicate detectAIAgentName/detectAgentName helpers from main.go and tracking.go in favor of useragent.DetectName().
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #550 +/- ##
==========================================
+ Coverage 71.64% 71.66% +0.01%
==========================================
Files 225 226 +1
Lines 19074 19104 +30
==========================================
+ Hits 13665 13690 +25
- Misses 4202 4207 +5
Partials 1207 1207 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
mwbrooks
left a comment
There was a problem hiding this comment.
Comments for the kind reviewers! 🖊️
| rootCmd.SetContext(ctx) | ||
| // Debug logging | ||
| clients.IO.PrintDebug(ctx, "system_id: %s", clients.Config.SystemID) | ||
| clients.IO.PrintDebug(ctx, "user_agent: %s", useragent.BuildUserAgent(version.Raw())) |
There was a problem hiding this comment.
note: This is a new addition to our verbose logs. For a while, I've wanted to see our user-agent which is used for each API request. This may also be helpful when diagnosing user reported issues.
| span.SetTag("hashed_hostname", ioutils.GetHostname()) | ||
| span.SetTag("slack_cli_process", processName) | ||
| if agentName := useragent.DetectName(); agentName != "" { | ||
| span.SetTag("ai_agent", agentName) |
There was a problem hiding this comment.
note: I chose ai_agent instead of agent because it's less ambiguous and more specific that it's an AI "agent".
|
|
||
| // EventContext contains information / metadata about the CLI session | ||
| type EventContext struct { | ||
| AIAgent string `json:"ai_agent,omitempty"` |
There was a problem hiding this comment.
note: I chose ai_agent instead of agent because it's less ambiguous and more specific that it's an AI "agent".
| ua := fmt.Sprintf("slack-cli/%s (os: %s)", cliVersion, runtime.GOOS) | ||
| if agent := Detect(); agent != nil { | ||
| var parts []string | ||
| parts = append(parts, "name="+agent.Name) |
There was a problem hiding this comment.
| parts = append(parts, "name="+agent.Name) | |
| parts = append(parts, "name: "+agent.Name) |
☎️ question: A ":" separator might match the os adjacent but I understand can make queries more difficult. If this was intentional please ignore but I did want to ask?
| // BuildUserAgent constructs the HTTP User-Agent header value for the CLI. If an | ||
| // AI agent is detected, an "AI-Agent (name=..., entry=...)" suffix is appended. |
There was a problem hiding this comment.
📚 quibble: It'd be helpful to have a full example here but no blocker!
|
|
||
| // DetectName returns the normalized name of the detected AI agent, or an empty | ||
| // string if no agent is detected. | ||
| func DetectName() string { |
There was a problem hiding this comment.
| func DetectName() string { | |
| func DetectHarness() string { |
🪬 question: Forgive these words but this is an unusual export for the value found I think but I also admit to not being so familiar with practices encouraged here!
There was a problem hiding this comment.
🌃 ramble: It does seem solid if we're framing this as the... actual user agent though? I'm understanding more I hope!
Changelog
Summary
This pull request adds detection of AI coding agents and surfaces the detected agent across HTTP requests, telemetry, and tracing.
Format:
slack-cli/v4.0.1 (os: darwin) AI-Agent (name=claude-code, entry=cli)slack-cli/v4.0.1 (os: darwin) AI-Agent (name=claude-code, entry=desktop)slack-cli/v4.0.1 (os: darwin) AI-Agent (name=codex)Analytics:
name=.entry=) but it's very limited today.Detected AI agents environment variables:
CLAUDECODE→claude-codeCLAUDE_CODE_ENTRYPOINT→cliordesktopor possibly evenvscodeCODEX_CI→codexGEMINI_CLI→gemini-cligeminiif we want, but since the env var is specific the CLI we may want to take advantage of thatCLINE_ACTIVE→clineCURSOR_AGENT→cursorAGENTWhen detected:
AI-Agent (name=<name>, [entry=<entrypoint>])additionagentfield in the contextai_agentspan tagTesting
Requirements