Observe agent activity
Before you can enforce a policy on an agent action, you need to know which agents are running, who runs them, and what they do. Arcjet ingests agent activity without a code change, through three paths:
- Coding agent hooks, where Claude Code or GitHub Copilot calls Arcjet at each lifecycle event. This is the only path that can also refuse a tool call. For more information, see Secure coding agents.
- OpenTelemetry, where a client you already run exports to Arcjet. It pushes with low latency and carries host metadata and token usage.
- The Claude Compliance API, where you paste one key and Arcjet polls Anthropic for your organization’s activity and session transcripts. It needs no client configuration and covers clients you never configured.
All three render in the same Console views. OpenTelemetry and Compliance API activity is context, not enforcement: it records what an agent did. To decide whether an action runs, add an enforcement point with agent guards or install the hooks.
Send OpenTelemetry data to Arcjet
Section titled “Send OpenTelemetry data to Arcjet”Arcjet accepts OpenTelemetry (OTLP) exports over HTTP at
https://decide.arcjet.com and records each record as an Arcjet capture event.
Point any OTLP exporter at it.
Export from Claude Code
Section titled “Export from Claude Code”Set these environment variables to export Claude Code’s security and audit telemetry:
export CLAUDE_CODE_ENABLE_TELEMETRY=1export OTEL_LOGS_EXPORTER=otlpexport OTEL_EXPORTER_OTLP_PROTOCOL=http/protobufexport OTEL_EXPORTER_OTLP_ENDPOINT=https://decide.arcjet.comexport OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ARCJET_KEY"export OTEL_LOG_USER_PROMPTS=1export OTEL_LOG_TOOL_DETAILS=1Replace ARCJET_KEY with the key for the site the activity belongs to.
OTEL_LOG_USER_PROMPTS and OTEL_LOG_TOOL_DETAILS enrich the audit trail with
prompt text and tool arguments. Leave them unset if that content shouldn’t
leave the machine.
Roll it out across an organization
Section titled “Roll it out across an organization”To enable ingest for everyone rather than relying on each person’s shell, ship the same configuration through Claude Code managed settings:
{ "env": { "CLAUDE_CODE_ENABLE_TELEMETRY": "1", "OTEL_LOGS_EXPORTER": "otlp", "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", "OTEL_EXPORTER_OTLP_ENDPOINT": "https://decide.arcjet.com", "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer ARCJET_KEY", "OTEL_LOG_USER_PROMPTS": "1", "OTEL_LOG_TOOL_DETAILS": "1" }}Three details decide whether this works:
- Every value is a string, including
"1". - Put a literal space after
Bearer.OTEL_EXPORTER_OTLP_HEADERSis baggage-encoded, so Claude Code’s exporter sends that space as%20. Arcjet decodes the header before parsing it, so either a literal space or%20works. Don’t encode it twice. - Point
OTEL_EXPORTER_OTLP_ENDPOINTat the host with no port. Port 4317 is the gRPC port, which Arcjet doesn’t accept. The exporter appends the OTLP HTTP paths itself.
The same managed settings file can carry the coding agent hooks, but use one or the other for a given site.
What Arcjet records
Section titled “What Arcjet records”| Signal | Path | What happens |
|---|---|---|
| Logs | POST /v1/logs | The primary signal. Each log record becomes one capture event. |
| Traces | POST /v1/traces | Each span becomes a capture event, best effort. |
| Metrics | POST /v1/metrics | Authenticated and acknowledged, but not recorded. |
Arcjet acknowledges metrics rather than rejecting them so that an exporter also sending metrics to another backend doesn’t error. Aggregate counters aren’t discrete auditable events, so there’s nothing to record.
Both OTLP wire formats work: http/protobuf and http/json. gRPC on port 4317
doesn’t.
Each record maps onto a capture event:
| OTLP | Capture event |
|---|---|
| Event name | action, verbatim. Claude Code sends names like claude_code.tool_decision. |
session.id | correlationId, which joins the activity in one session. |
| Every other attribute | metadata, with types preserved. A duration stays a number and a tool argument object stays an object. |
service.name | The sender identity. Claude Code reports claude-code. |
Metadata limits follow OpenTelemetry conventions: 128 keys, 32 KiB per serialized value, and a depth of 10. Past the cap, Arcjet keeps the security-relevant keys first and records what it dropped on the event, so a truncated event is never silently truncated.
Ingest is fire and forget. A 200 means Arcjet received the export, not that
it’s queryable yet.
Connect the Claude Compliance API
Section titled “Connect the Claude Compliance API”Instead of configuring an exporter on every client, connect one key and Arcjet polls Anthropic for your organization’s activity and session transcripts.
Choose a key
Section titled “Choose a key”Your Anthropic organization decides which credential you can create, and the two differ in what Arcjet can import:
| Compliance Access Key | Admin API key | |
|---|---|---|
| Prefix | sk-ant-api01- | sk-ant-admin01- |
| Who can create it | A Claude Enterprise primary owner or organization owner | A Claude Console organization admin |
| Arcjet imports | Activity and session transcripts | Activity only |
An Admin API key reaches the activity feed and nothing else, so you get which sessions ran, when, and by whom, but no prompts, tool calls, or transcripts. Arcjet detects the key type and skips the transcript requests rather than spending your organization’s shared rate budget on calls that can’t succeed.
Ask for read-only scopes: read:compliance_activities and
read:compliance_user_data. A key can also carry
delete:compliance_user_data, which permits hard-deleting chats, files, and
projects. Arcjet never calls a delete endpoint.
For more information about the two credentials, see Anthropic’s Compliance API access documentation.
Connect the key
Section titled “Connect the key”- In the Arcjet Console, open your team, then go to Settings > Integrations > Claude Compliance.
- Select which Claude product your organization uses.
- Enter the key and select the destination site. A team with one site skips this choice.
- Select Connect. Arcjet validates the key against Anthropic before storing it, so a key that doesn’t work is never stored.
A team admin has to do this, because the credential is a team resource: one key, one connection, one destination site. You can change the destination later without reconnecting. The connection keeps its position in the feed, so ingest continues where it left off, but events already imported stay with the site that received them.
The key never comes back from any API, never returns to the browser after you submit it, and is never written to Arcjet’s databases. Arcjet stores a masked form and a salted fingerprint.
What the Compliance API doesn’t cover
Section titled “What the Compliance API doesn’t cover”Recording isn’t retroactive, and Anthropic doesn’t backfill, so nothing from before you enabled the Compliance API is available. Turning it off later stops recording, and that gap can’t be recovered.
These are also absent, whichever key you connect:
- Claude Code authenticated with a Console API key, or run through Amazon Bedrock, Google Vertex AI, or Microsoft Foundry.
- Claude Code on the web.
- Organizations with HIPAA readiness enabled, and any session under zero data retention.
- Thinking blocks, images, and other binary content.
- The system prompt. A marker message stands in for it.
Tool inputs and results are truncated to 10,000 bytes each.
Diagnose a stalled feed
Section titled “Diagnose a stalled feed”The integration panel shows the last sync, how far through the feed it has read, the last error, and whether the connection is rate limited.
| What you see | What it means |
|---|---|
Status is needs_reauth | The key was revoked or the connection is gone. Reconnect. |
| Reconnected, still not syncing | Anthropic rejected the stored key. Only a different key clears this. Resubmitting the same one isn’t a rotation. |
| Activity but never any transcripts | The connection uses an Admin API key. Transcripts need a Compliance Access Key. |
| Sessions but no transcripts | Those sessions predate enablement, so their content was never captured. |
| Lagging with no errors | Your organization’s shared rate budget is being consumed by your own tooling. |
| Nothing at all | Confirm the Compliance API was enabled before the period you’re looking for. |
Read the activity
Section titled “Read the activity”Ingested activity appears in the Console under the site’s Activity, alongside the guard and protect decisions Arcjet made. Each row carries the sender, the asserted principal, and the correlation ID that joins the events of one session, so you can follow a session from its first prompt to its last tool call.
An ingested event is asserted context, so an action that appears in the activity with no decision beside it is an action nothing enforced. That gap is the point of the view. Use it to find the actions worth guarding, then add an enforcement point and a policy for each, or install the coding agent hooks where the sessions are Claude Code or Copilot.
Data handling
Section titled “Data handling”Ingested activity is untrusted context. Arcjet records it, correlates it, and shows it, but it can never satisfy a protection requirement: a capture event is what a client said happened, not something Arcjet adjudicated.
Session transcripts carry raw prompts, source code, and any credential someone
pasted into a session. Neither Anthropic nor Arcjet masks that content at
ingest. Prompt and tool-detail capture is opt-in on the OpenTelemetry path,
through OTEL_LOG_USER_PROMPTS and OTEL_LOG_TOOL_DETAILS. On the Compliance
API path it arrives organization-wide with no per-client opt-in, which is worth
weighing before you connect it.
For what Arcjet retains and for how long, see the privacy documentation.
Related
Section titled “Related”- Secure coding agents – enforce policy on Claude Code and Copilot tool calls
- Agent guards – enforce a policy before an action runs
- Capture events – record an action from your own application code
- Guard testing and reference – what a decision reports