Extend Persona Beyond Chat With Hooks
Persona has 13 render hooks that let you replace the message renderer, input composer, header, or launcher without forking. Build experiences that go far beyond a typical chat UI.
Chat is a good starting point. But the AI features your users actually want often go beyond a message thread.
Maybe your agent should render a 3D model when the user asks about a product. Maybe it should show a diagram instead of describing one in text. Maybe the input area needs custom validation before the message sends. Maybe the whole experience should look nothing like a "chat."
Persona's hook system makes all of this possible without forking the widget.
13 render hooks with priority ordering
Every major render surface in Persona exposes a hook. You can replace it, wrap it, or augment it. Here's the complete list:
renderMessage— Change how individual messages display. Render custom components, embed interactive elements, or transform the output format entirely.renderComposer— Add validation, custom buttons, or change the input behavior. Useful for structured inputs or guided workflows.renderHeader— Rebrand the widget chrome. Show status indicators, agent identity, or custom navigation.renderLauncher— Replace the trigger button with your own design or behavior.renderToolCall— Customize how tool invocations appear. Show rich previews, interactive results, or domain-specific visualizations.renderApproval— Customize the human-in-the-loop confirmation UI for sensitive actions.renderReasoning— Control how chain-of-thought and reasoning bubbles display.renderLoadingIndicator— Replace the loading state with your own animation or message.renderIdleIndicator— Customize what users see when the agent is idle.renderEventStreamView— Override the event stream inspector panel.renderEventStreamRow— Customize individual rows in the event stream.renderEventStreamToolbar— Replace the event stream toolbar controls.renderEventStreamPayload— Control how event payloads are rendered.
Hooks have priority ordering, so multiple plugins can coexist. A theming plugin and a custom renderer can both be active without conflicting.
Example: rendering rich content
Imagine your agent can generate diagrams. Without hooks, that diagram comes back as text or markdown. With a message render hook, you can intercept the response and render an actual interactive diagram.
// When the agent returns a diagram, render it interactively
const diagramHook = {
name: 'diagram-renderer',
priority: 10,
renderMessage: (message) => {
if (message.metadata?.type === 'diagram') {
const container = document.createElement('div')
renderDiagram(container, message.content)
return container
}
return null // Fall through to default renderer
}
}The same pattern works for 3D models, data visualizations, form builders, or any custom UI your product needs.
When embedding into existing products
Hooks are especially powerful when Persona is embedded inside a product that already has its own UI patterns. Instead of the widget feeling like a separate app, hooks let you weave it into the existing experience.
Use the composer hook to match your product's input patterns. Use the message hook to render responses using your own component library. Use the header hook to show contextual information from your app.
The design tokens carry through to hooked components, so your custom renders still respect the theme.
What you can build
- A support agent that renders interactive troubleshooting wizards
- A data assistant that shows charts and tables instead of describing them
- A product configurator where the agent updates a 3D preview in real time
- A document assistant that highlights relevant sections in a viewer pane
- An onboarding flow that guides users through setup steps with validation
The chat paradigm is the default. Hooks let you evolve past it.
Register a hook, return a DOM node, and Persona handles the rest — priority ordering, theme token inheritance, and cleanup on destroy.