Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
There was a problem hiding this comment.
I'm very in favor of building this for v0.10 - it feels like it's a natural progression which fills in a hole we created re event handling.
I'm wondering if we can instead frame this feature as "server functions" vs "client functions"
- There is no-longer a concept of actions - instead buttons handlers just trigger a FunctionCall
- A FunctionCall can be one of two types - clientFunctionCall (already existing) or serverFunctionCall
- Server functions do not have to be predeclared in the catalog - agents can just specify arbitrary serverFunctionCalls as tap handlers etc, seeing as they know what types of functions they can handle.
- ServerFunctionCalls can be used as parameters for DynamicValues and composed with ClientFunctionCalls. This could be a way to do async loading of content etc. E.g. what if you have a weather UI with a drop down menu to pick the day, which updates the data model, then you have a maxTemp Text Component mapped to
fetchCurrentTempFromServer(/weatherData/day). - serverFunctionCalls have a list of named parameters, and the return type is implied by the receiver of the result
- serverFunctionCalls are expected to return a value asynchronously by default, even if it's a 'void' return value. There is a
fireAndForgetproperty to disable this. - serverFunctionCalls might have additional identifiers associated with them to route the request to the appropriate backend.
- ActionResponse message type is renamed to ServerFunctionResult
I think my suggestion is mostly cosmetic - things would basically work exactly as you have them here, except that server functions return a value (even if it's void) by default. I think returning a value by default could actually unlock some nice UX improvements, e.g. what if when you click on a button in the basic catalog, a little spinner appears in the button, which only resolves when the server has processed the event, rather than the current "fire and forget" approach which feels weird.
|
@gspencergoog WDYT? |
I prefer the callFunction and action naming. In A2A UI Events people were endlessly confused since I had remoteFunctionCall that could go both directions, repeatedly people wanted different names/concepts for client->server vs server->client. Just a quirk of developer psychology, I guess, but distinct terms reduce cognitive load.
Yeah this is how the PR works. The agent specifies the functions so it can ensure it meets the handler specs.
So right now it would be action { name="fetchCurrentTempFromServer", wantResponse="True" }
We have this in action.context
I'm fine with this. so wantResponse is True by default?
TBD. I think safest is the surface routes calls back to the agent/mcp server that created it, and that can route from there. We'd need to think about it (I'm always worried when a genui across trust boundaries can spam another server). Imagine if a Bard 3P agent made a genui in a bard textbox { onload: action { path='https://some-internal-service/drop-database' } } or spammed a competitor's API. By forcing the surface to route actions only back to the originating MCP server, we keep the trust boundary intact and ensure the client isn't tricked into executing arbitrary cross-origin requests.
See above I think keep separate names for client->server and server->client
Apologies for the AI slop, but for the spinner Mechanically, we'd have to decide how to string this together. We essentially have two paths:
I lean heavily toward #2. If we default to expecting a return value, the framework can give us these pending states for free without the agent having to micromanage the data model for every single interaction. |
Currently, client-to-server communication in A2UI is primarily fire-and-forget action messages. To support use cases like MCP Apps running in A2UI (where client can call tools and expect a return value) or standard client-to-server RPC usecases like Autocomplete (where order and responses matter) we need a synchronous round-trip RPC mechanism.
This proposal introduces actionResponse as the server-to-client corollary to functionResponse, enabling servers to respond directly to a client-initiated action.