Skip to content

Your own UI

Every agent already has a working browser page: a voice client for a voice agent, and a form per declared workflow for a workflow app. Come here when you want to show something of your own beside it — a cart, an order, a live form — or replace the page entirely.

You do that by adding a client.tsx. Add the file and you get the same shell with your own panel in it:

client.tsx
import { sessionSlot } from "@alexkroman1/aai";
import { mountClient, useAgentState } from "@alexkroman1/aai-ui";
import "@alexkroman1/aai-ui/styles.css";
// In your project this is one line — `import { cartSlot } from "./shared.ts"`.
// The slot is declared once, beside the agent, and both ends read the same
// object.
type Cart = { items: { sku: string; qty: number }[] };
const cartSlot = sessionSlot("cart", (): Cart => ({ items: [] }), {
view: (cart) => ({ count: cart.items.length }),
});
function CartPanel() {
const cart = useAgentState(cartSlot.projected);
return <p>{cart.count} items</p>;
}
mountClient({ sidebar: CartPanel });

aai dev builds it and aai publish ships it, with no extra step.

A slot is a named piece of session state. useAgentState reads whatever the agent projects from one declared sync: true, so declare a slot first or there is nothing to receive — see Remembering things.