Help Desk

Sidebar Actions

Python that runs when an agent presses a button in the conversation sidebar.

A sidebar action is Python owned by a single sidebar widget. The widget draws a button; pressing it runs the action against that conversation.

They are the counterpart to custom actions: a custom action is offered to the AI, which decides when to call it. A sidebar action is only ever run by a human, and is never offered to the AI. An escalation that opens a ticket in someone else's system should not fire because a model thought it should.


Creating one

Sidebar actions are edited on the widget's own screen, under Settings → Sidebar Widgets → (your widget) → Actions. Names only need to be unique within that widget.

Your code must define execute_action(context):

def execute_action(context):
    """Runs when an agent presses this button."""
    team = context["args"].get("team", "web")

    summary = llm_summarize(
        context,
        prompt=f"Summarize this ticket for the {team} team.",
        max_words=120,
    )
    add_conversation_note(context, summary)
    add_conversation_tag(context, f"escalated-{team}")

    return f"Escalated to {team}."

context carries the same conversation, business and customer objects every other Python feature receives, plus args — the button's static args merged with any values the agent typed into a form.

Every built-in helper and all of your Python modules are available.


Wiring a button to it

From your widget code, reference the action by name:

"actions": [
    {
        "label": "Escalate to Web",
        "action": "escalate",
        "args": {"team": "web"},
        "confirm": "Open a ticket for the web team?",
        "variant": "primary",
    }
]

Add a form to collect input first — see form fields.

A button naming an action that does not exist fails only when it is pressed. Nothing checks the two against each other, because widget code is Python we cannot inspect ahead of time — so rename an action and its buttons together.


What the agent sees

Return a string and it becomes a toast. Return a dict to say more:

FieldTypeDescription
displaystr"toast" (default) or "markdown", which opens a modal
messagestrThe body. Markdown when display is "markdown".
titlestrTitle for the markdown modal
refreshboolRe-run the widgets afterwards (default True)
    return {
        "display": "markdown",
        "title": f"Escalated to {team}",
        "message": f"### {ticket_id} created\n\n[Open the ticket]({url})",
        "refresh": True,
    }

Set refresh: False when the action changed nothing the widget displays — it saves re-running every widget on the conversation.


Behaviour worth knowing

  • Double-presses are blocked. The same button with the same inputs cannot run twice at once on a conversation, so a double-click cannot open two tickets.
  • Only the return value reaches the agent. stdout, timings and tracebacks stay in the logs; use the action editor to see them while developing.
  • Secrets are scrubbed from output and return values, but never deliberately return one — see get_secret.

On this page