Action Logs
Every backend action that fires from a tool — email sent, webhook called, file delivered — is recorded here as a log entry. Use this page to confirm side-effects actually ran, look up a specific complaint by tracking ID, debug failed deliveries, and audit what the AI did on the user’s behalf.
The Action Logs page is reachable two ways: from the project sidebar (Action Logs — shows every tool’s actions in one list with a tool filter dropdown), or from a specific tool’s edit page (Delivery History — same table and detail drawer, scoped to that tool but without the Tool or Response filters described below).
How Rows Group
One user-facing event (a complaint, a reservation, a feedback submission) typically fires multiple backend actions — say, an email to the CX team plus a webhook to the CRM. Even though the database records each action as its own row, the list view groups them under a shared tracking ID so you see one row per invocation, not one per action.
The Actions column shows small icons indicating which action types ran — green when at least one of that type succeeded, red when all of that type failed. Click the row to open the detail drawer; if the invocation had multiple actions, the drawer renders them as tabs (Email / Webhook), each with its own forensic data.
This means a single complaint that emails three CX inboxes and posts to the CRM shows as one row with 2/3 ✓ deliveries (two emails accepted, one bounced) and a webhook icon — instead of as four separate rows that all carry the same tracking ID.
Filters
The filter bar above the table accepts:
| Filter | What it does |
|---|---|
| Tracking ID | Exact match on the tool’s tracking ID (e.g. CMP-8984690258) — a fast, direct lookup, the primary CX use case (“the customer says they sent us CMP-X, find it”). |
| Tool (project-level page only) | Narrow to a single tool. Useful when you want every email/webhook for the complaints tool but not for, say, the bookings tool. |
| Status | success (everything fired ok), partial_success (mixed — at least one action succeeded and at least one didn’t), failed (every action of the invocation failed), skipped (a conditional rule blocked firing — see Conditional Actions). |
| From / To | Date range on when the action executed. The “To” filter is treated as inclusive end-of-day so a single-day range works as expected. |
| Recipient | Narrows to invocations whose email actions targeted this address. Use this when a CX teammate says “I never got the email about complaint X” — filter by their address and Status = Failed to find bounce/skip cases. |
| Search | Free-text match against subject + body (HTML and text). Helpful when the tracking ID isn’t known but a customer quoted a phrase from the email. |
| Response (project-level page only) | Filters by Response Channel thread status: Awaiting reply, Replied, or Closed. Rows from tools without a response channel never match a non-empty filter here, since they have no thread. |
Type freely; nothing fires until you press Search or hit Enter. Reset clears every filter and returns to the most recent invocations.
Pagination
The list shows 50 invocations per page with prev/next buttons and a Showing X–Y of Z counter at the top. Pagination operates at the action-row level (the API returns up to 50 rows per call); a single tracking ID’s actions are nearly always all on the same page, but if a high-fanout invocation happens to straddle a page boundary you may see the same group split — adjust the date range to narrow further when this matters.
Detail Drawer
Clicking a row opens a slide-in drawer with everything the system captured for that invocation. The top of the drawer shows shared metadata that’s identical for every action in the group — tool name, executed timestamp, expiration, tracking ID — followed by two identity cards and a conversation link (below).
If the invocation had a single action, the action’s content (body, deliveries, request/response) renders directly. If it had multiple actions, they render as tabs so you can flip between Email and Webhook details without losing the shared header above. Each tab carries its own Resolved config, AI decisions, and Parameters JSON viewers — they’re per-action snapshots, not shared.
End User & Session Context
Two separate cards sit above the per-action tabs:
- End User — the SDK’s explicit end-user ID and, if the app passes structured end-user data, its key/value pairs. This is the canonical identity lane: it’s never sent to the LLM (unless a tool’s Description references it with
{{endUser.*}}), and it’s what tracking/grouping and email-template substitution use. - Session Context — the full context blob the LLM actually saw for this invocation (the same data the AI used to decide what to do), shown as key/value pairs for audit purposes.
Email Tab
- Subject — the resolved subject line (after
{{...}}token substitution). - Preview — opens the full HTML body in a sandboxed dialog. The iframe runs with
sandbox=""(no scripts, no forms, no top-level navigation) so malicious HTML can’t escape. - Delivery details — one row per recipient with target email, the routing condition that selected this address (when present), the provider’s message ID, error message on failure, and sent-at timestamp. Color-coded provider status — green for
accepted/delivered/sent/queued, red forfailed/bounced/rejected/dropped, amber for anything else.
Webhook Tab
- Sent request — the resolved URL, method, headers (with sensitive values like
AuthorizationandX-API-Keymasked), and the JSON or form-data summary that was actually sent. Captured from the runtime, not reconstructed from config — what you see here is what the receiver saw. - Receiver response — HTTP status code + status text, response headers, and parsed response body (truncated at 2KB if larger). Use this to confirm the receiver acknowledged the request and to read its error response on failure.
Both sections are collapsible JSON viewers with a copy-to-clipboard button.
Conversation Link
The drawer’s Open conversation link deep-links into the Conversations page with the matching session pre-selected — useful for reading the full chat that produced this invocation.
Operator ↔ User Thread (Response Channel)
For tools that have the Response Channel enabled, the drawer shows an extra section: an append-only thread between your team and the end user, anchored to this log’s tracking ID.
- Status badge — one of Awaiting reply, Replied, or Closed.
- Thread — every message so far, oldest first. Operator messages and user follow-ups (submitted through the AI’s built-in follow-up tool) are visually distinguished, each with its author and timestamp. An operator message shows Seen by user once it’s been proactively surfaced to the end user in a later chat’s greeting, or Not yet seen until then. Proactive surfacing needs the project’s user-identity setting to be present in the SDK’s
userContext, so it can recognize the same person across sessions — without it, a reply never flips to “seen” even if the user looks it up manually, since the reactive status-lookup tool doesn’t mark it seen either. - Append Reply — adds your typed message to the thread and moves the status to Replied. If the end user can be identified across sessions, their next chat’s greeting mentions the reply; either way, they can look it up directly with the tracking ID via the AI’s status-lookup tool.
- Close Thread — moves the status to Closed. A closed thread accepts no further replies from the operator side; if the user submits another request it starts a new thread.
What Each Log Captures
Beyond the visible columns, each log row stores enough forensic data to answer questions weeks after the fact:
- Tracking ID — the per-invocation reference number, used for fast lookup via the filter above.
- Conversation ID, Session ID, End user ID — tracing back into the chat platform.
- Session Context — a snapshot of the full
contextdata the AI saw at the moment the action fired (PII-redacted at capture time); shown in the Session Context card. The email action’s “User context keys to include” allow-list only controls what’s rendered into the email itself — it doesn’t limit what’s captured here. - End user data — the SDK’s structured end-user profile data, distinct from Session Context; shown in the End User card, never forwarded to the LLM unless a tool’s Description references it with
{{endUser.*}}. - Subject and body — for email actions, the rendered message that went to the recipient.
- Request and response — for webhook actions, the full HTTP request/response (sensitive headers masked, body truncated at 2KB).
- Resolved config — the action’s config after template substitution (e.g.
subjectPrefix: "[Complaint] TRK-..."rather than"[Complaint] {{tool.trackingId}}"). - AI decisions — when conditional firing was used, the AI’s decision payload — which targets matched, the per-action fire/skip decision, and the AI’s reasoning.
Sensitive headers (Authorization, X-API-Key, X-Auth-Token, Cookie) are redacted at capture time — what’s stored and shown is a masked value like Bearer ab12***xx, never the full token. The auto-set X-Qafka-Signature is also masked.
Why You’ll Open This Page
- Verifying delivery — a customer says they didn’t get the booking email — was it sent and bounced, or never sent? The log answers in one click.
- Tracking lookup — a customer references
CMP-8984690258; paste it into the Tracking ID filter to land directly on that invocation’s row. - Webhook debugging — your CRM webhook returned 500; the Sent Request + Receiver Response panels show the exact payload and response so you can reproduce locally.
- Compliance audit — someone asks “did our system send X person’s data anywhere?” — the log is the source of truth, including which
userContextkeys were forwarded and which recipients each email action reached. - Conditional routing audit — when a tool uses conditional actions or multi-target email routing, the
decisionsJSON viewer in the detail drawer shows the AI’s choice and reasoning.
Retention
Action logs auto-expire on a per-project window — default 30 days. A daily job deletes expired entries (and their per-recipient delivery details) automatically; once deleted, they’re gone. Export or archive externally if you need to keep records longer than the retention window. There’s no dashboard control for changing the window yet — ask if you need a different value for your project.