How a voice session runs.
Your server starts the session; the audio never touches it.
It talks to your users, sees their screen, and does real work beside them. The integration is front-end — no AI backend to build. Live in a weekend.
A real co-worker in a demo store. Mic required.
Recreated from orbit, our demo store — same products, same actions the live co-worker calls.
Peel back any card to see the code behind it.
How a voice session runs.
Your server starts the session; the audio never touches it.
Only what you declare.
useSurface({
label: `Search: ${query}`,
data: {
results: results.length,
maxPrice: "$50",
},
cue: "Help them pick a gift.",
});It knows what you declare: the page and its key facts. No screenshots, no DOM scraping.
useAction({
name: "addToCart",
description: "Add an item to the cart.",
parameters: {
type: "object",
properties: { id: { type: "string" } },
required: ["id"],
},
run: ({ id }) => cart.add(id),
});Your own code runs, in their signed-in session. It picks the action by its description.
useElement({
name: "sort",
state: { sortedBy: sort },
actions: {
byPrice: () => setSort("price"),
byRating: () => setSort("rating"),
},
});Its state is always live to the co-worker. Working the control waits for Hand mode.
useSurface({
label: "Workspace setup",
data: { stepsDone: 0, stepsTotal: 4 },
cue: "They're new and haven't started.",
chimeIn: true,
});Once per new place, only when they arrive on their own. Off by default.
<CoworkkitProvider
tokenUrl="/api/coworkkit/session"
onActionRecord={(r) => {
// "placeOrder" · "hard" · "confirmed"
audit.log(r.action, r.control, r.gate);
}}
>
{children}
</CoworkkitProvider>One record per action: what ran, how it was gated, what happened. Add your user id and store it.
useSurface({
label: "Product page",
// runs only while Hand mode is on:
handActions: ["addToCart"],
});Every element action waits for it too. The page's edges light up while it's on.
useAction({
name: "placeOrder",
description: "Place the order.",
control: "hard",
confirmationSummary: () =>
`Pay ${cart.totalLabel} now?`,
run: () => checkout.placeOrder(),
});A card only the user can tap. A spoken “yes” doesn't count.
import { coworkkitSessionRoute }
from "@coworkkit/server/next";
import { requireUser } from "@/lib/auth";
// reads COWORKKIT_API_KEY on the server
export const POST = coworkkitSessionRoute({
getUserId: async () =>
(await requireUser()).id,
});Your key never reaches the browser. This route trades it for a short-lived session for exactly this user.
What it does, cards 1 to 3 of 9
import { coworkkitSessionRoute } from "@coworkkit/server/next";
export const POST = coworkkitSessionRoute({
getUserId: async () => (await auth()).userId,
});import { CoworkkitProvider } from "@coworkkit/react";
<CoworkkitProvider tokenUrl="/api/coworkkit/session">
{children}
</CoworkkitProvider>useAction({
name: "addToCart",
description: "Add a product to the cart by its id.",
parameters: { type: "object", properties: { productId: { type: "string" } } },
run: ({ productId }) => addToCart(productId, 1),
});npm install @coworkkit/react @coworkkit/serverNo AI backend to build. Live in a weekend. Read the quickstart
A monthly sandbox, no card. Batteries included; one all-inclusive rate as you grow.
A monthly sandbox
$0
100 co-worker minutes a month
Your first co-worker in production
$99/mo
500 co-worker minutes a month
A co-worker your users rely on
$499/mo
3,500 co-worker minutes a month
High-volume co-worker use
$1,499/mo
15,000 co-worker minutes a month
Every plan is the same runtime — plans differ by included minutes and support. The monthly rate is a commitment discount; top-ups are always the flat list price of $0.20/min. All prices in USD, excluding tax. VAT or sales tax is added at checkout based on your location. Custom volume, SSO or an SLA? Talk to us. How it compares.