CoworkkitProvider is the one component you mount. Only getToken is required — it is your closed-loop token route. Every other prop is optional and ships with a sensible default, so a bare Provider works out of the box. This page is the complete list.
<CoworkkitProvider getToken={getToken}>
{children}
</CoworkkitProvider>Placement & behavior
Where the button sits and how it moves.
fabPosition?: "bottom-right" | "bottom-left" | "top-right" | "top-left"; // default "bottom-right"
draggable?: boolean; // default true
zIndex?: number; // default 2147483640fabPosition— which corner the button anchors to. Default"bottom-right".draggable— let the user drag the button off its anchor; the new position persists across reloads. Defaulttrue. Setfalseto pin it.zIndex— the stacking order of the button, its ring, and the page-edge glow. The default,2147483640, sits just under the 32-bit maximum so the overlays float above almost everything. Lower it only if the button covers an overlay of your own that legitimately needs to sit on top.
Confirmation & control
How actions are gated. Both are covered in depth under Control & confirmation — here are the two Provider-level knobs.
confirmationTimeout?: number; // default 60 (seconds)
defaultControl?: "open" | "soft" | "hard"; // default "open"confirmationTimeout— how many seconds ahardconfirmation may stay pending before the SDK resolves it astimeout(the handler never runs). Default60.defaultControl— the app-wide baseline for actions that declare nocontrolof their own and aren't caught by the destructive-name fail-safe. Default"open"(reads and benign actions run freely). Set"soft"to make the whole app ask-first; an explicit per-actioncontrolalways wins.
Appearance
look?: string | LookSpec; // brand the button (Studio look code or inline spec)
intensity?: "default" | "subtle" | "off"; // default "default"look— brand the button with your accent and dot style, via a Studio look code or an inline spec. See Appearance.intensity— the visual prominence of the button. Default"default"."subtle"dials it down — a fainter ring and a softer shadow;"off"removes the button entirely, an escape hatch to keep the Provider mounted without rendering the surface.
Wiring
Rarely set — the defaults are right for the common case.
getToken: () => Promise<SessionToken>; // required — your token route
cloudUrl?: string; // fallback control base
fallbackSurface?: (pathname: string) => Surface; // derive a surface from the URL
onActionRecord?: (record: ActionRecord) => void; // observe every settled actiongetToken— the one required prop: an async function that returns a minted session from your server. The tenant key stays server-side; it never reaches the browser. See Getting started.cloudUrl— normally omitted. A live session already carries the control base it was minted against, and that value wins while a session is running; this prop is only the fallback for pre-session and session-less (dev) configs.fallbackSurface— derive a surface from the current pathname when a route declares nouseSurfaceof its own.onActionRecord— called once per settled action with a record of what ran, how it was gated, and the outcome. The SDK emits; you persist it (your DB or SIEM). The Watch panel shows the same record in dev with no wiring.
Note there is no apiKey prop. The tenant key is secret and server-side, held by your getToken route — putting it in the browser is exactly what the closed-loop model exists to prevent.