Repository navigation
feat(agents): one agent harness for meetings, chat and a new Agents app - #415
Conversation
Agents existed only as meeting seats, the chat had its own unrelated "custom prompt" styles, and Meetings opened on a bare channel list. This brings the agent concept the coding harnesses converged on (Hermes, OpenCode, T3 Code) into Launchstack and shares it across three surfaces. The harness: a persona is a full definition — description, mode (primary/subagent/all), a tool policy over retrieval/web/reasoning/ attachments, a response style, route, temperature, autonomy — and reads and writes as a markdown-with-front-matter file (export, import with explicit replace, reset to shipped). Ten starter agents seed every workspace idempotently; the original four handles are kept so stored transcripts resolve. Meetings: the pane lands on a dashboard (three steps, nine workflow recipes grouped by intent, live/recent rooms, the roster). Workflows carry phases the collab engine enforces — goal, turn budget, optional speakers — computed from the turn index so meetings replay from their log; the room gains a Plan panel, phase announcements in the transcript and a run-to-the-end loop. Chat: an Agent pill picks who holds the chat, `@handle` summons another agent for one turn with a completion menu, the query route resolves the agent (mention wins), applies its tool policy, prepends its instructions above the style prompt and echoes it back for attribution. Sessions store the agent on the chat and on each turn. Also: a Studio "Agents" app with a try-it playground through the real chat route; hand-offs between Agents, Meetings and Chat through the pane context; auth-free harnesses at /dev/agents and /dev/meetings; migration 20260923042425 (additive); ADR-013. Verified: typecheck clean, lint at 59 warnings (was 63), 24 affected suites green (3,088 tests in the full run; the one other failure, brand/ logo-consistency, is pre-existing on main), both migration sets applied to a throwaway Postgres and exercised by scripts/probe-agent-harness.ts, and the dashboard, room, Agents app and composer exercised in the browser. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a27c4300-ccea-437d-9fd4-dd39f9426a7b) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d26c4e3ae0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const webSearch = request.webSearch && agentAllows(agent.tools, "web"); | ||
| if (request.webSearch && !webSearch) notes.push("web search is off for this agent"); | ||
| const thinking = request.thinking && agentAllows(agent.tools, "reasoning"); | ||
| if (request.thinking && !thinking) notes.push("extended reasoning is off for this agent"); | ||
| const attachmentsDropped = request.hasAttachments && !agentAllows(agent.tools, "attachments"); |
There was a problem hiding this comment.
Enforce the retrieval tool denial
When an agent is configured with tools.retrieval: false, this resolver gates web search, reasoning, and attachments but never carries or enforces the retrieval denial. The AIChat route therefore still runs documentEnsembleSearch/multiDocEnsembleSearch and sends workspace passages to the model, despite the Agents editor promising that disabled tools may not be used. Add retrieval to the resolved turn and bypass document lookup/context construction when it is denied.
Useful? React with 👍 / 👎.
| ALTER TABLE "pdr_ai_v2_collab_agent_persona" ADD COLUMN "mode" varchar(16);--> statement-breakpoint | ||
| ALTER TABLE "pdr_ai_v2_collab_agent_persona" ADD COLUMN "tools" jsonb;--> statement-breakpoint | ||
| ALTER TABLE "pdr_ai_v2_collab_agent_persona" ADD COLUMN "style" varchar(24);--> statement-breakpoint | ||
| ALTER TABLE "pdr_ai_v2_collab_agent_persona" ADD COLUMN "builtin" boolean DEFAULT false NOT NULL;--> statement-breakpoint |
There was a problem hiding this comment.
Backfill built-in status for existing starter agents
On an upgraded workspace, the four previously seeded starter rows receive builtin = false, and ensureStarterPersonas skips them because their handles already exist. They consequently appear as custom agents and the Agents pane hides their Reset action; their newly introduced description/mode defaults also remain uninitialized. The migration or seeding path needs to recognize and backfill legacy starter rows without overwriting user-edited definition fields.
Useful? React with 👍 / 👎.
| const next = await sendControl("run", { limit: RUN_BATCH }); | ||
| if (loop.cancelled || activeId.current !== meetingId) break; | ||
| if (isTerminal(next.status) || next.status !== "running") break; |
There was a problem hiding this comment.
Stop the run loop after the current turn
When the user clicks “Stop after this turn” while this request is in flight, stopRunning only marks the outer loop as cancelled, but the current request has already asked the server to execute RUN_BATCH (three) turns. The cancellation check does not run until all three return, so the meeting can take two additional turns after the promised stopping point. Use one-turn requests while the UI offers per-turn stopping, or provide cancellation inside the server-side batch.
Useful? React with 👍 / 👎.
| export async function resetStarterPersona(companyId: bigint, personaDbId: string) { | ||
| const current = await getPersonaById(companyId, personaDbId); | ||
| if (!current) return null; | ||
| const starter = STARTER_AGENTS.find(agent => agent.key === current.id); | ||
| if (!starter) return null; |
There was a problem hiding this comment.
Preserve starter identity when handles are renamed
When a user edits a built-in starter's handle, the next roster refresh seeds a second agent under the now-missing original handle, while the renamed row remains marked built-in. Resetting that renamed row then fails because this lookup identifies the starter solely by its mutable current handle. Either prevent handle edits for starters or persist an immutable starter identity and use it for seeding and reset.
Useful? React with 👍 / 👎.
…orkflows Follow-up to the harness on review feedback. Tools are a list, not a fixed policy: `~/lib/agents/tools.ts` is the one registry (id, label, description, surfaces, per-turn toggle) that the editor's checklist, the badges, the definition file and the chat resolver read. An agent stores null (every tool, including later ones) or exactly the ids it may use; a list naming every tool collapses to null. The file writes `tools:` as a YAML list and reads OpenCode's map of booleans and Claude Code's inline list. Adding a tool is one entry plus the route that honours it. Response style is an agent setting. The chat's per-request style was not exposed anywhere; an agent now carries its own, and the only chat-level style left is `chat.responseStyle` — a registry setting (workspace or member, under Settings → Agents) for the default assistant when no agent is picked, read by the query route. Every starter agent's instructions now follow a named method with sources (DACI + blue hat; Tetlock's superforecasting habits + fabric analyze_claims + Chain-of-Verification; MetaGPT's Architect + Google design docs; ISO 31000 + the contract-review order; WBR input/output metrics + burn multiple; Working Backwards + Cagan's four risks; Dunford positioning; MEDDIC + Challenger; the Mom Test + JTBD forces; Schwenk's meta-analysis on devil's advocacy with Nemeth's authentic-dissent caveat). The Agents app shows the basis under the instructions. Agents have pictures: `avatar_url` on the persona, an `AgentAvatar` component everywhere an agent is drawn (roster, cards, chat pill, @ menu, transcript, seats, plan panel, palette), and ten public-domain artworks from Wikimedia Commons as defaults (public/agents, CREDITS.md), offered in the editor's gallery alongside an https URL or initials. Workflows are proven recipes only: DACI decision, Six Thinking Hats, Lightning Decision Jam, Klein's pre-mortem, Working-backwards PR/FAQ review, Sequoia pitch review, 4Ls retrospective, customer discovery synthesis (Mom Test + JTBD), Amazon WBR, OKR setting, plus open discussion. Each names its origin and where it is used; the dashboard cards and the dialog show it. No workflow builder, on purpose. Agents are searchable from the command palette: "Ask X" picks the agent in the composer, "Open X in Agents" selects it in the Agents app. Migration regenerated (still unmerged, additive) to add avatar_url. ADR-013 and the design artifact updated. Tests: tool registry and list semantics, file round-trips for every starter with both spellings, picture URL rules, starters' basis and on-disk pictures, workflow provenance; 28 touched suites green, typecheck and lint clean on every touched file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_4fbfa6af-23b2-454d-8d43-0d220a61caa4) |
Adopts main's lucide-only icon set and the renamed display class in the files this branch rewrote; keeps the extracted AgentEditor, the meetings dashboard and the new-meeting dialog. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_8ab380f4-5379-447f-829a-0305cde50d8e) |
…ent harness branch Regenerates the harness migration after main's user_profiles migration so the snapshot chain stays intact (idx 22, prevId = the profiles snapshot); meeting transcripts now draw humans with the shared profile avatar and agents with the agent avatar. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b7e637b5-e02e-49be-b806-b81ea270e749) |
Every starter agent's system prompt is now a prompt file people already run with language models, stored verbatim from its source: fabric's pattern files (MIT — summarize_meeting, analyze_claims, review_design, explain_terms_and_conditions, create_prd, analyze_sales_call, analyze_product_feedback) and awesome-chatgpt-prompts (CC0 — Business Risk & Scenario Analyzer, Advertiser, devil adv). The only edits are a dropped trailing input marker or sample first request; each agent records its source (name, file, url, license, adaptation) and a test asserts the source's opening line survives. The Agents page shows "Prompt source" under the instructions. The earlier research citations are gone from the agents, and the workflow notes keep only where each format is used. scripts/battle-test-agents.ts runs every starter prompt on one grounded question and then a ten-turn DACI meeting between five of them through any OpenAI-compatible endpoint. Against the deployment's primary route (Gemini 3.7 Flash via OpenRouter): 10/10 chat answers in role and grounded; the meeting closed on a recommendation with two named owners in 8 turns and the minutes extracted it. The run found an engine gap: the extractive minutes did not treat "Recommendation for the approver", "Option: …" or "Owner: …" as decisions and actions. Cues added, with a sentence-start rule so "please stress-test this option:" is not a decision; covered by __tests__/collab/minutes-cues.test.ts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_770d1f1c-b0d8-4ecf-8985-53355a6fe0c5) |
Next's route-export check rejects an optional first parameter
("invalid GET export"), which failed the CI and Docker builds. The
handler always receives a Request in production; only the unit test
called it bare, so it now builds one.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_4a0af4a6-38a5-4f03-997f-9c1884d0f72f) |
…ent harness branch Two keep-both conflicts: the palette row kind gains both "history" (main) and "agent" (this branch); the Studio pane context carries both the agents and the investors handoff blocks. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_cc17a761-8f36-407d-9edc-5733a13ebf9e) |
Summary
primary/subagent/all, a tool list drawn from one registry, a response style, a picture, route, temperature, autonomy — that reads and writes as a markdown-with-front-matter file. Ten starter agents seed every workspace. Every starter's system prompt is a prompt file people already run, stored verbatim: fabric's pattern files (MIT:summarize_meeting,analyze_claims,review_design,explain_terms_and_conditions,create_prd,analyze_sales_call,analyze_product_feedback) and awesome-chatgpt-prompts (CC0: Business Risk & Scenario Analyzer, Advertiser, devil adv). A test asserts each source's opening line survives; the Agents page links the file. Pictures are public-domain artworks. The same agents sit in meetings, answer in chat, are searchable from ⌘K, and can be tried on a new Studio Agents app.@launchstack/collab(goal, turn budget, optional speakers, computed from the turn index). The workflow set is meeting formats teams already run, each card naming where it is used: DACI decision, Six Thinking Hats, Lightning Decision Jam, pre-mortem, Working-backwards PR/FAQ review, Sequoia pitch review, 4Ls retrospective, customer discovery synthesis, Amazon WBR, OKR setting, plus open discussion. No workflow builder, on purpose.@handlesummons another agent for one turn (with completion), the query route resolves the agent, applies its tool list, prepends its instructions above its style and echoes it back for attribution; sessions store the agent on the chat and on each turn. Response style is an agent setting; the only chat-level style left ischat.responseStylefor the default assistant (Settings → Agents).apps/web/scripts/battle-test-agents.tsruns every starter prompt on the same grounded question and then a ten-turn DACI meeting between five of them, through any OpenAI-compatible endpoint. Against Gemini 3.7 Flash (the running app's primary route): 10/10 chat answers in role and grounded; the meeting closed on a recommendation with two named owners in 8 turns, and the minutes extracted it. The run surfaced one engine gap, now fixed: the extractive minutes did not recognise "Recommendation for the approver" / "Option: …" / "Owner: …" as decisions and actions.Design record: https://claude.ai/artifact/HjXNCsVYAepsoMkRg7MS6D (private until shared). ADR:
docs/architecture/ADR-013-agent-harness.md. Picture credits:apps/web/public/agents/CREDITS.md.Related
Builds on the roster + autonomy from #399 and the Studio tabs from #409.
Checklist
pnpm checkpasses (lint + typecheck) — typecheck clean; every touched file lints cleanpnpm --filter @launchstack/web testpasses — 53 touched suites / 487 tests green in the targeted run after the last merge of main; the collab suites (8 / 97) re-run green after the minutes change@launchstack/collabminor: meeting phases and minutes cues)BATTLE_*variables of its own, documented in the script)@menu — through the auth-free/dev/meetings,/dev/agents,/dev/ask-startersharnesses)Testing
__tests__/lib/agents/{tools,definition,agent-file,meeting-workflows,starter-agents}.test.ts,__tests__/collab/{meeting-phases,minutes-cues}.test.ts,__tests__/server/chat-agent.test.ts,_workspace/__tests__/AskPanel.agents.test.tsx, plus the existing collab, chat-query, scope-gate, sessions and settings suites.apps/web/scripts/probe-agent-harness.tsseeded the starters, edited one, created a phased meeting, reloaded it and stored a session with agents.scripts/battle-test-agents.tsagainst Gemini 3.7 Flash via OpenRouter — 10/10 prompts, meeting passed (report generated locally, not committed).Notes for reviewers
20260925030906_agent_harness_and_meeting_workflowsis additive (nullable columns oncollab_agent_personaincl.avatar_url,builtin boolean default false,collab_meeting.workflow_key/phases,agent_keyon sessions and messages). Regenerated after main'suser_profilesmigration so the snapshot chain is intact.null= every tool including later ones; a list = exactly those ids; naming every tool collapses tonull. Files accept a YAML list, OpenCode's boolean map, or Claude Code's inline list.🤖 Generated with Claude Code
Note
Medium Risk
Touches the main document Q&A route, collab orchestrator, and new persisted agent/meeting fields; behavior is guarded by validation and tests but the chat path is user-facing and broad.
Overview
Unifies workspace agents as a full harness (definition file import/export, ten seeded starters, tool registry, primary/subagent modes, avatars) and wires them through meetings, document Q&A chat, and a new Agents Studio surface.
Meetings can run phased workflows: each phase has a goal, turn budget, and optional speaker subset;
@launchstack/collabderives phase from turn index, narrows who may speak, announces transitions, and persistsworkflowKey/phaseson create. Minutes extraction now treats approver-style closings (Recommendation:,Option:,Owner:, etc.) as decisions and actions.Chat gains an agent pill,
@handleone-turn summons with completion, and the AIChat query route resolves the agent (mention wins over composer), applies tool/route/style/temperature policy, prepends system instructions, and returns attribution; sessions storeagent_keyon the thread and messages.Supporting work: additive DB migration, collab/meetings APIs validation via
phasePlanProblems, dev browser simulators (/dev/agents,/dev/meetings), probe and battle-test scripts, and ⌘K agent rows.Reviewed by Cursor Bugbot for commit 9f4b54e. Bugbot is set up for automated code reviews on this repo. Configure here.