Vercel UI SDK
When an agent drives an interface built with Vercel's UI SDK, the controls you mark wait for a named person to decide in Deliverd.
UI SDK (@ui-sdk/*) is Vercel's component library for React, Vue, Svelte, Solid and web components. Its agent bridge, createAgent, lets an AI agent read your page and press buttons or fill fields, directly or through WebMCP in the browser. You mark the controls an agent must not use alone with data-agent-confirm, and the bridge asks its allow hook before it touches them. Deliverd answers that hook with a real person.
How it works
- The agent tries a control marked
data-agent-confirm. UI SDK callsallowand waits. deliverdAllowsends the step to your own server route. The browser never holds your agent key.- Your route,
uiSdkApprovalRoute, asks Deliverd. The approver reads the mark's sentence, the control and the values, from the email, Slack or Teams. - A yes lets the step run. A no, a wait that runs out or a route that fails all leave the control untouched, and UI SDK tells the agent the person said no.
Set it up
- 1
Install the SDK
Run
npm install @deliverd/sdkand setDELIVERD_API_KEYon the server to an agent key (Agents → your agent → Keys). Use an agent key, not a personal one, so the person who started the agent can still approve. - 2
Mark what needs a person
Put
data-agent-confirmon each control an agent must not use alone, with a sentence written for the approver. For a confirm dialog, mark the button that confirms, not the trigger. - 3
Add the route
Add a
POSTroute that callsuiSdkApprovalRoute. It works as a Next.js route handler and in anything else that takes a fetch-styleRequest. - 4
Connect the bridge
Pass
deliverdAllowasallowwhen you create the bridge, in client code only. If you also register WebMCP tools, passallow: () => truetoregisterTools, so the person is asked once, not twice.
The mark
<AlertDialogClose value="confirm" data-agent-confirm="Deletes the project and all its files" > Delete forever </AlertDialogClose>
The route
// app/api/deliverd/ui-approval/route.ts
import { Deliverd } from "@deliverd/sdk";
import { uiSdkApprovalRoute } from "@deliverd/sdk/adapters";
export const maxDuration = 800;
export const POST = uiSdkApprovalRoute({
deliverd: new Deliverd(), // reads DELIVERD_API_KEY
approvers: ["ops"],
timeout: "13m",
});The bridge
"use client";
import { createAgent } from "@ui-sdk/react/agent";
import { deliverdAllow } from "@deliverd/sdk/adapters";
export const agent = createAgent({
allow: deliverdAllow({ endpoint: "/api/deliverd/ui-approval" }),
// UI SDK gives up after 5 minutes unless you raise this.
timeout: 15 * 60_000,
});Timing
Three clocks have to agree: the route's timeout (four minutes by default), your platform's function limit (maxDuration on Vercel) and the bridge's own timeout (five minutes by default). Keep the route's the shortest, so it can answer no before it is cut off. The request expires when the route stops waiting, so nobody approves a step the agent has given up on, and each ask is its own request, so an approval never carries over to a later step.
Options
| Option | Where | What it does |
|---|---|---|
endpoint | deliverdAllow | Your route's address. |
when | both | Which steps go to a person. Default: steps on a data-agent-confirm mark. Change it in both places, since the route refuses any step outside its own when. |
headers | deliverdAllow | Extra headers for your route, such as a CSRF token. |
onAnswer | deliverdAllow | Told each answer, so the page can show a person's reason for a no. |
approvers | uiSdkApprovalRoute | Who decides: people, teams or groups. Your organisation's admins when omitted. |
describe | uiSdkApprovalRoute | What the approver reads. Built from the mark's sentence and the step when omitted. |
timeout, expiresIn | uiSdkApprovalRoute | How long to wait, and how long the request stays open. Both four minutes by default. |
flowId, metadata | uiSdkApprovalRoute | Put each ask on a flow's timeline, or tag it for your own records. |
More on the SDK itself is in SDKs.
Try it on your own agent.
Free to start, no card. Sign up with Google, Microsoft or GitHub, and the first page after hands you an API key.