Claude OTLP Telemetry Setup
Send Claude Code and Claude Cowork OpenTelemetry logs into AgentKeeper as centralized telemetry evidence. OTLP adds Activity rows, cost and token context, MCP observations, detector findings, and...
Send Claude Code and Claude Cowork OpenTelemetry logs into AgentKeeper as centralized telemetry evidence. OTLP adds Activity rows, cost and token context, MCP observations, detector findings, and investigation context alongside Runtime Shield hooks and MCP Gateway.
For provider-side SaaS audit exports, use the Compliance API connector for the relevant enterprise workspace: Anthropic Compliance API for Claude Enterprise, or OpenAI Compliance API for ChatGPT Enterprise and Codex compliance logs. Compliance API rows are after-the-fact audit evidence, not pre-execution blocking.
What is OTLP telemetry?
Claude Code and Claude Cowork can emit structured OpenTelemetry log records to an OTLP-compatible HTTP collector. AgentKeeper acts as that collector.
Use the base endpoint for Claude Code environment variables:
https://www.agentkeeper.dev/api/v1/otlp
Use the logs endpoint when a UI asks for the exact OTLP logs destination:
https://www.agentkeeper.dev/api/v1/otlp/v1/logs
AgentKeeper attributes events to the sending workstation using hostname and session identity. The events appear in:
- Usage & Costs: per-session token counts, model costs, trend charts
- Workstations: per-developer cost, activity, and baseline context
- Activity:
Claude OTLPandCowork OTLPevidence rows - Investigations: detector findings plus surrounding Claude-reported context
Telemetry is additive: use Runtime Shield hooks and MCP Gateway for pre-execution enforcement, and use OTLP for centralized evidence, usage context, and post-execution detections.
Choose the right setup path
| Deployment | Best path | What you get |
|---|---|---|
| One developer using Claude Code | Shell exports or /agentkeeper:connect --enable-telemetry | Fast validation in Activity and Settings > Connectors > Claude OTLP |
| Fleet using Claude Code | MDM-managed managed-settings.json or native policy | Consistent coverage without developer action |
| Claude Cowork / Claude Desktop org | Claude org Monitoring settings | Centralized Cowork telemetry and investigation evidence |
| ChatGPT Enterprise / Codex audit logs | OpenAI Compliance API connector | Provider-side SaaS audit evidence in Activity and AI Discovery |
| Need pre-execution blocking | Runtime Shield hooks or MCP Gateway | Real allow, warn, and block decisions before execution |
Claude Code local setup
The fastest way to enable telemetry on a single workstation. Run these commands in your terminal, then restart Claude Code.
Step 1: Get an API key
- Log in to www.agentkeeper.dev
- Go to Settings → Access → API keys
- Click Create Key and name it "Telemetry" or similar
- Copy the key (starts with
ak_live_)
Step 2: Set environment variables
Add the following block to your shell rc file (~/.zshrc, ~/.bashrc, or ~/.config/fish/config.fish):
# >>> agentkeeper-telemetry >>>
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://www.agentkeeper.dev/api/v1/otlp
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ak_live_YOUR_KEY_HERE"
export OTEL_LOG_TOOL_DETAILS=1
export OTEL_LOG_USER_PROMPTS=0
export OTEL_RESOURCE_ATTRIBUTES="host.name=$(scutil --get LocalHostName 2>/dev/null || hostname -s | tr ' ' '_')"
# <<< agentkeeper-telemetry <<<
Replace ak_live_YOUR_KEY_HERE with your actual API key.
Step 3: Reload your shell
source ~/.zshrc # or ~/.bashrc
Step 4: Verify
Open a new Claude Code session and run any tool call. Within 60 seconds, you should see the workstation appear in Settings → Connectors → Claude OTLP and a Claude OTLP row in Activity.
Claude Cowork setup
Use this path when a Claude organization owner configures Cowork monitoring from Claude admin settings.
Claude Cowork OpenTelemetry requires Claude Desktop 1.1.4173 or later and a Claude Team or Enterprise organization. Cowork events can include prompt text, tool parameters, file paths, user email, skills, plugins, MCP calls, approval decisions, token counts, and estimated cost. Set the AgentKeeper privacy toggles to match the tenant's data policy before enabling telemetry.
In the Claude Cowork monitoring panel, enter:
| Field | Value |
|---|---|
| OTLP endpoint | https://www.agentkeeper.dev/api/v1/otlp/v1/logs |
| OTLP protocol | http/protobuf |
| OTLP headers | Authorization=Bearer ak_live_YOUR_KEY_HERE |
| Resource attributes | deployment.environment=prod,team=legal,managed_by=iru |
Replace ak_live_YOUR_KEY_HERE with an AgentKeeper API key from Settings > Access > API keys. Resource attributes are optional, but they make telemetry easier to search and audit.
After saving, fully quit and relaunch Claude Desktop, start a new Cowork chat, and send one real prompt that causes a tool action. Then check Activity for a Cowork OTLP row.
MDM setup for Claude Code
For fleet-wide rollout, push the environment variables via managed Claude Code settings. This is the recommended approach for Team and Enterprise customers, no developer action required.
managed-settings.json format
AgentKeeper can use Claude Code's file-based managed-settings.json deployment. Managed settings are read before user and project settings, so individual settings.json files cannot override them.
Official file-based locations:
| Platform | Path |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/managed-settings.json |
| Linux / WSL | /etc/claude-code/managed-settings.json |
| Windows | C:\Program Files\ClaudeCode\managed-settings.json |
On macOS and Windows, you can also deploy native MDM policies. For Windows Intune, the native policy path is the registry key HKLM\SOFTWARE\Policies\ClaudeCode with a Settings string value containing the JSON.
Create the following payload, replacing ak_live_YOUR_KEY_HERE with your org's Telemetry API key:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://www.agentkeeper.dev/api/v1/otlp",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer ak_live_YOUR_KEY_HERE",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_USER_PROMPTS": "0"
}
}
Note: The
host.nameresource attribute is intentionally omitted from MDM config. Claude Code automatically uses the system hostname, which ensures each workstation maps to the correct record in AgentKeeper.
Jamf Pro
Use a Jamf policy with a script payload. This writes the file-based managed settings path Claude Code reads on macOS:
#!/bin/bash
set -euo pipefail
MANAGED_DIR="/Library/Application Support/ClaudeCode"
MANAGED_FILE="$MANAGED_DIR/managed-settings.json"
mkdir -p "$MANAGED_DIR"
cat > "$MANAGED_FILE" << 'EOF'
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://www.agentkeeper.dev/api/v1/otlp",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer ak_live_YOUR_KEY_HERE",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_USER_PROMPTS": "0"
}
}
EOF
chmod 644 "$MANAGED_FILE"
chown root:wheel "$MANAGED_FILE"
echo "AgentKeeper telemetry config written to $MANAGED_FILE"
Scope the Jamf policy to your developer group and run it once per device or on recurring check-in until coverage is complete.
Iru/Kandji
- In Iru/Kandji, go to Library → Custom Scripts
- Click Add New and name it "AgentKeeper Telemetry Config"
- Set Execution Frequency to "Run once per device"
- Paste the following script, replacing the API key:
#!/bin/bash
set -e
MANAGED_DIR="/Library/Application Support/ClaudeCode"
MANAGED_FILE="$MANAGED_DIR/managed-settings.json"
mkdir -p "$MANAGED_DIR"
cat > "$MANAGED_FILE" << 'EOF'
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://www.agentkeeper.dev/api/v1/otlp",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer ak_live_YOUR_KEY_HERE",
"OTEL_LOG_TOOL_DETAILS": "1",
"OTEL_LOG_USER_PROMPTS": "0"
}
}
EOF
chmod 644 "$MANAGED_FILE"
chown root:wheel "$MANAGED_FILE"
echo "AgentKeeper telemetry config written to $MANAGED_FILE"
- Assign the script to your developer blueprint and click Save
Microsoft Intune (Windows / Linux)
For Windows, deploy the managed settings JSON through an Intune PowerShell script or remediation. The registry policy path is preferred because it is the native Windows managed-settings surface:
$settings = @{
env = @{
CLAUDE_CODE_ENABLE_TELEMETRY = "1"
OTEL_LOGS_EXPORTER = "otlp"
OTEL_METRICS_EXPORTER = "otlp"
OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
OTEL_EXPORTER_OTLP_ENDPOINT = "https://www.agentkeeper.dev/api/v1/otlp"
OTEL_EXPORTER_OTLP_HEADERS = "Authorization=Bearer ak_live_YOUR_KEY_HERE"
OTEL_LOG_TOOL_DETAILS = "1"
OTEL_LOG_USER_PROMPTS = "0"
}
} | ConvertTo-Json -Depth 5 -Compress
$path = "HKLM:\SOFTWARE\Policies\ClaudeCode"
New-Item -Path $path -Force | Out-Null
New-ItemProperty -Path $path -Name "Settings" -Value $settings -PropertyType String -Force | Out-Null
Write-Host "AgentKeeper telemetry policy written to $path"
For Linux or WSL developer workstations, deploy file-based managed settings to /etc/claude-code/managed-settings.json. If your Intune target only supports user shell scripts, use this shell-script deployment:
#!/bin/bash
# AgentKeeper telemetry, deploy via Intune shell script
RC_FILE="$HOME/.bashrc"
# Remove existing block if present
if grep -q "agentkeeper-telemetry" "$RC_FILE" 2>/dev/null; then
sed -i '/# >>> agentkeeper-telemetry >>>/,/# <<< agentkeeper-telemetry <<</d' "$RC_FILE"
fi
# Append new block
cat >> "$RC_FILE" << 'EOF'
# >>> agentkeeper-telemetry >>>
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://www.agentkeeper.dev/api/v1/otlp
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ak_live_YOUR_KEY_HERE"
export OTEL_LOG_TOOL_DETAILS=1
export OTEL_LOG_USER_PROMPTS=0
# <<< agentkeeper-telemetry <<<
EOF
echo "Telemetry configured."
Using /connect --enable-telemetry
The /agentkeeper:connect skill in Claude Code handles full AgentKeeper setup in one step. When you pass the --enable-telemetry flag, it also writes the OTEL environment variables to your shell rc file automatically.
Usage:
In a Claude Code chat session, run:
/agentkeeper:connect --enable-telemetry
The skill will:
- Authenticate with AgentKeeper using your existing API key (or prompt you to create one)
- Install Runtime Shield hooks into
~/.claude/settings.json - Detect your shell (
$SHELL) and locate the appropriate rc file - Write the
agentkeeper-telemetryblock to your rc file, with your API key embedded - Instruct you to
sourcethe rc file or restart your terminal
If the telemetry block already exists in your rc file, the skill replaces it with an updated version, it does not create duplicates.
Verifying your setup
After completing setup, verify that telemetry is arriving:
- Open a new terminal (to load the updated environment variables)
- Start a Claude Code session and run any tool (e.g., ask Claude to list files)
- In the AgentKeeper dashboard, go to Settings → Connectors → Claude OTLP
- Look at the Status card
The Status card shows:
| State | Meaning |
|---|---|
| Active (green) | OTLP events received in the last 24 hours |
| Inactive (gray) | No events received yet |
| Partial (yellow) | Some workstations reporting, others not |
If the card shows Active, telemetry is working. Your workstation will appear in the Workstations list within 1–2 minutes of the first event.
Privacy controls
AgentKeeper gives you granular control over what telemetry is collected. Find these settings at Settings → Connectors → Claude OTLP → Privacy.
| Toggle | Default | What it controls |
|---|---|---|
| Collect tool details | On (when OTEL_LOG_TOOL_DETAILS=1) | Whether tool call parameters and input arguments are included in telemetry events. When off, only tool name, duration, and high-level result data are retained, no file paths, no command text. |
| Collect prompt content | Off | Whether user prompt text is included. Off by default for all plans. When on (Enterprise only), prompts are stored encrypted and subject to your data retention policy. |
| Share anonymized benchmarks | On | Whether your aggregated cost and usage metrics contribute to AgentKeeper's industry benchmarks (e.g., "your team spends 12% less than average"). No individual data is shared. Opt out at any time. |
These toggles apply org-wide. Individual workstations cannot override privacy settings set by an admin.
Team rollout
For Team and Enterprise customers, the Workstations page shows a rollout tracker: how many developers have telemetry active vs. total workstations registered.
To check coverage:
-
Go to Settings → Connectors → Claude OTLP
-
The Setup Health card lists workstations by status:
- Reporting: received an OTLP event in the last 7 days
- Not reporting: workstation is registered but no OTLP events
-
Click a workstation name to open its detail view and see the last event timestamp
To nudge pending workstations:
Use the Copy setup script button in the Setup Health card to generate a one-liner your developers can paste into their terminal. The script is pre-populated with your org's API key.
For MDM-managed fleets, use the MDM Setup instructions above to push config without requiring developer action.
Troubleshooting
"My workstation isn't showing up"
The most common cause is a missing or incorrect host.name resource attribute. AgentKeeper uses this to match OTLP events to workstation records.
Check:
echo $OTEL_RESOURCE_ATTRIBUTES
Expected output: host.name=your-machine-name
Fix:
Add or update the attribute in your shell rc:
export OTEL_RESOURCE_ATTRIBUTES="host.name=$(scutil --get LocalHostName 2>/dev/null || hostname -s | tr ' ' '_')"
On Linux, use hostname -s directly:
export OTEL_RESOURCE_ATTRIBUTES="host.name=$(hostname -s)"
Then reload: source ~/.zshrc and start a new Claude Code session.
"Cost data shows $0.00"
Cost data requires tool detail logging to be enabled. Without tool details, AgentKeeper receives session boundaries but not model or token information.
Check:
echo $OTEL_LOG_TOOL_DETAILS
Expected output: 1
Fix:
export OTEL_LOG_TOOL_DETAILS=1
Add this to your shell rc file and reload. Cost data will appear from the next session onward, existing sessions are not retroactively updated.
"OTLP events aren't arriving"
If no events appear in the dashboard after several Claude Code tool calls, check each variable in sequence:
1. Verify telemetry is enabled:
echo $CLAUDE_CODE_ENABLE_TELEMETRY
Expected: 1
2. Verify the endpoint:
echo $OTEL_EXPORTER_OTLP_ENDPOINT
Expected: https://www.agentkeeper.dev/api/v1/otlp
3. Verify the API key:
echo $OTEL_EXPORTER_OTLP_HEADERS
Expected: Authorization=Bearer ak_live_... (your key)
4. Test endpoint reachability:
curl -s -o /dev/null -w "%{http_code}" \
-X POST https://www.agentkeeper.dev/api/v1/otlp/v1/logs \
-H "Authorization: Bearer ak_live_YOUR_KEY" \
-H "Content-Type: application/x-protobuf"
An empty-body probe should return a successful HTTP status when the endpoint and key are accepted. A 000 means a network connectivity issue. Use Settings > Connectors > Claude OTLP > Setup Health to confirm live keyed events, host mapping, and recent arrival.
5. Check that variables are set in the Claude Code process:
Environment variables must be set before Claude Code starts. If you added them to ~/.zshrc but launched Claude Code from an app launcher (not a terminal), the variables may not be inherited. Try launching Claude Code from a terminal where you've already sourced your rc file.
"Unmapped workstation" in Setup Health
An unmapped workstation means OTLP events arrived from a host.name that doesn't match any registered workstation in your org.
To assign it:
- Go to Settings → Connectors → Claude OTLP → Setup Health
- Find the workstation in the Unmapped list
- Click Assign next to the hostname
- Select the matching workstation record (or create a new one)
To prevent this in the future:
Make sure the host.name in OTEL_RESOURCE_ATTRIBUTES matches the hostname AgentKeeper registered. The easiest way is to use the same command AgentKeeper uses when it registers the host:
scutil --get LocalHostName 2>/dev/null || hostname -s | tr ' ' '_'
Set OTEL_RESOURCE_ATTRIBUTES to the output of that command.
Customer-ready validation checklist
Before declaring a rollout working:
- Claude Code: Activity shows at least one
Claude OTLProw from a real tool call. - Cowork: Activity shows at least one
Cowork OTLProw after a real Cowork action. - Identity: Settings > Connectors > Claude OTLP > Setup Health shows
host.namepresent and mapped. - Detectors: A safe synthetic secret or sensitive-path prompt creates an OTLP-backed detector finding.
- Investigations: The investigation detail shows a Claude OTLP context panel and timeline rows for the same session, prompt, or nearby host/time window.
- Controls: If the customer needs blocking, confirm Runtime Shield hooks or MCP Gateway are installed for pre-execution enforcement.