Coding-Agent Telemetry
AI coding agents export OpenTelemetry (OTLP) data. ANTS Platform ingests it and builds one trace per prompt, grouped into sessions and attributed to a user. Each trace carries the model, token counts, cost and tool calls.
ANTS Platform has dedicated parsers for three coding agents that export OTLP natively:
- Claude Code
- GitHub Copilot CLI
- OpenAI Codex CLI
Content capture is opt-in and off by default. Without the content settings, each tool sends usage metadata only: counts, models, durations and tool names. Prompt and response text is sent only after you turn on the content setting for that tool. One exception: Codex CLI always sends tool arguments and tool output (see the Codex CLI notes).
Two ways to set it up
| Method | Best for | What you do |
|---|---|---|
| Automatic | Devices enrolled in Discover AI | Run the Discover AI enrollment script. It detects the coding agents on the device and configures them. |
| Manual | Individual developers, or devices without the enrollment script | Set the environment variables or config file shown under Manual setup. |
How it works
Each tool exports OTLP over HTTP to one ingest endpoint, authenticated with a project key pair. ANTS Platform detects which tool sent the data and parses it into traces.
| Value | |
|---|---|
| Endpoint (base) | https://<your-ants-host>/api/public/otel |
| Signal paths | /v1/traces and /v1/logs (most exporters append these to the base) |
| Content types | application/x-protobuf or application/json; gzip is accepted |
| Auth | HTTP Basic with a project public key and secret key |
Authentication
Use a project public key (pk-ap-...) and secret key (sk-ap-...). Project API
keys are under Settings > API Keys. The Discover AI project keys under
Settings > Deployment & Keys also work.
Join the two keys with a colon and Base64-encode the result:
Send the value as an Authorization: Basic header:
The secret key grants ingest access to your project. Distribute it through managed configuration, not shared documents or repositories.
Automatic setup with the enrollment script
The Discover AI enrollment script (macOS and Windows) configures coding-agent telemetry as part of enrollment. See Deploying Agents & Extensions.
- It detects each tool by its configuration folder in the user's home
directory (
.claude,.copilotor thecopilotcommand,.codex). - Claude Code and Copilot CLI: it writes the OTLP endpoint, headers and
user.idinto a marked block in~/.zshenvon macOS, or into the user's environment variables on Windows. - Codex CLI: it writes a marked
[otel]block into~/.codex/config.tomlwithtrace_exporter = "none". If the file already has an[otel]section that ANTS did not write, the script leaves it unchanged. - It sets
user.idto the user's email when the script can resolve one. - On projects that use device certificates, the tools send to a local relay run by the desktop agent, which forwards the data with the device certificate. No secret key is written into the tool configuration.
- Re-running the script replaces its own block. The uninstall script removes it.
Turn on content capture
Content capture is set per project, per tool, under Settings > Deployment & Keys > Coding-agent telemetry > Capture content. All three tools are off by default. The setting is applied the next time the enrollment script runs on a device.
| Tool | What the enrollment script adds when content capture is on |
|---|---|
| Claude Code | OTEL_LOG_USER_PROMPTS=1, OTEL_LOG_TOOL_DETAILS=1, OTEL_LOG_TOOL_CONTENT=1 |
| GitHub Copilot CLI | OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true |
| OpenAI Codex CLI | log_user_prompt = true (otherwise false) |
User attribution
ANTS Platform attributes each trace to a user from the resource attribute
user.id. It also accepts enduser.id and user.account_id.
Set user.id, not user.email. A resource-level user.email is ignored
as an override, so a stale value in a shell profile cannot replace a tool's own
login identity.
| Tool | Identity the tool sends | How to get a readable user |
|---|---|---|
| Claude Code | user.email from the Claude login, on every span | Automatic. Set user.id only to override. |
| OpenAI Codex CLI | user.email and user.account_id from the ChatGPT login, on every event | Automatic. Set user.id only to override. |
| GitHub Copilot CLI | Only enduser.pseudo.id, a non-reversible hash | Set user.id=<email>. Without it, traces are attributed to the hash. |
Manual setup
Set the values for each coding agent you use. Add environment variables to your
shell profile (~/.zshrc or ~/.bashrc). For fleet rollout without the
enrollment script, see Enterprise MDM rollout.
Set OTEL_SERVICE_NAME per tool. If OTEL_SERVICE_NAME="claude-code" is
exported in a shell, any other agent started from that shell inherits it and
can be attributed to the wrong tool. Run each agent in its own shell, or set
OTEL_SERVICE_NAME for each tool as shown below.
Claude Code reads standard OTEL_* environment variables.
Optional content capture. Leave these unset to send metadata only:
Assistant response text arrives only through OTEL_LOG_RAW_API_BODIES.
Extended thinking is always redacted by Claude Code. Restart the terminal or
Claude Code session after changing the variables.
Other tools
- Claude Cowork: ANTS Platform also parses Claude Cowork OTel log events
sent to
/api/public/otel/v1/logswith the same Basic auth header. - Gemini CLI and Cursor have no dedicated parser. Gemini CLI cannot attach an auth header to its OTLP export, and Cursor has no native OpenTelemetry export.
Planned capabilities are listed on the roadmap.
What each tool can export
Some fields are never sent by a tool. In those cases the trace shows a
[<Field> not exported by <Tool>] placeholder. This is expected and is not an
ingestion error.
| Field | Claude Code | Copilot CLI | Codex CLI |
|---|---|---|---|
| User prompt | ✓ with OTEL_LOG_USER_PROMPTS | ✓ with the content variable | ✓ with log_user_prompt |
| Assistant text | ✓ with OTEL_LOG_RAW_API_BODIES (thinking redacted) | ✓ with the content variable | ✗ never sent |
| Tool name | ✓ | ✓ | ✓ |
| Tool arguments | ✓ with OTEL_LOG_TOOL_DETAILS | ✓ with the content variable | ✓ always sent |
| Tool result | ✓ with OTEL_LOG_TOOL_CONTENT | ✓ with the content variable | ✓ always sent |
| Model, tokens, cost | ✓ | ✓ | ✓ |
Environment variable reference
| Tool | Key | Value |
|---|---|---|
| Claude Code | CLAUDE_CODE_ENABLE_TELEMETRY | 1 |
| Claude Code | CLAUDE_CODE_ENHANCED_TELEMETRY_BETA | 1 (enables the span view) |
| Claude Code | OTEL_TRACES_EXPORTER / OTEL_LOGS_EXPORTER / OTEL_METRICS_EXPORTER | otlp |
| Claude Code | OTEL_LOG_USER_PROMPTS / OTEL_LOG_TOOL_DETAILS / OTEL_LOG_TOOL_CONTENT | 1 to capture content; unset for metadata only |
| Claude Code | OTEL_LOG_RAW_API_BODIES | 1 to capture assistant response text |
| Copilot CLI | COPILOT_OTEL_ENABLED | true |
| Copilot CLI | COPILOT_OTEL_ENDPOINT | https://<your-ants-host>/api/public/otel |
| Copilot CLI | OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT | true to capture content; unset for metadata only |
| Codex CLI | [otel] table in ~/.codex/config.toml | log_user_prompt, trace_exporter = "none", logs exporter |
| Claude Code, Copilot CLI | OTEL_EXPORTER_OTLP_ENDPOINT | https://<your-ants-host>/api/public/otel |
| Claude Code, Copilot CLI | OTEL_EXPORTER_OTLP_HEADERS | Authorization=Basic <base64(pk:sk)> |
| Claude Code, Copilot CLI | OTEL_SERVICE_NAME | claude-code or github-copilot |
| All | OTEL_RESOURCE_ATTRIBUTES | deployment.environment=production,user.id=<email> |
Verify it's working
Confirm the configuration
Generate activity
Run a prompt in the tool, for example a question in Claude Code or a Codex command that calls a tool.
Check ANTS Platform
Each prompt appears as its own trace within a minute or two. Traces are grouped on the Sessions tab and attributed on Users.
Troubleshooting
Nothing shows up
- Is the endpoint reachable? An unauthenticated POST returns
401, not404:Abashcurl -s -o /dev/null -w "%{http_code}\n" -X POST \ -H "Content-Type: application/json" --data '{}' \ https://<your-ants-host>/api/public/otel/v1/logs404means the host or path is wrong. The base path is/api/public/otel. 401errors? Check the Base64pk:skvalue and that the keys belong to the right project.- Everything shows as Claude Code? A stale
OTEL_SERVICE_NAME=claude-codeis set in the shell. Set it per tool or use a fresh shell.
Codex creates many extra traces
Set trace_exporter = "none" and keep only the logs exporter with the
/v1/logs path.