AgentUIServer and pass the object straight to the component, with no type wrapper: every call the UI makes, including the createTurn event stream, hits your endpoints.
Because server accepts an AgentUIServer directly, you can front any backend — including your own proxy that keeps API keys server-side. The object is used immediately, so there is no loading indicator on mount.
Minimal implementation
The shape below is the smallest thing that mounts. Optional methods are omitted; required ones must exist even if they only throw in paths your UI never reaches. List methods return aListResult<T> — a plain object of { data, nextPageToken? }. There are no methods on it, so you can return a parsed JSON body directly as long as it carries those two fields.
server.ts
sandbox and skill as disabled is the honest starting point — the UI then hides those affordances instead of offering controls your backend cannot serve. Flip them on as you implement each.
App.tsx
Streaming
createTurn yields envelopes of the form { sequenceNumber, event } — not bare events. The number must increase monotonically within the turn, and it is what lets a reconnecting client resume via subscribeToTurn({ afterSequenceNumber }).
The minimum viable stream for one assistant reply is three events:
id. And a stream that ends without a turn.done leaves the UI showing the turn as still running.
Streaming events documents the full protocol — tool calls, approval prompts, sub-agent threads, and sandbox artifacts.
Pagination
ListResult<T> is { data: T[]; nextPageToken?: string }. Return the next cursor in nextPageToken; omit it (or leave it undefined) on the last page. Tokens travel the other way too — list requests accept a pageToken, which the SDK feeds back to fetch the following page.
nextPageToken in only when present keeps the result valid under exactOptionalPropertyTypes; assigning undefined to the optional field directly is rejected there.
listEvents additionally accepts lastTurnId, used when hydrating history for an existing session.
Optional capabilities
deleteSession / deleteAgent
deleteSession / deleteAgent
In a hand-written
AgentUIServer like the one above, omitting these leaves the corresponding affordances unavailable rather than broken. With createTrueForgeServer, an omitted deleteAgent throws when called.downloadSandboxFile
downloadSandboxFile
Return a
Blob. Required only if your agents produce sandbox artifacts users should be able to download.subscribeToTurn
subscribeToTurn
Resumes a live stream from
afterSequenceNumber, so a reconnecting client picks up where it left off instead of replaying the turn. Skip it if your backend cannot resume.catalog
catalog
Attach a
CatalogServer to enable the settings UI — models, connectors, skills, and sandboxes. Without it those surfaces do not render.Widening the types
The interfaces are generic so you can carry backend-specific fields through the UI without casting.AgentUIServer itself is a plain alias, so compose the widened chat and builder ports directly:
Attachments
Attachment handling defaults totrueForgeAttachmentAdapter. Override it through the adapters prop on TrueForgeUI if your backend stores uploads differently.