Start here

  • Getting started
  • Backends
  • Connect your coding agent
  • How it works

Declaring your app

  • Actions, surfaces & elements
  • Hand mode
  • Control & confirmation

Polish & operate

  • Appearance
  • The Watch panel

Reference

  • Advanced
  • Configuration
  • Browser & framework support
  • Troubleshooting & FAQ
All docs

Docs

The Watch panel

See what the agent sees and did — live turns, the action timeline, latency — an in-app devtool you drop in during a build.

CoworkkitWatch is a drop-in developer panel you mount during a build to see what the agent perceives and did. It reads the same internal session state the on-screen button does — no new wire, no instrumentation on your side — and renders it as a floating, resizable panel over your app. Because it reads the Provider's context, mount it anywhere inside CoworkkitProvider; where it sits in the tree doesn't matter.

It's the fastest way to answer the two questions every integration raises: does the agent actually see the surfaces and elements I declared, and did my actions fire — and gate — the way I intended?

Drop it in

It ships as a deep import so it stays tree-shakeable — the panel and its code never reach a bundle that doesn't import it. Add one line to the Provider you already have:

app/providers.tsx
"use client";

import { CoworkkitProvider } from "@coworkkit/react";
import { CoworkkitWatch } from "@coworkkit/react/watch";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <CoworkkitProvider
      getToken={async () => {
        const res = await fetch("/api/session", { method: "POST" });
        if (!res.ok) {
          // Check before parsing, and guard the parse: an error page (a proxy 404,
          // a framework 500) is often HTML, and a throw here would lose both fields.
          const body = await res.json().catch(() => ({}));
          // Pass the reason AND the status through — that is what lets the FAB say
          // "Setup needed" for a bad key instead of a generic "Can't connect":
          throw Object.assign(new Error(body.error ?? "session mint failed"), {
            reason: body.reason,
            status: res.status,
          });
        }
        return res.json();
      }}
    >
      {children}
      {/* Mounts only in development; ships nothing to a production build. */}
      <CoworkkitWatch />
    </CoworkkitProvider>
  );
}

Watch renders only in development, and it doesn't open on its own — it's a panel you toggle. Open it from the watch icon in the on-screen button's control row, or press ctrl+shift+k. If you've mounted it and don't see the watch icon, you're almost certainly on a production build, where Watch hides itself by default — that's expected, not a missing feature; It's a dev surface (below) shows how to force it on when you need it.

What it shows

A pinned State strip across the top — session phase, mic, Hand-mode arm state, the active surface, session duration and idle time — plus four tabs:

  • Timeline — the live event stream, turn by turn: each action call, how it was gated (allowed, Hand-blocked, or held for a confirmation), and its outcome. This is where you watch an action actually fire, or catch the needs_hand_mode that explains why it didn't.
  • Catalogue — the live declared-exposure snapshot: the current surface, every mounted element (including see-only ones), and the full action catalogue with each entry's kind and control. This is what proves the agent sees what you declared — and it marks the declared-vs-live distinction, so a snapshot taken before the agent joins isn't mistaken for "the agent already knows".
  • Transcript — the conversation, both sides, as the agent heard and spoke it.
  • Metrics — per-turn latency, a turn table, and a session summary, for spotting a slow leg without reaching for a profiler.

It's a dev surface

Watch is gated to NODE_ENV === "development" by default — in a production build it mounts nothing, so leaving <CoworkkitWatch /> in your tree is safe. Two escapes exist for when you need it past dev: enableInProduction for a QA build, and visibleTo — a predicate over your own auth that must return true before anything renders (pair it with the redact policy to mask transcripts and tool I/O).

The header's copy and download buttons emit the whole session — state, timeline, transcript, metrics — as a single JSON blob. That's how you hand a teammate the exact observable state you're looking at: send them the export instead of narrating what you saw.

PreviousAppearanceNextAdvanced

Machine-readable: this page as Markdown · all docs (llms.txt)