Actions, Events and Functions
An action defines what happens when a user interacts with a component by triggering either an event or a function. Events prompt the agent to respond with UI updates, while functions execute specific logic on the renderer or agent. Functions can also run outside user actions, such as property bindings, validation checks, and agent requests.
Actions
An action is an interaction handler property on an interactive UI component, such as Button.action on Button, that runs when a user interacts with that component (for example, clicking or tapping a button).
An action determines how user interaction is handled:
- An event notifies the agent of user intent by sending an outbound
actionmessage. Use an event when the agent needs to decide what happens next and stream UI or data updates back to the client (such as confirming an order or booking a reservation). - A function invokes a registered catalog operation directly without starting a new agent conversation turn. The function can execute locally on the renderer (such as opening a link with
openUrl) or run remotely on the agent viacallAgentFunctionto perform a discrete backend check (such as verifying inventory).
See Action in the protocol schema for the action structure.
| Aspect | Event | Function |
|---|---|---|
| Action property | action.event | action.functionCall |
| Purpose | Prompts the agent to process intent and update UI | Triggers specific logic on the renderer or agent |
| Triggered by | A user gesture on a component action | Actions, property bindings, validation checks, or agent |
| Runs on | The agent, after an action message | The renderer, or the agent via callAgentFunction |
| Agent turn | Starts a new agent conversation turn | Runs without starting an agent turn |
| Result | The agent decides next steps and updates UI | A typed return value, or a local side effect |
Events
Events inform the agent that a user interacted with a component and prompt the agent to respond. When a user clicks or taps a component configured with an event (such as a “Book flight” button), the client sends an action message to the agent. The agent processes the interaction, makes any required decisions or backend updates, and streams back updated UI components or data.
When dispatching an event, the client performs the following tasks:
- Reads any context values attached to the event (such as the flight number or selected seat) and resolves data bindings against the current surface data model.
- Evaluates an optional human-readable
userMessagedescribing what the user did (for example,"Confirmed flight reservation for Alex Rosario", formatted withformatString). - Sends an
actionmessage to the agent containing the event name, source component, timestamp, resolved context, and optional user message.
If the surface is configured to share its data model, the client also attaches the full surface state to outbound messages so the agent has complete visibility into what the user sees. See Data Model and Data Binding for details.
The following example shows a confirmation Button declaration and the outbound action message the renderer sends when the user clicks it.
Button component declaration:
{ "id": "confirm_button", "component": "Button", "child": "confirm_label", "variant": "primary", "action": { "event": { "name": "confirmReservation", "userMessage": { "@call": "formatString", "args": { "value": "Confirmed flight reservation for ${/passenger/fullName}" } }, "context": { "flightNumber": "UA-402", "seat": {"@path": "/selection/seatNumber"} } } }}Outbound action message sent on click:
{ "version": "1.0", "action": { "name": "confirmReservation", "surfaceId": "booking_surface", "sourceComponentId": "confirm_button", "timestamp": "2026-11-02T03:45:00Z", "userMessage": "Confirmed flight reservation for Alex Rosario", "context": { "flightNumber": "UA-402", "seat": "14B" } }}Button component declaration:
{ "id": "confirm_button", "component": "Button", "child": "confirm_label", "variant": "primary", "action": { "event": { "name": "confirmReservation", "context": { "flightNumber": "UA-402", "seat": {"path": "/selection/seatNumber"} } } }}Outbound action message sent on click:
{ "version": "v0.9", "action": { "name": "confirmReservation", "surfaceId": "booking_surface", "sourceComponentId": "confirm_button", "timestamp": "2026-11-02T03:45:00Z", "context": { "flightNumber": "UA-402", "seat": "14B" } }}Functions
Functions execute specific logic or calculations on either the client or the server. Unlike events, which start an agent turn to generate or update entire UI surfaces, functions are focused operations that compute a value, validate input, access local state, or trigger a local operation. Every available function is declared in a catalog, defining its name and expected parameters.
Function types
Functions run either locally on the client renderer or remotely on the agent.
When evaluating a function call, the client checks whether the function is registered locally in its catalog. If a local implementation exists, the client runs it immediately without making a network request. If the function is not implemented locally, the client routes the call to the agent via callAgentFunction and awaits the response.
Renderer functions
Renderer functions are implemented locally by the client renderer and registered with its catalog. Some types of renderer functions are:
- Validation functions that check input values or form readiness against constraints, such as required fields or email formatting.
- Data transformation functions that format numbers, dates, currency, or strings, or evaluate boolean logic before displaying values on screen.
- Local data access functions that read client-side state or template context not stored in the surface data model, such as an item’s position inside a list template or device screen dimensions.
- Local action functions that perform client-side operations in response to user gestures, such as opening a URL in the browser.
These examples illustrate common functions available in the Basic Catalog. See the Basic Catalog functions specification for the full set of standard renderer functions, or define custom functions in your own catalog.
Agent functions
Agent functions run on the server rather than in the client application. They let UI components trigger discrete backend operations (such as checking real-time inventory or validating a coupon code) without starting a full conversation turn.
When a component calls an agent function, the following steps occur:
- The client sends a
callAgentFunctionrequest naming the function, its resolvedcatalogId, and its arguments. While waiting for the server, the client can display a pending or loading state. - The server executes the function logic and returns an
agentFunctionResponsecontaining either avalueor anerrorobject. - The client applies the returned
valueto the component property, validation check, or action. If the call returns an error, property bindings resolve tonulland report anerrormessage (code: "EXPRESSION_ERROR"with the failedfunctionCallId), validation checks mark the component as invalid, and in-progress component actions stop and reportEXPRESSION_ERRORwithfunctionCallId.
The following example shows an outbound agent function call to verify product stock:
{ "version": "1.0", "callAgentFunction": { "surfaceId": "checkout_surface", "functionCallId": "call_inv_check_881", "callFunction": { "@call": "checkInventory", "catalogId": "https://example.com/catalogs/store/v1/catalog.json", "args": { "sku": "SKU-99201", "quantity": 2 } } }}Calling functions
Functions can be invoked in four contexts:
- Component actions, when a user clicks or taps a component configured to execute a function directly.
- Property bindings, when a component property computes its display value from a function.
- Validation checks, when an input field or button evaluates rules before allowing user progress.
- Agent requests, when the agent asks the client to execute a local function on the device.
Component actions
A component action can execute a function directly instead of sending an event to the agent. For example, clicking this help button opens a support URL in the browser without contacting the agent:
{ "id": "help_link", "component": "Button", "child": "help_text", "variant": "borderless", "action": { "functionCall": { "@call": "openUrl", "args": { "url": "https://support.example.com/billing" } } }}{ "id": "help_link", "component": "Button", "child": "help_text", "variant": "borderless", "action": { "functionCall": { "call": "openUrl", "args": { "url": "https://support.example.com/billing" } } }}Property bindings
Component properties can compute their value from a function call. The client automatically re-evaluates the function whenever the underlying bound data changes. In this example, a text component formats an order subtotal into currency:
{ "id": "order_total_text", "component": "Text", "text": { "@call": "formatCurrency", "args": { "value": {"@path": "/order/subtotal"}, "currency": "USD" } }}{ "id": "order_total_text", "component": "Text", "text": { "call": "formatCurrency", "args": { "value": {"path": "/order/subtotal"}, "currency": "USD" } }}Validation checks
Interactive components like text fields and buttons can define validation rules. Each rule checks a condition (such as verifying required fields or checking email format) and provides an error message if the check fails. For buttons, failing any validation check automatically disables the button:
{ "id": "user_email_input", "component": "TextField", "label": "Email", "value": {"@path": "/formData/email"}, "checks": [ { "condition": { "@call": "required", "args": {"value": {"@path": "/formData/email"}} }, "message": "Email address is required." }, { "condition": { "@call": "email", "args": {"value": {"@path": "/formData/email"}} }, "message": "Enter a valid email address." } ]}{ "id": "user_email_input", "component": "TextField", "label": "Email", "value": {"path": "/formData/email"}, "checks": [ { "condition": { "call": "required", "args": {"value": {"path": "/formData/email"}} }, "message": "Email address is required." }, { "condition": { "call": "email", "args": {"value": {"path": "/formData/email"}} }, "message": "Enter a valid email address." } ]}Agent requests
The agent can also request the client to execute a function locally via callRendererFunction, for example to query device screen dimensions. The client runs the local function and always replies with a rendererFunctionResponse message containing the matching functionCallId and either value or error (even when the function’s return type is void):
{ "version": "1.0", "callRendererFunction": { "functionCallId": "hw_screen_001", "callFunction": { "catalogId": "https://example.com/catalogs/device.json", "@call": "getScreenResolution", "args": { "screenIndex": 0 } } }}Who can call a function
Because functions can trigger sensitive side effects (like opening a browser URL) or access device attributes, a catalog FunctionDefinition can control who is permitted to call it and whether it requires a direct user gesture:
- The
allowedCallersproperty restricts callers to"rendererOnly"(the default),"agentOnly", or"rendererOrAgent". For example,"rendererOnly"functions cannot be invoked remotely by the agent viacallRendererFunction, while"agentOnly"functions can only be called by the agent and cannot be used in component properties or actions. - The
requiresUserActivationproperty (which defaults tofalseand requiresallowedCallers: "rendererOnly"whentrue) restricts execution to a direct user tap or click on a component action, such asopenUrl. This prevents passive property bindings, validation checks, or incoming agent messages from triggering browser navigation without user intent.