feat: detect all coding agents in user-agent, not just Claude Code#519
Merged
Conversation
Extends agent source tracking beyond CLAUDECODE to the full set of coding agent harnesses, mirroring runpodctl PR #280 and Hugging Face's public agent-harnesses registry so traffic is attributed under the same identifiers across surfaces. - Add runpod/agent.py: ordered harness registry (claude-code, cursor, cursor-cli, codex, gemini-cli, github-copilot, cline, replit, zed, etc.) plus a sanitized generic AI_AGENT fallback. - Wire agent.detect() into construct_user_agent(), replacing the single CLAUDECODE check. Emits "(via <agent>)" as before. - Tests for detection precedence, sanitization, and the user-agent string. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Extends the RunPod Python SDK’s User-Agent agent-source attribution from a single CLAUDECODE check to a broader registry of coding-agent “harness” environment signals, with a generic AI_AGENT fallback to support additional/unknown tools.
Changes:
- Added
runpod/agent.pywith an ordered harness registry,detect()logic, andAI_AGENTsanitization/length cap. - Updated
construct_user_agent()to append(via <agent>)usingagent.detect()rather than only detecting Claude Code. - Added
tests/test_agent.pyand expandedtests/test_user_agent.pyto cover detection precedence, empty handling, sanitization, and non-Claude agent tagging.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
runpod/agent.py |
New module providing agent detection + sanitization and helper APIs. |
runpod/user_agent.py |
Integrates agent detection into the emitted User-Agent string. |
tests/test_agent.py |
New unit tests for registry matching, precedence, and AI_AGENT behavior. |
tests/test_user_agent.py |
Updates UA tests to clear all agent env vars and adds a non-Claude agent case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- user_agent.py: use agent.suffix() instead of re-implementing the "(via <id>)" fragment, so the format lives in one place and cannot drift. - agent.detect(): strip env var values before matching, so a whitespace-only value does not count as detection (aligns harness matching with the docstring and the AI_AGENT path, which already strips). - Add a test for the whitespace-only case. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
KAJdev
approved these changes
Jun 23, 2026
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
Extends agent source tracking in the SDK's User-Agent beyond
CLAUDECODEto the full set of coding-agent harnesses, so traffic from Cursor, Codex, Gemini CLI, Copilot, Cline, Replit, and others is attributed (today everything except Claude Code shows up untagged).The detection registry mirrors runpodctl PR #280 and Hugging Face's public agent-harnesses list so traffic is attributed under the same identifiers across surfaces (MCP, runpodctl, Python SDK).
Changes
runpod/agent.py: an ordered harness registry (claude-code,cursor,cursor-cli,codex,gemini-cli,github-copilot,cline,cowork,replit,zed,goose,kiro, and more), plus a sanitized genericAI_AGENTfallback. First match wins; specific signals (e.g.cursor-cli,cowork) are ordered before broader ones they co-occur with.agent.detect()intoconstruct_user_agent(), replacing the singleCLAUDECODEcheck. The emitted tag format is unchanged:(via <agent>).tests/test_agent.py(detection precedence, empty-value handling,AI_AGENTsanitization + 64-char cap) and updatedtests/test_user_agent.py(now clears all known agent env vars; adds a non-Claude agent case).Test plan
tests/test_agent.pyandtests/test_user_agent.pypass (18 tests)construct_user_agent()emits(via claude-code)when run inside Claude Code🤖 Generated with Claude Code