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

# Typed payloads

> ActionsPayload, SummaryPayload, and SlimAction — the typed models your callbacks receive.

All callbacks receive typed dataclass instances, not raw dicts. Your IDE will autocomplete
every field, and each model has a `.to_text()` method that returns an embedding-ready string.

***

## Data structures at a glance

Use this map to understand which structure owns which concern:

| Structure                         | Layer                              | Primary key / scope                                    | Write path                                                  | Read path                                               |
| --------------------------------- | ---------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------- | ------------------------------------------------------- |
| `SessionState`                    | `agent_state.v2`                   | `session_id`                                           | `SessionState` transitions + `on_conversation_linked(link)` | Delivery routing and state-machine decisions            |
| `ConversationLink`                | `chat`                             | (`session_id`, `conversation_id`, `event`)             | Created by `link_conversation(...)`                         | Transition input to `SessionState` and store sync       |
| `ConversationLinkStore`           | `chat`                             | `conversation_id -> session_id`                        | `store.save(link)` inside `link_conversation(...)`          | Webhook/reverse lookup only (not delivery hot path)     |
| `ConversationWebhookEvent`        | `chat` webhook parsing             | inbound platform payload                               | `extract_conversation_event(...)` parser output             | Identity/session resolution before linking              |
| `ActionsPayload`                  | event stream payload               | session batch                                          | connector emits `actions` frame                             | `on_actions` callbacks, context writers, embeddings     |
| `SummaryPayload`                  | event stream payload               | session summary                                        | summarizer emits `summary` frame                            | `on_summary` callbacks and retrieval context            |
| `SlimAction`                      | action item payload                | per-action within batch                                | included in `ActionsPayload.actions`                        | formatting, embeddings, and downstream replay           |
| `ProactiveTriggerContext`         | proactive trigger evaluation       | `session_id`, `product_id`, optional `conversation_id` | built each proactive tick from recent payloads              | input to `ProactiveTriggerRegistry.evaluate_first(...)` |
| `ProactiveTriggerResult`          | proactive trigger output           | `trigger_id` + delivery fields                         | returned by matching trigger                                | delivery layer (`body`, `reply_option_labels`, timings) |
| `TriggerMessage`                  | proactive trigger config           | stable chip `id` + `label`                             | configured in `ProactiveTriggerConfig.messages`             | maps user chip selection to optional tour launch        |
| `TourDefinition` / `TourRegistry` | proactive visual-guidance registry | `id` / `user_tour_id`                                  | parsed from `integration_config.tour_registry`              | resolves per-tour timeout/cooldown and launch metadata  |

Directionality rules:

* **Session-owned routing state:** `SessionState.conversation_linked` + `SessionState.conversation_id`
* **Reverse index lookup:** `ConversationLinkStore` (`conversation_id -> session_id`)
* **Inbound webhook parse DTO:** `ConversationWebhookEvent`
* **Outbound action/summary transport:** `ActionsPayload`, `SummaryPayload`, `SlimAction`
* **Proactive decision input/output:** `ProactiveTriggerContext` and `ProactiveTriggerResult`
* **Proactive choice-to-tour mapping:** `TriggerMessage` with `TourRegistry`/`TourDefinition`

See also: [Agent session states](/sdk/agent-states), [BaseChatbotWriter](/sdk/support-agent-writer), [Payload schema](/sdk/payload-schema), and [Proactive triggers](/sdk/proactive-triggers).

***

## ActionsPayload

Delivered when the connector forwards a batch of UI actions from a user session.

```python theme={null}
from autoplay_sdk import ActionsPayload

def on_actions(payload: ActionsPayload):
    print(payload.session_id)   # identify the session
    print(payload.email)        # tie to a user identity
    print(payload.count)        # number of actions in this batch

    for action in payload.actions:
        print(action.title)
        print(action.description)
        print(action.canonical_url)
        print(action.session_id, action.user_id, action.email)

    # embedding-ready string — pass directly to your embedding API
    text = payload.to_text()
```

**`to_text()` example output:**

```
Session ps_abc123 — 3 actions
[0] pageview: User landed on the dashboard page — https://app.example.com/dashboard
[1] click: User clicked Export CSV button — https://app.example.com/dashboard
[2] click: User opened billing settings — https://app.example.com/settings/billing
```

### Fields

<ParamField path="product_id" type="string" required>
  Connector product identifier.
</ParamField>

<ParamField path="session_id" type="string | None">
  User session identifier. `None` for anonymous sessions before identity linking.
</ParamField>

<ParamField path="user_id" type="string | None">
  External user identifier passed at session boot. `None` when the session is fully anonymous.
</ParamField>

<ParamField path="email" type="string | None">
  User email if available from the identity store.
</ParamField>

<ParamField path="actions" type="list[SlimAction]">
  Ordered list of UI actions in this batch. See [SlimAction](#slimaction) below.
</ParamField>

<ParamField path="count" type="int">
  Number of actions in this batch. Equals `len(actions)`.
</ParamField>

<ParamField path="forwarded_at" type="float">
  Unix timestamp (float) when the connector forwarded this batch.
</ParamField>

### `ActionsPayload.merge(payloads)`

Merges a non-empty list of `ActionsPayload` objects for the same session into one.

* Actions are concatenated and re-indexed sequentially from `0`
* `user_id` / `email` resolved from the first non-`None` value across all inputs
* `forwarded_at` set to the latest timestamp across all inputs
* Raises `ValueError` if `payloads` is empty

```python theme={null}
merged = ActionsPayload.merge([payload_a, payload_b])
# merged.actions == [*payload_a.actions, *payload_b.actions]  (re-indexed)
# merged.count   == len(merged.actions)
```

Used internally by `AsyncAgentContextWriter` when `debounce_ms > 0` to combine
payloads that arrive within the accumulation window before calling `write_actions`.

***

## SummaryPayload

Delivered when the connector's LLM summariser produces a prose description of a session.
Replaces the raw action list for context-window efficiency in RAG pipelines.

```python theme={null}
from autoplay_sdk import SummaryPayload

def on_summary(payload: SummaryPayload):
    print(payload.session_id)
    print(payload.replaces)    # how many actions this summary replaces

    # the prose summary string — pass directly to your embedding API
    text = payload.to_text()
```

**`to_text()` example output:**

```
The user navigated to the Dashboard, exported a CSV report, then opened
account settings to update their billing plan.
```

### Fields

<ParamField path="product_id" type="string" required>
  Connector product identifier.
</ParamField>

<ParamField path="session_id" type="string | None">
  User session identifier.
</ParamField>

<ParamField path="summary" type="string">
  Prose description of what the user did during this session.
</ParamField>

<ParamField path="replaces" type="int">
  Number of individual actions this summary condenses.
</ParamField>

<ParamField path="forwarded_at" type="float">
  Unix timestamp when the connector forwarded this summary.
</ParamField>

***

## SlimAction

A single UI action inside `ActionsPayload.actions`.

```python theme={null}
for action in payload.actions:
    action.index            # 0, 1, 2 ... position in the session
    action.type             # "pageview", "click", "submit", "type", ...
    action.title            # "Page Load: Dashboard" or "Click Export CSV button"
    action.description      # "User landed on the dashboard page"
    action.timestamp_start  # unix float — when the action began
    action.timestamp_end    # unix float — when the next action began
    action.raw_url          # "https://app.example.com/dashboard?ref=email"
    action.canonical_url    # "https://app.example.com/dashboard"
    action.session_id       # PostHog session id (or None)
    action.user_id          # distinct id / user id (or None)
    action.email            # email from PostHog properties (or None)
    action.to_text()        # "[0] pageview: User landed on the dashboard page — ..."
```

### Fields

<ParamField path="index" type="int" default="0">
  0-based position of this action in the session sequence.
</ParamField>

<ParamField path="type" type="string" default="&#x22;&#x22;">
  Lowercase event type. One of `"pageview"`, `"click"`, `"submit"`, `"type"`, `"focus"`, `"blur"`.
</ParamField>

<ParamField path="title" type="string">
  Human-readable label for the event (e.g. `"Page Load: Dashboard"` or `"Click Export CSV button"`).
</ParamField>

<ParamField path="description" type="string">
  Natural-language description of what the user did (e.g. `"User landed on the dashboard page"`).
</ParamField>

<ParamField path="timestamp_start" type="float" default="0.0">
  Unix timestamp when this action began.
</ParamField>

<ParamField path="timestamp_end" type="float" default="0.0">
  Unix timestamp when this action ended (equals the next action's `timestamp_start`).
  For the last action in a batch this equals `timestamp_start`.
</ParamField>

<ParamField path="raw_url" type="string" default="&#x22;&#x22;">
  Original URL as captured, before canonicalization (includes query strings and fragments).
</ParamField>

<ParamField path="canonical_url" type="string">
  Normalised page URL with dynamic path segments collapsed to `:id`
  (e.g. `https://app.example.com/projects/:id`).
</ParamField>

<ParamField path="session_id" type="string | None">
  PostHog session id for this action. `None` when unknown (same semantics as batch-level `session_id`).
</ParamField>

<ParamField path="user_id" type="string | None">
  Distinct id or identified user id for this action. `None` when anonymous.
</ParamField>

<ParamField path="email" type="string | None">
  User email from PostHog identity properties when present.
</ParamField>

***

## Using `.to_text()` for embeddings

Both payload types expose `.to_text()` so you can embed either without branching:

```python theme={null}
from autoplay_sdk import ActionsPayload, SummaryPayload

def embed_any(payload: ActionsPayload | SummaryPayload):
    text = payload.to_text()         # works on both types
    embedding = embed_api.encode(text)
    vector_store.upsert(id=payload.session_id, vector=embedding)
```
