Run your workspace
Tickets
Tickets are durable support records. Conversations expire after 24 hours; tickets persist forever. Use them for issues that need a human follow-up beyond the live chat window β billing disputes, bug reports, account problems, feature complaints.
How tickets get created
-
The bot opens one mid-chat via the
open_ticketLLM tool. Auto-enabled for agents whose vertical ishelp_center(theHelpCenterPresetships theticketingcapability the tool requires). Other verticals can opt in by addingticketingto the agent'svertical_overrides.capabilities. -
An operator-configured CTA of kind
open_ticketrenders a button inside the chat that opens a ticket directly when the visitor clicks it. Useful when you want a deterministic escalation path that doesn't depend on the LLM choosing the tool. - Inbox human-handoff β operators can convert a live conversation into a ticket from the Inbox UI when they realise it needs follow-up after the visitor leaves the page.
Ticket lifecycle
Status moves through four values backed by constants on
App\Models\Ticket:
| Status | Meaning |
|---|---|
open | Created, not yet picked up. Default on insert. |
pending | Assigned to an operator and being worked. |
resolved | Operator marked done. resolved_at stamped. |
closed | Archived. Hidden from default views. |
Priority is one of low, normal, high, urgent β set by the LLM at create time, mutable by operators.
Admin surface
Operators see workspace tickets at /app/tickets:
GET /app/ticketsβ paginated list, filter by status / priority / assignee. Workspace-scoped via theBelongsToWorkspacetrait.GET /app/tickets/{ticket}β single ticket with the linked conversation history if one exists.PATCH /app/tickets/{ticket}β change status, priority, assignee, or notes.
Schema
The tickets table (migration 2026_05_13_092105_create_tickets_table.php):
workspace_id,agent_id,conversation_id(nullable β operator-opened tickets needn't be tied to a chat).subject(β€ 120 chars),body.status(open / pending / resolved / closed),priority(low / normal / high / urgent).assigned_to_user_idβ nullable.metadataJSON β free-form bag for source-specific context (theopen_tickettool storessource: 'open_ticket_tool'; the CTA path stores the rule id; the human-escalation path stores the operator's id).resolved_atstamped when status flips to resolved.- Timestamps.
Linking back to chat history
Every ticket carries conversation_id when one is
available. The admin page renders the full chat thread side-by-side
with the ticket body so the operator can answer with the visitor's
own words for context β no "what did they actually ask?" hunt.
How the open_ticket tool works
See Tools & rich messages for the registry shape. The tool's input schema:
subjectβ required, β€ 120 chars.bodyβ required. The LLM is prompted to include the visitor's account / order references, what they tried, and what went wrong.priorityβ optional, defaults tonormal.
On invoke the tool inserts a Ticket row tied to the
current conversation and returns a confirmation the LLM weaves into
its final reply ("I've opened ticket #ABC-1234 for our teamβ¦").
Operators get a notification via the same channel they receive
new-lead pings.