> ## Documentation Index
> Fetch the complete documentation index at: https://developers.autoplay.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging

> Structured logging conventions when building on autoplay-sdk — module loggers, exception tracebacks, and safe extra fields.

The SDK uses the standard library `logging` module. It does **not** attach handlers or call `logging.basicConfig()` — your application owns root logging configuration. When you extend the SDK with custom backends, webhooks, or LLM calls, follow the same patterns so your logs stay searchable and safe in production.

Observability-related release notes live in the [Changelog](/changelog).

***

## Logger hierarchy

All package loggers sit under the **`autoplay_sdk`** namespace (one logger per module via `logging.getLogger(__name__)`):

| Logger name                                                 | Typical use                                                                                                                                                                                                                                                      |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autoplay_sdk.async_client`                                 | `AsyncConnectorClient` connection, reconnect, parse errors                                                                                                                                                                                                       |
| `autoplay_sdk.client`                                       | `ConnectorClient` (sync SSE reader)                                                                                                                                                                                                                              |
| `autoplay_sdk.buffer`                                       | `EventBuffer` / `RedisEventBuffer`                                                                                                                                                                                                                               |
| `autoplay_sdk.context_store`                                | `ContextStore` / `AsyncContextStore`                                                                                                                                                                                                                             |
| `autoplay_sdk.chatbot`                                      | `BaseChatbotWriter` delivery and debounce tasks                                                                                                                                                                                                                  |
| `autoplay_sdk.summarizer`                                   | `SessionSummarizer` / `AsyncSessionSummarizer`                                                                                                                                                                                                                   |
| `autoplay_sdk.models`                                       | `ActionsPayload` and related parsing                                                                                                                                                                                                                             |
| `autoplay_sdk.agent_context`                                | `AsyncAgentContextWriter`                                                                                                                                                                                                                                        |
| `autoplay_sdk.webhook_receiver`                             | `WebhookReceiver` verification and dispatch                                                                                                                                                                                                                      |
| `autoplay_sdk.rag`                                          | `RagPipeline` / `AsyncRagPipeline`                                                                                                                                                                                                                               |
| `autoplay_sdk.chat_pipeline`                                | Composition helper (`compose_chat_pipeline`) — currently minimal/no routine logs; rely on downstream module loggers for runtime behavior                                                                                                                         |
| `autoplay_sdk.user_index`                                   | User-session index helper — currently minimal/no routine logs; use integration logs around cache misses and identity mapping                                                                                                                                     |
| `autoplay_sdk.serve.fastapi`                                | Optional bridge factory (`build_copilot_app`) — currently minimal/no routine logs; endpoint errors surfaced via HTTP status (`404` for no activity)                                                                                                              |
| `autoplay_sdk.rag_query.pipeline`                           | `assemble_rag_chat_context` — debug summary on success (lengths/flags only); **warning** + traceback if assembly fails (then exception is re-raised)                                                                                                             |
| `autoplay_sdk.agent_states.state_machine`                   | `AgentStateMachine` — **debug** on successful transitions and rejected transitions; **debug** when `complete_task` moves guidance to `thinking`; **warning** + traceback on malformed snapshots (`from_snapshot`), skipped corrupt task rows                     |
| `autoplay_sdk.agent_states.proactive_idle_expiry`           | `run_proactive_idle_expiry` — **error** + `extra` (`event_type`, `from_state`) if FSM does not transition after a successful remote delete (unexpected); otherwise no routine logs                                                                               |
| `autoplay_sdk.agent_state_v2.session_state`                 | `SessionState` — **warning** + `extra` (`event_type: agent_state_v2_snapshot_invalid`, `snapshot_version`) immediately before raising `ValueError` on an unrecognised snapshot `_v`; no routine logs for normal transitions                                      |
| `autoplay_sdk.proactive_triggers.tour_registry`             | `TourRegistry.from_dict` — **warning** + traceback (`event_type: tour_registry_entry_invalid_type` or `tour_registry_entry_parse_error`, `index`) for each malformed or unparseable entry; skips the entry and continues                                         |
| `autoplay_sdk.proactive_triggers.proactive_intercom_config` | `parse_proactive_trigger_configs` / `parse_tour_registry` — **warning** + traceback (`event_type: proactive_trigger_config_invalid_type`, `proactive_trigger_config_parse_error`, `tour_registry_parse_error`) for malformed config entries; skips and continues |
| `autoplay_sdk.rag_query.formatters`                         | Pure string fill-ins — **no** log records                                                                                                                                                                                                                        |
| `autoplay_sdk.rag_query.assembly`                           | Pure builders — **no** log records                                                                                                                                                                                                                               |
| `autoplay_sdk.rag_query.watermark`                          | Watermark types/stores — **no** log records (implementations may log in your app)                                                                                                                                                                                |
| `autoplay_sdk.metrics`                                      | `SdkMetricsHook` wiring (minimal; prefer hook for counters)                                                                                                                                                                                                      |

**`autoplay_sdk.integrations`** (e.g. `integrations.intercom`) contains constants and helpers only — **no log records** are emitted from that subpackage.

Enable debug output for the whole SDK:

```python theme={null}
import logging
logging.getLogger("autoplay_sdk").setLevel(logging.DEBUG)
```

Narrow to one module, e.g. chatbot delivery only:

```python theme={null}
logging.getLogger("autoplay_sdk.chatbot").setLevel(logging.DEBUG)
```

***

## Recommended pattern

* **Logger per module:** `logger = logging.getLogger(__name__)`.
* **Lazy formatting:** use `%` placeholders in the message (`logger.error("failed: %s", err)`), not f-strings, so arguments are not evaluated if the log level filters the record out.
* **Exceptions:** on error paths, pass `exc_info=True` (or pass the exception to `exc_info` where your framework expects it, e.g. task `done_callback` handlers).
* **Structured context:** add a stable `extra` dict with correlation fields your team can query — for example `session_id`, `product_id`, `conversation_id`, `url`, `event_type`. Use the same key names across your integration where possible.

### Error paths and tracebacks

* Inside `except SomeError as exc:` prefer **`exc_info=True`** (records the active exception and traceback) or pass **`exc_info=exc`** when you need to attach a specific exception instance before re-raising.
* Shorthand while handling an exception: **`logger.exception("msg %s", arg)`** is equivalent to `logger.error(..., exc_info=True)` for the current exception context.
* For **`asyncio.Task`** `done_callback` handlers (no active `except` frame), use **`exc_info=t.exception()`** when the task failed and `t.exception()` is not `None` — otherwise there is no traceback to record.

Transient retry loops may log **`logger.warning(..., exc)`** without `exc_info` to avoid log volume; use `exc_info=True` on the final failure or at `DEBUG` if you need full stacks for noise.

In-repo examples: `autoplay_sdk.client` (`ConnectorClient`), `autoplay_sdk.rag` (`RagPipeline`), `autoplay_sdk.rag_query.pipeline` (`assemble_rag_chat_context`), `autoplay_sdk.webhook_receiver` (`WebhookReceiver`), and `autoplay_sdk.agent_context` (`AsyncAgentContextWriter`).

### Recommended log points for self-hosted bridges

For integrations built on `UserSessionIndex`, `compose_chat_pipeline`, and `build_copilot_app`, add app-layer logs at:

* stream lifecycle boundaries (startup, reconnect, shutdown),
* endpoint misses (`/context` or `/reply` returning `404` for no activity),
* identity resolution failures (missing/mismatched `user_id`),
* LLM callback failures in reply handlers or summary overwrite callbacks.

Use consistent `extra` keys (`user_id`, `session_id`, `product_id`, `conversation_id`, `endpoint`) so these lines correlate with SDK module logs.

### Subclassing `BaseChatbotWriter`

If you implement a custom chatbot destination in **your** package, define `logger = logging.getLogger(__name__)` in **your** module (not under `autoplay_sdk`). Follow the same `%` formatting, `exc_info`, and `extra` rules so your logs compose cleanly with SDK lines in shared aggregators.

***

## Do not log secrets

* **API keys, bearer tokens, cookies, and signing secrets** — including material used for HMAC verification (e.g. raw webhook signing payloads or shared secrets).
* **Full HTTP request and response bodies** — especially in webhook-heavy apps. Bodies are the most common accidental leak vector: they often contain tokens, session cookies, or PII. Prefer logging a short prefix, status code, and correlation ids; redact or omit bodies unless you have a deliberate, reviewed redaction pipeline.
* **Full user or session payloads** unless redacted or truncated to non-sensitive fields.

***

## When `extra` is sparse

Some SDK code paths only know `session_id` (for example failures inside `overwrite_with_summary` before your callback runs). If you need `product_id` or other fields in those logs, thread them through your own layer (wrapper, context var, or subclass) — the SDK does not add new parameters for logging-only data in this release.

***

## Common mistake

Logging the exception message without a traceback loses the stack you need for production debugging. Omitting `extra` makes it hard to tie a line to a session or product in your log platform.

```python theme={null}
# Avoid
logger.error("Request failed: %s", exc)

# Prefer
logger.error(
    "Request failed for session=%s: %s",
    session_id,
    exc,
    exc_info=True,
    extra={"session_id": session_id, "product_id": product_id},
)
```

Keep `extra` to non-sensitive correlation fields; never put secrets or raw bodies there.
