AI workspace

BlockPro

A whole AI application surface: conversations down one side, the active transcript with reasoning, tool calls and sources in the middle, and the context — window usage, attachments and a structured result — on the other.

Contract review — Acme MSA

  1. You said:
    Summarise the termination and liability clauses, and flag anything unusual.
  2. Assistant said:
    **Termination (§14).** Either party may terminate for convenience with 90 days' written notice, or immediately for an uncured material breach after a 30-day cure period. **Liability (§11).** Each party's aggregate liability is capped at fees paid in the preceding 6 months — your template uses 12. Indirect damages are excluded on both sides. **Unusual:** the 6-month cap, and §11.4 carves data-breach costs out of the cap for you but not for them.
    1,284 tokens

A still, rendered at build time from the same story the tests run. The block itself is interactive; the copy that runs is the one the CLI installs.

Installation

The block is written to your blocks directory, and everything it is built from is installed alongside it. This one needs a licence: sign in once with the CLI and the install is the same command.

Terminal
pnpm dlx @dowel-ui/cli add ai-workspace

Built from

A block is not a black box. Every piece is a component you already have documentation for, and can change independently.

Props

AiWorkspaceBlock

PropTypeDefault
messages (required)

The transcript of the active thread.

WorkspaceMessage[]
threads (required)WorkspaceThread[]
activeThreadstring
attachmentsWorkspaceAttachment[][]
busy

A response is in flight.

booleanfalse
headerActions

Anything else for the top bar — a share button, a settings link.

ReactNode
modelstring
modelsModelOption[]
name

The application's name, at the top of the conversation list.

string"Workspace"
onAttach() => void
onModelChange(model: string) => void
onNewThread() => void
onRemoveAttachment(attachment: WorkspaceAttachment) => void
onSelectThread(id: string) => void
onSend(message: string) => void
onStop() => void
output

A structured result the conversation is filling in, shown beside it.

WorkspaceOutput
placeholderstring"Ask anything…"
tokenLimitnumber
tokensUsed

Context consumed so far, and the window. Both or neither.

number
waiting

Shown before the first token arrives.

booleanfalse
classNamestring

Accessibility

Three landmarks, each named: the conversation list is a navigation called Conversations, the transcript is the main content, and the context is a complementary region called Context, so a screen reader user can jump between them and skip the one they do not want. The transcript is a list and never a live region; the response state is announced from a separate status line, so a streaming answer does not read itself aloud token by token. Each attachment's remove button is named after its file. On a narrow screen the conversation list becomes a sheet with a focus trap and an Escape key, not a div slid over content that stays reachable by Tab.

Source

One file, written by dowel add ai-workspace with imports rewritten to your own path alias, and yours to edit from then on.

This is a Pro block.

The preview is the real block, rendered from its own story — a still of it, not a copy of it. The source is installed by the CLI once this machine is signed in with a licence key — dowel login checks the key against the registry before storing it — and lands in your project as a file you own, exactly like a free block.

Registry name: ai-workspace