Documentation Index
Fetch the complete documentation index at: https://trigger.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Custom actions let the frontend send structured commands (undo, rollback, edit, regenerate) that modify the conversation state. Actions are not turns: they firehydrateMessages (if set) and onAction only. No turn lifecycle hooks (onTurnStart / prepareMessages / onBeforeTurnComplete / onTurnComplete), no run(), no turn-counter increment. The trace span is named chat action.
Actions wake the agent from suspension the same way a new message does, run their handler against the latest accumulator state, and emit a trigger:turn-complete chunk so the frontend’s useChat knows the action has been applied.
Defining an action handler
Define anactionSchema for validation and an onAction handler that uses chat.history to modify state:
actionSchema → hydrateMessages (if set) → onAction → apply chat.history mutations → emit trigger:turn-complete → wait for next message.
Returning a model response from an action
onAction can return a StreamTextResult, string, or UIMessage to produce a response. The returned stream is auto-piped to the frontend just like a normal turn, but the rest of the turn machinery (onTurnStart, onTurnComplete, etc.) still does not fire.
onAction itself; you have access to the streamed response object.
Gating actions on HITL state
If you have a human-in-the-loop tool waiting onaddToolOutput, you usually want to refuse competing actions like regenerate until the answer arrives. chat.history.getPendingToolCalls() gives you exactly that signal:
Sending actions from the frontend
actionSchema on the backend; invalid actions throw and surface as a stream error. The action parameter in onAction is fully typed from the schema.
For silent state changes that should never appear as a turn (e.g. injecting background context), use
chat.inject() instead. Actions are explicit user-driven mutations; injections are agent-side context updates.See also
chat.history— the imperative API actions use to mutate state- Sending actions from the frontend —
transport.sendActionergonomics hydrateMessages— fires beforeonActionwhen set- Branching conversations — pairs action handlers with backend-controlled history
- Human-in-the-loop — gating fresh actions while a tool is waiting

