Document selected-agent chat docs

This commit is contained in:
Dotta committed 2026-06-16 10:02:04 +00:00
1 parent 67649878d2
commit c35ba20ee4
5 files changed
+67 -12

No files matched your search

+4 -1
View File
@@ -346,6 +346,9 @@ Agent orchestration has subtleties in how you coordinate who has work checked ou
**Do agents run continuously?**
By default, agents run on scheduled heartbeats and event-based triggers (task assignment, @-mentions). You can also hook in continuous agents like OpenClaw. You bring your agent and Paperclip coordinates.
**Can I chat with my CEO?**
Yes, when Conference Room Chat is enabled. It is still issue-backed Paperclip work: the room resolves a `board_chat` issue, posts your message as an issue comment, and wakes a real selected agent by `targetAgentId` with the CEO as the default target.
<br/>
## Development
@@ -389,7 +392,7 @@ See [doc/DEVELOPING.md](doc/DEVELOPING.md) for the full development guide.
- ⚪ Work Queues
- ⚪ Self-Organization
- ⚪ Automatic Organizational Learning
- ⚪ CEO Chat
- ✅ Issue-backed CEO / selected-agent chat
- ⚪ Cloud deployments
- ⚪ Desktop App
+26
View File
@@ -124,6 +124,32 @@ These browser suites are intended for targeted local verification and CI, not th
For normal issue work, start with the smallest targeted check that proves the change. Reserve repo-wide typecheck/build/test runs for PR-ready handoff or changes broad enough that narrow checks do not cover the risk.
## Selected-Agent Conference Room Verification
The Conference Room is an experimental UI surface, but its transport is ordinary issue work. It is enabled through `Instance Settings > Experimental > Conference Room Chat`, or by patching the experimental instance setting:
```sh
curl -X PATCH http://localhost:3100/api/instance/settings/experimental \
-H 'Content-Type: application/json' \
-d '{"enableConferenceRoomChat":true}'
```
Maintainers should verify the flow as issue-backed selected-agent chat:
1. Open `/board-chat` after enabling the setting.
2. Confirm the page resolves or creates a `board_chat` issue through `POST /api/board/chat/conversations`.
3. Send a message. The UI posts to `POST /api/issues/:issueId/selected-agent-chat/comments`.
4. Confirm the request targets the selected real agent by `targetAgentId`; if omitted, the server defaults to the company CEO.
5. Confirm history is the issue's comments, live output comes from `/api/issues/:issueId/active-run?targetAgentId=...` and `/api/issues/:issueId/live-runs?targetAgentId=...`, and next-step cards are normal issue-thread interactions.
Targeted regression commands:
```sh
pnpm vitest run server/src/__tests__/issue-selected-agent-chat-routes.test.ts
pnpm vitest run server/src/__tests__/board-chat-conversations-routes.test.ts server/src/__tests__/board-chat-route-authz.test.ts
pnpm vitest run ui/src/components/SelectedAgentChat.test.tsx ui/src/pages/BoardChat.test.tsx
```
## One-Command Local Run
For a first-time local install, you can bootstrap and run in one command:
+12 -1
View File
@@ -101,6 +101,17 @@ See [SPEC.md](./SPEC.md) for the full technical specification and [TASKS.md](./T
Paperclip’s core identity is a **control plane for autonomous AI companies**, centered on **companies, org charts, goals, issues/comments, heartbeats, budgets, approvals, and board governance**. The public docs are also explicit about the current boundaries: **tasks/comments are the built-in communication model**, Paperclip is **not a chatbot**, and it is **not a code review tool**. The roadmap already points toward **easier onboarding, cloud agents, easier agent configuration, plugins, better docs, and ClipMart/ClipHub-style reusable companies/templates**.
## Conversational Work Surfaces
Some Paperclip surfaces feel conversational, but they still use the same issue/comment control-plane model:
- The issue detail chat tab is the issue's comment thread with run, interaction, and work-product context rendered inline.
- The Conference Room is a board-facing entry point backed by ordinary company-scoped `board_chat` issues. History is issue history, not a separate conversation store.
- Sending a Conference Room message posts a comment to the backing issue and wakes a real selected agent through `targetAgentId`. If no target is supplied, Paperclip selects the company's CEO.
- Agent replies are real agent-authored issue comments and their live work is shown from the target agent's active run for that issue.
This is why "Chat with CEO" still resolves to strategy threads, decisions, tasks, approvals, and work products. It is a fast path into the work graph, not a board-concierge subsystem or a general-purpose chatbot.
## What Paperclip should do vs. not do
**Do**
@@ -131,7 +142,7 @@ Paperclip’s core identity is a **control plane for autonomous AI companies**,
The default UI should answer: what is the company doing, who is doing it, why does it matter, what did it cost, and what needs my approval.
3. **Conversation stays attached to work objects**
“Chat with CEO” should still resolve to strategy threads, decisions, tasks, or approvals.
“Chat with CEO” should still resolve to issue-backed strategy threads, decisions, tasks, approvals, and work products.
4. **Progressive disclosure**
Top layer: human-readable summary. Middle layer: checklist/steps/artifacts. Bottom layer: raw logs/tool calls/transcript.
+17 -2
View File
@@ -35,7 +35,7 @@ These decisions close open questions from `SPEC.md` for V1.
| Board | Single human board operator per deployment |
| Org graph | Strict tree (`reports_to` nullable root); no multi-manager reporting |
| Visibility | Company-scoped visibility: board + all in-company agents can see all work objects by default; public/private deployment flags affect external exposure only and do **not** imply project/issue privacy |
| Communication | Tasks + comments only (no separate chat system) |
| Communication | Tasks + comments only (no separate chat system). Conversational surfaces such as the Conference Room are issue-backed and wake real selected agents by `targetAgentId` (CEO by default). |
| Task ownership | Single assignee; atomic checkout required for `in_progress` transition |
| Recovery | Liveness/watchdog recovery preserves explicit ownership: retry lost execution continuity where safe, otherwise open visible source-scoped recovery actions by default, use issue-backed recovery only for independent repair work, or require human escalation (see `doc/execution-semantics.md`) |
| Agent adapters | Built-in `process`, `http`, local CLI/session adapters, and OpenClaw gateway support; external adapters can also be loaded through the adapter plugin flow |
@@ -632,12 +632,26 @@ All endpoints are under `/api` and return JSON.
- `POST /issues/:issueId/admin/force-release` (board-only lock recovery)
- `POST /issues/:issueId/comments`
- `GET /issues/:issueId/comments`
- `POST /issues/:issueId/selected-agent-chat/comments` (board-only; add a comment and wake a real selected agent, defaulting to the company CEO when `targetAgentId` is omitted)
- `GET /issues/:issueId/live-runs?targetAgentId=:agentId`
- `GET /issues/:issueId/active-run?targetAgentId=:agentId`
- `POST /companies/:companyId/issues/:issueId/attachments` (multipart upload)
- `GET /issues/:issueId/attachments`
- `GET /attachments/:attachmentId/content`
- `DELETE /attachments/:attachmentId`
### 10.4.1 Atomic Checkout Contract
### 10.4.1 Selected-Agent Issue Chat Contract
Selected-agent chat is a thin board-user convenience over normal issue work:
1. The board posts `body` to `POST /api/issues/:issueId/selected-agent-chat/comments`.
2. `targetAgentId` is optional. When omitted, the server selects the most recently created non-terminated CEO agent in the issue company.
3. The target agent must belong to the issue company and must not be paused, terminated, or otherwise unavailable.
4. The server persists the board message as a normal issue comment, writes activity, and wakes only the selected target agent with `selectedAgentChat: true` and a stable `taskKey` of `selected-agent-chat:{issueId}:{targetAgentId}`.
5. The UI reads durable history from `GET /api/issues/:issueId/comments`, reads issue-thread interactions from the normal interactions endpoints, and scopes live-run polling with `targetAgentId`.
6. If another selected-agent chat target is already running for the issue, retargeting returns `409 selected_agent_chat_target_active` unless the caller explicitly requests interruption.
### 10.4.2 Atomic Checkout Contract
`POST /issues/:issueId/checkout` request:
@@ -721,6 +735,7 @@ The current app also exposes V1-supporting surfaces for:
- issue thread interactions (`suggest_tasks`, `ask_user_questions`, `request_confirmation`)
- issue approvals, issue references/search, labels, read state, inbox/archive state, and work products
- Conference Room conversation issue resolution through `POST /api/board/chat/conversations` (experimental `enableConferenceRoomChat`; resolves or creates a `board_chat` issue for the selected-agent chat surface)
- execution workspaces, project workspaces, workspace runtime services, and workspace operations
- routines and scheduled/API/webhook triggers
- plugin installation, configuration, state, jobs, logs, webhooks, and plugin database namespace migration
+8 -8
View File
@@ -1,6 +1,7 @@
// @vitest-environment jsdom
import { act } from "react";
import type { ReactNode } from "react";
import { flushSync } from "react-dom";
import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { Agent } from "@paperclipai/shared";
@@ -81,13 +82,13 @@ describe("SelectedAgentChatView", () => {
});
afterEach(() => {
act(() => root.unmount());
flushSync(() => root.unmount());
container.remove();
vi.clearAllMocks();
});
function render(node: React.ReactNode) {
act(() => root.render(node));
function render(node: ReactNode) {
flushSync(() => root.render(node));
}
it("renders the real selected-agent identity in the header", () => {
@@ -131,7 +132,7 @@ describe("SelectedAgentChatView", () => {
(b) => b.textContent === "Try again",
);
expect(retry).toBeTruthy();
act(() => retry!.dispatchEvent(new MouseEvent("click", { bubbles: true })));
flushSync(() => retry!.dispatchEvent(new MouseEvent("click", { bubbles: true })));
expect(onRetry).toHaveBeenCalledOnce();
});
@@ -144,9 +145,8 @@ describe("SelectedAgentChatView", () => {
"Sarah",
);
const send = container.querySelector('[data-testid="send"]') as HTMLButtonElement;
await act(async () => {
send.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
flushSync(() => send.dispatchEvent(new MouseEvent("click", { bubbles: true })));
await Promise.resolve();
expect(onSend).toHaveBeenCalledWith("hello");
});