Skip to content

feat(agents): one agent harness for meetings, chat and a new Agents app - #415

Merged
Deodat-Lawson merged 7 commits into
mainfrom
claude/launchstack-meeting-agents-9c4960
Sep 26, 2026
Merged

Deodat-Lawson merged 7 commits into
mainfrom
claude/launchstack-meeting-agents-9c4960

Conversation

@Deodat-Lawson

@Deodat-Lawson Deodat-Lawson commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Brings the agent concept the coding harnesses converged on (Hermes / OpenCode / T3 Code) into Launchstack: an agent is a full definition — description, mode 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.
  • Meetings get a dashboard and phases enforced by @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.
  • Chat: an Agent pill picks who holds the chat, @handle summons 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 is chat.responseStyle for the default assistant (Settings → Agents).
  • Battle-tested against the deployment model. apps/web/scripts/battle-test-agents.ts runs 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 check passes (lint + typecheck) — typecheck clean; every touched file lints clean
  • pnpm --filter @launchstack/web test passes — 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
  • Changeset added (@launchstack/collab minor: meeting phases and minutes cues)
  • New env vars documented — none added (the battle test takes BATTLE_* variables of its own, documented in the script)
  • UI changes exercised in a browser (dashboard, a room run to the end with phase notes and the Plan panel, the Agents app with the verbatim prompt and its source block, the editor's tool checklist and picture gallery, the composer pill and @ menu — through the auth-free /dev/meetings, /dev/agents, /dev/ask-starters harnesses)
  • Docs updated — ADR-013, CREDITS.md

Testing

  • Unit: __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.
  • Persistence: both migration sets applied to a throwaway Postgres, then apps/web/scripts/probe-agent-harness.ts seeded the starters, edited one, created a phased meeting, reloaded it and stored a session with agents.
  • Live model: scripts/battle-test-agents.ts against Gemini 3.7 Flash via OpenRouter — 10/10 prompts, meeting passed (report generated locally, not committed).

Notes for reviewers

  • Migration 20260925030906_agent_harness_and_meeting_workflows is additive (nullable columns on collab_agent_persona incl. avatar_url, builtin boolean default false, collab_meeting.workflow_key/phases, agent_key on sessions and messages). Regenerated after main's user_profiles migration so the snapshot chain is intact.
  • Prompts are the source files. The engine and the chat route wrap them with the medium (room, objective, phase, grounding, channel etiquette), so a single-input prompt works as a meeting seat unchanged. Expect fabric's section headings in agent output; that is the prompt doing what it does.
  • Tool list semantics: null = every tool including later ones; a list = exactly those ids; naming every tool collapses to null. Files accept a YAML list, OpenCode's boolean map, or Claude Code's inline list.
  • Phases are engine facts; a plan the engine could not keep is refused by the API; meetings without phases are unchanged.
  • Minutes cues: "Recommendation for the approver", "we recommend", and a sentence starting with "Option:"/"Recommendation:" now count as decisions; "Owner:" and "X owns …" as action items. A mid-sentence "this option:" does not.
  • Deferred on purpose: streaming answers from agents, agent-to-agent delegation inside chat, per-agent model ids beyond the four routes, a workflow builder.

🤖 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/collab derives phase from turn index, narrows who may speak, announces transitions, and persists workflowKey / phases on create. Minutes extraction now treats approver-style closings (Recommendation:, Option:, Owner:, etc.) as decisions and actions.

Chat gains an agent pill, @handle one-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 store agent_key on 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.

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>
@vercel

vercel Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
launch-stack Error Error Sep 26, 2026 2:13am UTC
1 Skipped Deployment
Project Deployment Actions Updated
pdr-ai-v2 Ignored Ignored Sep 26, 2026 2:13am UTC

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-23T05:10:54.279795Z d26c4e3 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cursor

cursor Bot commented Sep 23, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +249 to +253
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");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment on lines +272 to +274
const next = await sendControl("run", { limit: RUN_BATCH });
if (loop.cancelled || activeId.current !== meetingId) break;
if (isTerminal(next.status) || next.status !== "running") break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment on lines +295 to +299
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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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>
@cursor

cursor Bot commented Sep 24, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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>
@cursor

cursor Bot commented Sep 24, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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>
@cursor

cursor Bot commented Sep 25, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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>
@cursor

cursor Bot commented Sep 25, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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>
@cursor

cursor Bot commented Sep 25, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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>
@cursor

cursor Bot commented Sep 26, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@Deodat-Lawson
Deodat-Lawson merged commit a6e0252 into main Sep 26, 2026
15 of 16 checks passed
@Deodat-Lawson
Deodat-Lawson deleted the claude/launchstack-meeting-agents-9c4960 branch September 26, 2026 02:28

This branch had an error being deployed

1 failed deployment
Preview – launch-stack — 9f4b54e9 Deployed Sep 26, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant