Is your feature request related to a problem? Please describe.
We need app-specific click behavior that does not map cleanly to the built-in action steps (@ToAssistant, @OpenUrl, @Run, @Set, @Reset). In our case, we want the model to say what happens when tapping a card: open a menu, post a message, reset the conversation etc.
Today, unknown @ calls are not evaluated as action steps. We work around this by preprocessing OpenUI Lang before render, rewriting syntax like:
Action([@OpenMenu(["option 1", "option 2"])])
into a plain object literal that our component reads from an action prop. That works, but it is brittle (regex/string rewriting), duplicates knowledge already in the system prompt, and is easy to get wrong while streaming.
Describe the solution you'd like
A public API to register custom action handlers, e.g.:
registerActionStep({
name: "OpenMenu",
description: "Opens a menu with the given options",
props: z.object({
options: z.array(z.string()),
}),
evaluate: (props) => ({
openMenu(props.options);
}),
});
Requirements:
- Registered steps appear in generated system prompts (like built-ins).
- They can be used inside
Action([...]).
- They dispatch to the host app via
onAction (or a similar callback), with a typed params payload.
- Unknown
@ steps fail clearly at parse/eval time instead of being silently dropped.
Describe alternatives you've considered
- Object literals in props — e.g.
{ intent: "product_select", name, variantId } on action: z.any(). Works, but is less ergonomic for the LLM and not documented as a first-class action pattern.
- Component-only handling — custom card components with explicit props instead of
Action([...]). More verbose in generated Lang.
- String preprocessing — rewrite Lang before
Renderer. Current approach; fragile and hard to maintain.
- Always use
@ToAssistant — sends a message immediately; cannot support intermediate UI like a product menu.
Is your feature request related to a problem? Please describe.
We need app-specific click behavior that does not map cleanly to the built-in action steps (
@ToAssistant,@OpenUrl,@Run,@Set,@Reset). In our case, we want the model to say what happens when tapping a card: open a menu, post a message, reset the conversation etc.Today, unknown
@calls are not evaluated as action steps. We work around this by preprocessing OpenUI Lang before render, rewriting syntax like:into a plain object literal that our component reads from an
actionprop. That works, but it is brittle (regex/string rewriting), duplicates knowledge already in the system prompt, and is easy to get wrong while streaming.Describe the solution you'd like
A public API to register custom action handlers, e.g.:
Requirements:
Action([...]).onAction(or a similar callback), with a typedparamspayload.@steps fail clearly at parse/eval time instead of being silently dropped.Describe alternatives you've considered
{ intent: "product_select", name, variantId }onaction: z.any(). Works, but is less ergonomic for the LLM and not documented as a first-class action pattern.Action([...]). More verbose in generated Lang.Renderer. Current approach; fragile and hard to maintain.@ToAssistant— sends a message immediately; cannot support intermediate UI like a product menu.