Skip to main content
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.

Logger hierarchy

All package loggers sit under the autoplay_sdk namespace (one logger per module via logging.getLogger(__name__)):
Logger nameTypical use
autoplay_sdk.async_clientAsyncConnectorClient connection, reconnect, parse errors
autoplay_sdk.clientConnectorClient (sync SSE reader)
autoplay_sdk.bufferEventBuffer / RedisEventBuffer
autoplay_sdk.context_storeContextStore / AsyncContextStore
autoplay_sdk.chatbotBaseChatbotWriter delivery and debounce tasks
autoplay_sdk.summarizerSessionSummarizer / AsyncSessionSummarizer
autoplay_sdk.modelsActionsPayload and related parsing
autoplay_sdk.agent_contextAsyncAgentContextWriter
autoplay_sdk.webhook_receiverWebhookReceiver verification and dispatch
autoplay_sdk.ragRagPipeline / AsyncRagPipeline
autoplay_sdk.metricsSdkMetricsHook 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:
import logging
logging.getLogger("autoplay_sdk").setLevel(logging.DEBUG)
Narrow to one module, e.g. chatbot delivery only:
logging.getLogger("autoplay_sdk.chatbot").setLevel(logging.DEBUG)

  • 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.webhook_receiver (WebhookReceiver), and autoplay_sdk.agent_context (AsyncAgentContextWriter).

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.
# 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.