Ship an AI co-worker inside your web app.

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.

It lives inside your app.

Alexthe shopper
shop.demo.coworkkit.ai

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.

Behind the sceneshow-it-works

How a voice session runs.

CoworkkitEuropeagent · speechAmericasagent · speechAsia-PacificplannedCoworkkit APIcontrol planeplaces each sessionlive audioWebRTCactionsYour web appin the user's browser+ Coworkkit SDKyour actions run hereYour serverkeeps the API keyyour token routeasks fora sessionAPI keytoken

Your server starts the session; the audio never touches it.

Real-time voice.

Behind the scenessearch/page.tsx

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.

You decide what it sees.

Behind the scenesAddToCart.tsx
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.

It does the thing.

Behind the scenesSortMenu.tsx
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.

It uses your controls.

Behind the scenessetup/page.tsx
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.

It can speak first.

Behind the scenesproviders.tsx
<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.

It keeps a record.

Behind the scenesproduct/page.tsx
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.

Hands only when allowed.

Behind the scenesCheckout.tsx
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.

It asks first.

Behind the scenessession/route.ts
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.

It acts as the user.

What it does, cards 1 to 3 of 9

It can never do more than the user could.

  • As the signed-in user. It runs under their permissions — it can never do more than they could.
  • Hard actions wait. Mark an action hard and it waits for a click only the user can make.
  • Your key stays on your server. Sessions run in the EU or the US.

You bring the runtime; you pick the job.

  • OnboardingWalks every new user to their first success — by doing it with them.
  • In-app supportAnswers about the screen they're on, then fixes it instead of linking a doc.
  • Guided workflowsTakes users through the long, rare, easy-to-get-wrong tasks.
  • Interviews & feedbackAsks users what they think, in their own words, at the right moment.

Three files. That's the integration.

app/api/coworkkit/session/route.ts
import { coworkkitSessionRoute } from "@coworkkit/server/next";

export const POST = coworkkitSessionRoute({
  getUserId: async () => (await auth()).userId,
});
npm install @coworkkit/react @coworkkit/server

No AI backend to build. Live in a weekend. Read the quickstart

Start free.

A monthly sandbox, no card. Batteries included; one all-inclusive rate as you grow.

Free

A monthly sandbox

$0

100 co-worker minutes a month

  • Full SDK — voice, screen, actions
  • Hosted voice stack included
  • No card, no trial clock
  • 1 co-worker
Start free

Starter

Your first co-worker in production

$99/mo

500 co-worker minutes a month

  • Everything in Free
  • Top-ups at $0.20/min
  • Email support
  • Adjustable quotas
  • 2 co-workers
Get started

Growth

A co-worker your users rely on

$499/mo

3,500 co-worker minutes a month

  • Everything in Starter
  • Priority email support
  • Region affinity + Edge routing
  • Programmable quotas
  • 5 co-workers
Get started

Scale

High-volume co-worker use

$1,499/mo

15,000 co-worker minutes a month

  • Everything in Growth
  • Priority email support + a scheduled call
  • Unlimited co-workers
Talk to us

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.

Your app just hired a co-worker.