In a development build, the SDK does three things it never does in production: it renders a thin onboarding banner over your app, it warns about the two mistakes that otherwise fail silently, and it tells the co-worker it is a dev session so it can help you build. Ship a production build and all three vanish — there is nothing to turn off, because a production bundle turns them off by construction.
Mode comes from the build, not a toggle
Dev mode is on whenever process.env.NODE_ENV !== "production" — the same signal your bundler already strips from the browser. It is deliberately not a per-coworker setting in the portal: a coworker is shared by every end-user of your deployed app, so a toggle there would show dev behaviour to your users. Mode is a property of the build, full stop. That also means a production bundle contains zero dev-banner bytes — the banner module is reached only from a dev-only branch, so your bundler tree-shakes it out.
The banner
The Provider renders it automatically — you mount nothing. It is a fixed strip across the top of the viewport (it never pushes your layout) with the five steps of the golden path — key · installed · connected · first action · go live. Each step is a button that opens a small popover: a live status line, one primary action, and one help link. While a session is live the installed step shows the integration-health readout (connected · N actions · N elements · surface: …) — the same line the SDK logs once to your console on connect. If a connect fails, the connected step shows the raw reason and status plus a link to the matching error-codes entry. Once the co-worker has acted the strip collapses to a small pill; dismissing it is remembered for that origin.
Hide it — without losing the rest
Two props, both on <CoworkkitProvider>. devBanner={false} hides only the strip while keeping the console readouts, the guards, and the agent's dev behaviour. dev overrides the whole mode: force it on for a staging build that ships as production, or off entirely.
"use client";
import { CoworkkitProvider } from "@coworkkit/react";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<CoworkkitProvider
getToken={getToken} // your token route — see Getting started
devBanner={false} // hide only the strip; keep the readouts + guards
// dev={true} // force dev mode on in a staging build that ships as production
>
{children}
</CoworkkitProvider>
);
}The two guards
The hook warning is a silent no-op in production and speaks only in a dev build; the mintSession guard warns in production and throws in a dev build:
- A hook outside the Provider. A
useAction/useElement/useSurfacemounted with no<CoworkkitProvider>ancestor registers nothing — so the co-worker “just talks and does nothing.” In dev the SDK warns once, naming the hook and the fix. - A secret key in the browser. Your tenant key is server-side only. If it rides a browser-exposed prefix (
NEXT_PUBLIC_/VITE_/PUBLIC_), the server-sidemintSessionguard throws in development and warns in production (never refusing a live mint). It never prints the key.
The co-worker in a dev session
When it’s a dev session, the co-worker knows it is talking to the developer, not an end-user. On the very first session it opens with one warm line naming its two roles — your build companion in here, and your app’s co-worker for your users. If nothing is declared yet, its first words say so and point you at the sample action (“paste the sample action from the quickstart and say celebrate”). And when you ask for something you haven’t wired, it names the missing declaration for that request in one sentence — it never tutors the SDK and never claims it can edit code (that’s your coding agent). In production, with an empty catalogue, it stays a plain talk-only co-worker and never announces its own incompleteness.
This layer is ours to gate: a fleet switch on our side turns the agent’s dev behaviour on or off across the fleet without a redeploy. The banner and the guards are entirely client-side — they follow your build, not our switch.
Staging from your server
A staging deployment is usually a real production build. Besides the dev prop, you can force dev mode from your token route by passing session: { dev: true } to mintSession — it rides the mint opaquely and is never echoed back. Leave it unset for real production.