Skip to content

[Anthropic] Claude Code / Cowork Telemetry #19407

Description

@jamiehynds

Description

Unlike the Claude Enterprise web product, Cowork and Claude Code activity is explicitly excluded from the Compliance API — confirmed across all plan tiers including Enterprise (as of May 2026, Cowork is excluded from Audit Logs, the Compliance API, and Data Exports; Claude Code is on a separate path entirely).

The supported route for session-level telemetry from these products is OpenTelemetry (OTel): both Claude Code and Cowork emit events via standard OTLP export. Elastic's InfoSec team has already built and documented a working pipeline for this (see the Security Labs post in references). This issue is about formalising that work as a native, installable integration rather than leaving it as a manual configuration exercise for every customer.

This is a meaningful security surface: agentic workflows in Claude Code and Cowork may involve shell execution, file-system access, MCP tool calls, and web browsing — all high-value signals for threat detection and compliance that are invisible to the Compliance API.

What this data does (and doesn't) give you

OTel is the only telemetry path for these products, so the integration's value is gated by what's exported and at what verbosity:

What the events expose:

  • Tool execution — every tool call and MCP server call (tool_result): tool_name, tool_use_id, success, duration_ms, error_type, and the permission decision_source.
  • Permission decisions (tool_decision) — how each call was approved/rejected and the source (config, hook, user_permanent, user_temporary, user_abort, user_reject).
  • API usage & cost (api_request) — model, cost_usd, token counts (input/output/cache), duration_ms, MCP attribution.
  • Session structuresession.id + event.sequence (monotonic per-session counter) + prompt.id (links every event triggered by one prompt) enable full session reconstruction.
  • Identity/contextuser.email, user.id, organization.id, terminal.type on every event.

What's redacted/gated by default (important):

  • Prompt content — redacted unless OTEL_LOG_USER_PROMPTS=1.
  • Tool parameters & input (bash commands, MCP server/tool names, skill names, tool args) — redacted unless OTEL_LOG_TOOL_DETAILS=1 (a separate gate from prompts). MCP server/tool visibility depends on this being set.
  • Raw API request/response bodies — only with OTEL_LOG_RAW_API_BODIES (full conversation history; heavy).
  • Claude Code redacts prompts and tool arguments by default; Cowork surfaces fuller detail automatically per the Security Labs configuration.

Scope & data boundaries

  • OTel-native, not Agent-polled: this is a packaged set of templates + pipeline + dashboards that customers install once, applied to OTLP data — not a traditional polled-API datastream.
  • The collector/gateway is infrastructure, not a shipped asset. The package ships ingest/mapping/dashboard assets; the OTLP collector path is documentation (see deployment options below).
  • Complementary to the Compliance API datastream, not overlapping: the Compliance API covers claude.ai web interactions and admin/auth events; this OTel integration covers agentic tool execution and session telemetry from Claude Code and Cowork. Both are needed for full Claude fleet visibility.
  • Two datasets, one package: claude_code and claude_cowork, routed via data_stream.dataset.

Why this matters

  • Tool invocation auditing: every MCP server call and tool execution is logged with tool name, server name, and (with OTEL_LOG_TOOL_DETAILS=1) input parameters — surface unauthorized data access, unexpected shell commands, or MCP connections to unapproved internal systems.
  • Session reconstruction: session.id + event.sequence gives a monotonic counter for complete session replay — critical for incident investigation and forensics.
  • EDR correlation: combined with Elastic Defend endpoint telemetry, Claude's OTel events provide the intent (what the agent was asked to do) while EDR provides the impact (processes spawned, files written, network connections). Joining by timestamp and host produces materially richer investigations than either source alone.
  • Permission-decision analysis: tool_decision source values expose how each call was approved — surface users auto-approving risky tool categories (user_permanent) or unusual permission patterns fleet-wide.
  • Cost and usage anomaly detection: cost_usd and token counts on every api_request enable per-user, per-session spend tracking and anomaly alerting.
  • MCP server access monitoring: the flattened mcp_server_name / mcp_tool_name fields show which internal systems agents call and with what operations.
  • Compliance: demonstrate oversight of autonomous AI agents for regulated industries (DORA, EU AI Act, SOX).

Telemetry schema

Both products emit events via OTLP logs. Core event types:

Event (event.name) Key fields
api_request model, cost_usd, input_tokens, output_tokens, cache tokens, duration_ms, MCP attribution
tool_result tool_name, tool_use_id, success, duration_ms, decision_source, tool_parameters/tool_input (gated)
tool_decision tool_name, decision (accept/reject), source (config/hook/user_*)
user_prompt prompt_length, command_name; prompt content gated by OTEL_LOG_USER_PROMPTS=1
api_error error, status_code, attempt, model

Note: additional event types now exist beyond these five — api_refusal (stop_reason refusal) and the raw-body events api_request_body / api_response_body (only with OTEL_LOG_RAW_API_BODIES). Every event carries the standard attributes (session.id, organization.id, user.email, user.id, terminal.type), the prompt.id correlation attribute, and event.sequence / event.timestamp.

What needs to be built

Package assets to ship:

  • Component template (logs-claude_code.otel@custom): override default keyword mappings for numeric fields (cost_usd, duration_ms, input_tokens, etc. as float/long) and add flattened mappings for tool_parameters_flattened and tool_input_flattened, so MCP server/tool names and bash commands are queryable without unbounded field explosion.
  • Index template (logs-claude_code.otel): compose standard OTel component templates (otel@mappings, semconv-resource-to-ecs@mappings, etc.) plus the custom template above; match both logs-claude_code.otel-* and logs-claude_cowork.otel-*.
  • Ingest pipeline (logs-claude_code.otel@custom): parse tool_parameters and tool_input from JSON strings into *_flattened fields; ignore failures gracefully.
  • Dashboards: session timeline view, tool-call frequency by type and user, MCP server access heatmap, cost by user/session, permission-decision breakdown, admin configuration events.

Deployment paths (documentation, not shipped assets):

  • Option A — Elastic Cloud (mOTLP, no gateway): point Claude Code's OTLP exporter directly at the Elastic Cloud Managed OTLP endpoint. Set data_stream.dataset=claude_code as a resource attribute so data routes to the correct data stream with the installed templates applied. No collector to operate.
  • Option B — Self-managed (EDOT Collector): deploy the EDOT Collector as an OTLP gateway. Use the transform/route processor to set data_stream.dataset based on service.name (claude-code vs cowork). Supports bearer-token auth via the bearertokenauth extension. See the Security Labs post for a reference Helm configuration.

Telemetry configuration delivery:

  • Claude Code: configured via CLAUDE_CODE_ENABLE_TELEMETRY=1, OTEL_EXPORTER_OTLP_ENDPOINT, and auth headers. For fleet rollout, use managed settings delivered via MDM (Jamf, Intune) or the Admin Console server-managed settings — these cannot be overridden by end users, which also locks in the OTEL_LOG_* verbosity gates.
  • Claude Cowork: configured centrally in the Anthropic admin portal; instances pick up the OTLP endpoint automatically. Note: the gateway endpoint must be allowlisted for outbound access from the Cowork sandbox.

Sample event

⚠️ Illustrative sample. Attribute names follow the Claude Code monitoring docs; values are representative. A real captured event should be added during development. This shows a tool_result for an MCP call with OTEL_LOG_TOOL_DETAILS=1 enabled (so tool_parameters is populated) — the JSON string the ingest pipeline flattens into tool_parameters_flattened.

{
  "event.name": "tool_result",
  "event.timestamp": "2026-06-01T14:23:11.412Z",
  "event.sequence": 47,
  "session.id": "b2c3d4e5-6f70-4a1b-8c2d-3e4f5a6b7c8d",
  "prompt.id": "a1b2c3d4-5e6f-4071-9a2b-3c4d5e6f7081",
  "organization.id": "11112222-3333-4444-5555-666677778888",
  "user.email": "engineer@contoso.com",
  "user.id": "user_01H9XYZABCDEF",
  "terminal.type": "vscode",
  "tool_name": "mcp__github__create_issue",
  "tool_use_id": "toolu_01ABCdef456",
  "success": "true",
  "duration_ms": 842,
  "decision_type": "accept",
  "decision_source": "user_permanent",
  "tool_input_size_bytes": 312,
  "tool_result_size_bytes": 1840,
  "tool_parameters": "{\"mcp_server_name\":\"github\",\"mcp_tool_name\":\"create_issue\"}"
}

Key fields

Field Description
user.email / organization.id Who ran the tool, and in which org
session.id + event.sequence Session identity and ordering for replay/forensics
prompt.id Ties this event to the prompt that triggered it
tool_name / tool_use_id The tool invoked and its unique call id
decision_source How the call was approved (user_permanent = a standing auto-approve — a risk signal)
success / duration_ms Outcome and execution time
tool_parameters (gated) JSON string with mcp_server_name / mcp_tool_name (or bash command) — flattened by the ingest pipeline

Availability note: tool parameters appear only with OTEL_LOG_TOOL_DETAILS=1 and prompt content only with OTEL_LOG_USER_PROMPTS=1 — set these via managed settings during testing to validate the flattened-field mappings.

Access requirements

  • Claude Code with telemetry enabled (CLAUDE_CODE_ENABLE_TELEMETRY=1) and/or Claude Cowork with OTLP configured in the Anthropic admin portal. An Enterprise plan is required for managed/server-side settings to enforce telemetry and verbosity gates fleet-wide.
  • An OTLP destination: Elastic Cloud Managed OTLP endpoint (Option A) or a self-managed EDOT Collector gateway (Option B).
  • Development requires Claude Code with telemetry exporting to a test Elastic cluster; a Cowork instance is needed to validate the claude_cowork dataset.

References

Metadata

Metadata

Assignees

Labels

9.5 candidateEpicNew IntegrationIssue or pull request for creating a new integration package.Team:Security-Service IntegrationsSecurity Service Integrations team [elastic/security-service-integrations]

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions