# Chat debug logging

Records a detailed trace of each chat turn for troubleshooting: the
normalized request sent to the LLM provider, the full response, token usage,
retry attempts, and errors.

Off by default. Three layers control whether it runs for a given chat:

1. **Deployment override.** Setting `CODER_CHAT_DEBUG_LOGGING_ENABLED=true`
   (or `--chat-debug-logging-enabled` at server start) forces debug logging
   on for every chat. The runtime admin and user toggles become read-only.
1. **Runtime admin gate.** With the deployment override unset, the
   *Let users record chat debug logs* toggle decides whether users can opt
   in. Configure it under **AI Settings** > **Lifecycle**, or at
   `GET/PUT /api/experimental/chats/config/debug-logging`.
1. **Per-user toggle.** Users with the admin gate enabled can turn debug
   logging on for their own chats from **Agents** > **Settings** > **General**
   under *Record debug logs for my chats*. The endpoint
   `PUT /api/experimental/chats/config/user-debug-logging` returns
   `409 Conflict` if the deployment override is active and `403 Forbidden`
   if the admin has not enabled user opt-in.

> [!IMPORTANT]
> Debug logs may contain sensitive content from prompts, responses, tool
> calls, and errors. Treat them with the same care as conversation history.
> Only the chat owner (or a user with read access to the chat) can fetch a
> chat's debug runs through the API. Administrators do not get blanket
> access to all users' debug data.

When debug logging is active for a chat, a **Debug** tab appears in the
right panel of the Agents page (alongside Git, Terminal, and Desktop) for
that chat's owner. The tab lists recent debug runs and lets you expand a run
into its per-step request, response, token usage, retry attempts, errors,
and policy metadata.

## Export debug logs

You can export the same captured debug data from the UI:

1. Navigate to **Agents**.
1. Open a chat with debug logging enabled.
1. Open the **Debug** tab in the right panel.
1. Click **Export debug logs** to download the chat's recent debug runs as
   JSON, or expand a run and click **Export this run** to download one run.

The chat-level export includes the full run detail for the runs returned by
the debug run list endpoint. The current list endpoint returns up to 100 of
the newest runs.

### API access

The same data is available through the experimental API:

- `GET /api/experimental/chats/{chat}/debug/runs` lists the most recent runs
  for a chat (up to 100, newest first).
- `GET /api/experimental/chats/{chat}/debug/runs/{debugRun}` returns a single
  run with all of its steps, including normalized request and response bodies.

Fetch a single run and save it as JSON:

```sh
export CODER_URL="https://coder.example.com"
export CODER_SESSION_TOKEN="$(coder login token)"
export CHAT_ID="00000000-0000-0000-0000-000000000000"
export RUN_ID="11111111-1111-1111-1111-111111111111"

curl -fsS \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/experimental/chats/$CHAT_ID/debug/runs/$RUN_ID" \
  | jq . > "coder-agents-debug-run-$RUN_ID.json"
```

Fetch every run returned by the list endpoint and save a chat-level export.
Using the same `CODER_URL`, `CODER_SESSION_TOKEN`, and `CHAT_ID` variables
from above:

```sh
RUN_IDS=$(curl -fsS \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/experimental/chats/$CHAT_ID/debug/runs" \
  | jq -r '.[].id') || {
  echo "Failed to list debug runs" >&2
  exit 1
}

RUN_EXPORTS=$(mktemp)
trap 'rm -f "$RUN_EXPORTS"' EXIT

for RUN_ID in $RUN_IDS; do
  curl -fsS \
    -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
    "$CODER_URL/api/experimental/chats/$CHAT_ID/debug/runs/$RUN_ID" \
    >> "$RUN_EXPORTS" || {
      echo "Failed to fetch debug run $RUN_ID" >&2
      exit 1
    }
  echo >> "$RUN_EXPORTS"
done

jq -s \
  --arg chat_id "$CHAT_ID" \
  --arg exported_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  '{
    version: 1,
    scope: "chat",
    exported_at: $exported_at,
    chat_id: $chat_id,
    run_count: length,
    limited_to_most_recent: 100,
    runs: .
  }' "$RUN_EXPORTS" > "coder-agents-debug-chat-$CHAT_ID.json"
```

Debug runs are stored alongside the chat and are removed when the parent
conversation is deleted (manually, by retention, or by chat purge). See
[Data Retention](https://coder.com/docs/ai-coder/agents/platform-controls/chat-retention.md) for the conversation retention
controls.
