Skip to main content

Agent Detector

agent-detector is a small, dependency-free Python package for detecting which AI coding agent is driving the current process, and for parsing that identity back out of a User-Agent header on the receiving side.

It returns evidence rather than only a boolean, so callers can distinguish an explicit identity from a broad environmental hint.

Installation

pip install agent-detector

Usage

from agent_detector import detect_agent

detection = detect_agent()

if detection:
    print(detection.agent)       # "codex"
    print(detection.confidence)  # "high"
    print(detection.signal)      # "CODEX_THREAD_ID"

The returned DetectionResult contains:

  • agent: an AgentName literal containing a supported agent name
  • confidence: high, medium, or low
  • source: environment, path, or user-agent
  • signal: the name of the matched signal, never its value

Pass a mapping to make detection deterministic in tests:

assert detect_agent({"OPENCODE": "1"}).agent == "opencode"

Require a minimum confidence when broad environmental hints are not useful:

detection = detect_agent(minimum_confidence="high")

minimum_confidence is typed as Literal["high", "medium", "low"] and defaults to "low".

User-Agent propagation

A client can propagate a detected identity to a server as a second User-Agent product. The value must be exactly two whitespace-separated products:

<product>/<version> AI-Agent/<agent>

For example:

example-cli/1.2.3 AI-Agent/codex

The rules are strict and case-sensitive:

  • product and version are both required and must be non-empty RFC 9110 tokens (letters, digits, and !#$%&'*+-.^_`|~; no /, spaces, or parentheses)
  • the marker must be exactly AI-Agent (mirroring the AI_AGENT environment variable)
  • agent must be one of the supported agent names below, in lowercase
  • comments such as (darwin) and additional products are rejected
  • leading and trailing whitespace is ignored

A client can build the value like this:

from agent_detector import detect_agent

user_agent = "example-cli/1.2.3"
if detection := detect_agent(minimum_confidence="high"):
    user_agent += f" AI-Agent/{detection.agent}"

Use parse_invoking_agent on the receiving side. It returns a DetectionResult with confidence="high", source="user-agent", and signal="User-Agent", or None when the value does not match:

from agent_detector import parse_invoking_agent

detection = parse_invoking_agent(
    request.headers.get("user-agent"),
    expected_product="example-cli",
)

if detection:
    print(detection.agent)  # "codex"

expected_product is optional. When given, it must be a non-empty string and only values whose product matches it exactly are accepted; anything else returns None. Use it to ignore unrelated clients that happen to send a similar header. It is a filter, not authentication: as with environment detection, the identity is informational and any HTTP client can send it.

Supported agents

Agent Signals Confidence
Explicit override AI_AGENT containing a supported agent name high
Amp AGENT=amp, AMP_CURRENT_THREAD_ID high / medium
Codex CODEX_THREAD_ID, CODEX_CI, CODEX_SANDBOX high
Gemini CLI GEMINI_CLI high
Copilot CLI COPILOT_CLI medium
OpenCode OPENCODE high
Antigravity ANTIGRAVITY_AGENT medium
Augment CLI AUGMENT_AGENT medium
Cowork CLAUDE_CODE_IS_COWORK high
Claude Code CLAUDE_CODE_CHILD_SESSION, CLAUDECODE, CLAUDE_CODE high / medium
Cursor CURSOR_TRACE_ID medium
Cursor CLI CURSOR_AGENT, CURSOR_EXTENSION_HOST_ROLE=agent-exec high / medium
Grok GROK_SESSION_ID, GROK_AGENT high / medium
Grok Bot CURSOR_AGENT + SAND_BOX_BOOT_ID + SAND_BOX_STORE_ID (all required) high
Kiro TERM_PROGRAM=kiro low
Pi .pi/agent entry in PATH medium
Replit REPL_ID low
Goose GOOSE_PROVIDER low

AI_AGENT takes precedence over inferred signals when its value is one of the supported agent names. Unknown values are ignored.

The detector is deliberately ordered. For example, Amp is checked before Claude Code because Amp also sets CLAUDECODE, and Grok Bot is checked before Cursor CLI because it also sets CURSOR_AGENT.

Important limitations

Detection is best-effort. None means unattributed, not "human". Some signals can also be present in an integrated terminal where a person typed the command manually.

This package detects the execution harness. It cannot determine whether a particular skill, plugin, prompt, or model caused the command. Use a separate explicit marker when that attribution matters.

Neither environment detection nor the User-Agent format verifies the caller. Do not use a detected identity to grant access or bypass checks.

Privacy

Environment values such as thread IDs are never returned. A result contains only a normalized agent name and the name and category of the matched signal. parse_invoking_agent likewise returns only the agent name, never the client product, version, or the raw header.

Development

uv sync --all-groups
uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest
uv build

Metadata

Release files for agent-detector 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-detector 2.0.0
File Size Uploaded Provenance Actions
agent_detector-2.0.0.tar.gz 55.1 kB Without provenance Details for agent_detector-2.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for agent-detector 2.0.0
File Interpreter ABI Platform Actions
agent_detector-2.0.0-py3-none-any.whl Python 3 none any Details for agent_detector-2.0.0-py3-none-any.whl

Total release size: 64.4 kB

Release files / agent_detector-2.0.0.tar.gz

Download URL agent_detector-2.0.0.tar.gz
Size 55.1 kB
Tags Source
SHA-256 checksum
How to use checksums
19c8ae185dbdca23c24abdcd8ac2cf58b8e84dc284c6f6db536656601f9ffc3f
BLAKE2b-256 checksum
How to use checksums
b3922c3e2ad5ce9683876729034082af19cfb3fbafd1c298b22a0b0c10ecfdc5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / agent_detector-2.0.0-py3-none-any.whl

Download URL agent_detector-2.0.0-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
22c6a1c9c23894a12f55aea625f060b8d3330fba774de72d02d5442bb580417f
BLAKE2b-256 checksum
How to use checksums
7215504337e302d070bd2ff2f39418bb17d2ad73c662c403a4f37cb4e5c5b237
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for agent-detector 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page