Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 21 additions & 31 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ this repo:
- **Inference** — LLM calls (`@intx/inference`).
- **Workflow runtime** — definitions, runs, and the workflow host
(`@intx/workflow`, `@intx/workflow-host`, `@intx/workflow-deploy`).
- **Mail** — the transport every agent run, including a workbench's own,
uses to receive and send messages.
- **Mail** — the transport an agent turn uses to receive and send
messages. A workbench itself is not a mail-holding host run.

Workbench adds product contracts on top of these primitives; it never
forks or patches Interchange internals. See [docs/TENANCY.md](docs/TENANCY.md)
Expand Down Expand Up @@ -67,33 +67,26 @@ workbench's own child tenancy (native tenants carry no `kind` field), and
[docs/GLOSSARY.md](docs/GLOSSARY.md) for the term mapping between product
nouns and platform primitives.

## Conversation as a folded workflow run

A workbench is not a parallel messaging system bolted onto Interchange —
it is an ordinary folded, credential-free interactive workflow run whose
only job is to hold a mailbox. Creating a workbench launches that run (its
**workbench host**, sometimes called its anchor); the host's system prompt
forbids it from ever replying or acting — it exists purely to give the
conversation a durable, listable mailbox. Reading that mailbox back in
order is the conversation's timeline.

Because a workbench is an ordinary run, it goes through the same launch,
addressing, and mail machinery any other interactive agent run uses — no
parallel transport is invented for chat. An invited agent participant
replies by emitting `connector.reply` events on its own stream; a reply
bridge turns those events into timeline messages, mirroring how an
`@mention` fans a message out to an agent participant. See
[docs/CHAT.md](docs/CHAT.md) for the full message, thread, and
participant model built on top of this run. Per-workbench settings (name,
participants, capacity, connector overrides, notification prefs — see
PRODUCT.md's "Workbench settings") are composition on top of this same
run and its tenant, not a separate object; the surface lives in
`packages/chat-ui`'s `workbench-settings`.
## Conversation as workbench data

A workbench is not a parallel messaging system bolted onto Interchange,
and it is not itself a workflow run. Creating a workbench mints a child
tenant and writes settings rows — no deploy, no host, no anchor instance
(`provisionSpaceWorkbench` and the chat create path). A workbench holds a
**timeline** of `chat.workbench_messages` rows; posting is one insert plus
one publish onto the workbench's live stream, so the conversation takes
messages whether or not any agent process is running.

**Direction (CL-6093):** today a workbench's run is "settle-and-wake" —
the anchor run settles between deliveries and wakes on the next mail
event. This is the current mechanism, not a permanent constraint; see
CL-6093 for where the self-anchored run model is headed next.
A workbench's address is derived, not resolved. Asking an invited agent
for a turn is a separate act over Interchange mail; the agent replies by
emitting `connector.reply` events on its own stream, and a reply bridge
turns those events into timeline messages. See
[docs/CHAT.md](docs/CHAT.md) for the full message, thread, and
participant model. Per-workbench settings (name, participants, capacity,
connector overrides, notification prefs — see PRODUCT.md's "Workbench
settings") are composition on top of this tenant and its settings rows,
not a separate object; the surface lives in `packages/chat-ui`'s
`workbench-settings`.

**Streaming a reply.** An agent's live reply reaches the timeline through
one path, deltas to pixels:
Expand Down Expand Up @@ -156,9 +149,6 @@ does not maintain a parallel scheduler.

## Open questions

- The exact shape of the CL-6093 self-anchored run model beyond
"settle-and-wake today" is not yet documented in this repo — treat it
as in-flight design, not a settled architecture.
- Sidecar placement policy specifics (how a run is assigned to a
particular sidecar instance under multi-sidecar deployment) are not
detailed in the docs reviewed for this pass.
11 changes: 10 additions & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ column and no collapse affordance — it is always present, at a fixed width.

Top to bottom:

1. **Brand row** — logo mark and a "New workbench" button (`+`).
1. **Brand row** — logo mark and a "New workbench" button (`+`) that
opens `/new`.
2. **Bench list** — the "Workbenches" label, then rows of workbench
conversations, with search built into the list itself. Nothing
page-scoped ever renders in this body; it lists conversations, not
Expand Down Expand Up @@ -54,6 +55,14 @@ consumed by both). A route that gets renamed or relocated leaves a redirect
behind at its old path — old links and bookmarks always land somewhere
real, never a 404.

**`/new` is the shipped create surface** (`NewWorkbenchPickerRoute`). The
primary act is a prompt: say what the workbench should do, or pick a
template shortcut underneath. The sidebar `+` and an empty-bench land on
`/` both open this route — there is no Describe door.

**`/inbox` is gone as a page** (CL-6151). The path stays as a redirect
home so old links still resolve; it is not a live groups inbox.

## Tables & Lists

The default shape for "many of the same thing" is a data table, not a card
Expand Down
57 changes: 27 additions & 30 deletions PRODUCT.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Product

Corbits Workbench is the multiplayer workspace for humans and agents — a
team and its AI agents working side by side, with the same conversations,
routines, and inbox. It is the default implementation of the Corbits
team and its AI agents working side by side, with the same conversations
and routines. It is the default implementation of the Corbits
Platform, built on [Interchange](https://github.com/faremeter/interchange).

## The one concept
Expand Down Expand Up @@ -36,9 +36,10 @@ column at a time:
bench, flat, most-recently-active first. There is no separate "channels"
vs. "chats" grouping the sidebar exposes to a person — every row is a
workbench.
- **"+ New Workbench" always creates.** It never opens a picker of existing
things to join — starting a new workbench is the one way in, whether the
result is a one-on-one conversation with an agent or a group conversation
- **"+ New Workbench" always creates.** It opens `/new` — the shipped
prompt-primary picker — never a picker of existing things to join.
Starting a new workbench is the one way in, whether the result is a
one-on-one conversation with an agent or a group conversation
with people and agents together.
- **Agents are templates.** Starting a new agent conversation means picking
an agent definition (a named, reusable capability) as the starting point
Expand All @@ -48,29 +49,24 @@ column at a time:
it carries account-wide surfaces (approvals, recent activity) that stay
visible regardless of which workbench is open.

## First run (CL-6104)
## First run

A brand-new account is walked through four steps, ending in a live
conversation rather than an empty shell:
A brand-new account is walked through login and a credential connect, then
lands on the create surface rather than an empty shell:

1. **Login.**
2. **Credential** — connect a model provider (one-click OAuth for
supported providers, or a pasted API key); see `packages/onboarding`.
3. **Describe** — a single free-text field asking what the first agent
should do. No name field, no template picker: a name and a handle are
derived from the description, and submitting drafts an agent
definition the same way `CreateAgentPanel` does
(`draftAgentDefinition` → `createAgentDefinition`, CL-6074/CL-6086).
See `apps/web/src/pages/describe-first-workbench.tsx`.
4. **Greeting** — the drafted agent is deployed and opened into a fresh
conversation, and its first reply introduces itself and names what it
can do. There is no separate screen for this step: the drafted system
prompt itself carries the instruction (see
`packages/agent-directory/src/agent-definition-drafting.ts`), so the
greeting arrives as an ordinary streamed reply in the new workbench.

A bench that already has one or more workbenches skips straight past step
3 and 4 and lands in its existing conversation instead (see
3. **Create** — `/` hops an empty bench to `/new`, the prompt-primary
picker (`apps/web/src/pages/new-workbench-picker.tsx`). A prompt box is
the primary act: typing a goal and submitting creates a blank
workbench and sends that text as the first message. Prefab template
rows underneath are one-click shortcuts, not a kind-then-Create
second step. There is no Describe door and no
`describe-first-workbench.tsx`.

A bench that already has one or more workbenches skips create and lands
in an existing conversation instead (see
`apps/web/src/pages/home-page.tsx`).

## Plugins and Skills
Expand All @@ -94,8 +90,8 @@ and capabilities; dedicated vs. shared inference capacity (CL-6117);
per-workbench connector and plugin overrides against the account default
(CL-6099); inference model/provider fallback order; applying a saved
config profile; per-person notification preferences for that workbench;
and archiving. See ARCHITECTURE.md's "Conversation as a folded workflow
run" for how a workbench's settings relate to its underlying run, and
and archiving. See ARCHITECTURE.md's "Conversation as workbench data"
for how a workbench's settings relate to its tenant, and
`packages/chat-ui`'s `workbench-settings` for the implementation.

## Routines, through conversation
Expand All @@ -109,12 +105,13 @@ again, on what schedule, and where the result should land. See

## Inbox and approvals

Two account-wide surfaces sit outside any single workbench:
Approvals sit outside any single workbench. Inbox does not:

- **Inbox** projects a person's mail into three groups — action, mention,
delivery — with mark-all-read and clear-done bulk actions. It is where
a mention or a routine's delivery lands once the triggering activity is
done. See `packages/inbox`.
- **Inbox is not a product page.** The groups UI (action / mention /
delivery) is gone. `/inbox` stays routable only as a redirect home
(CL-6151) so old links and bookmarks land somewhere real. The hub
inbox API (`packages/inbox`, `/api/tenants/:tenantId/inbox`) may still
exist as a backend; it is not a live groups page.
- **Approvals ("needs you")** surface a paused agent run waiting on a
human decision. There is no dedicated Approvals page — pending approvals
show up in the Activity band, a permanent section of the contextual
Expand Down
6 changes: 3 additions & 3 deletions docs/CHAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ event log. The shape lives in `@corbits/agent-runtime`
(`buildAgentRuntimeWorkflow`, `mode: "section"`), and
`platform-adapter.ts`'s `ROOM_AGENT_MODE` is the single place that pins
it — one switch feeding both the wake and the relaunch path. The
workbench host keeps the folded step shape: it holds a mailbox and never
takes a turn, so it has no occurrences to name.
workbench itself has no host run and no occurrences to name; only invited
agents deploy as sections.

`onBodyFailure: "continue"` — authored in the section shape itself — is
the failure edge: a turn that ends `failed` records the failed occurrence
Expand Down Expand Up @@ -332,7 +332,7 @@ following routes:

| Method & path | What it does |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /workbenches` | Mints the workbench's own tenant, launches its host, writes its initial settings, and — for a chat — joins its one counterpart (an agent or a person; see [Chats and direct messages](#chats-and-direct-messages-dms)) |
| `POST /workbenches` | Mints the workbench's own tenant, writes its initial settings, and — for a chat — joins its one counterpart (an agent or a person; see [Chats and direct messages](#chats-and-direct-messages-dms)) |
| `GET /workbenches` | Lists the tenant's workbenches, optionally filtered by kind |
| `GET /workbenches/:id/messages` | Reads the workbench's timeline, decoded into parts, paginated by cursor |
| `POST /workbenches/:id/messages` | Posts a message, fanning a copy to every @mentioned agent participant. `threadId` or `inReplyToMessageId` route it into a thread instead of the root feed; a reply that would nest past depth 2 is a `409 conflict` |
Expand Down
Loading