schema: roster-assistant proposal contract (types + JSON Schema) #1210

Closed
opened 2026-05-15 17:01:40 +00:00 by architect · 0 comments
Collaborator

Context

Part of the Agents Roster AI Assistant feature. The assistant proposes complete fleets (one or more agents) as structured data; FE renders the preview and BE generates it from a Claude call. To keep accept-to-roster a direct write (no parsing), FE and BE must agree on a typed shape up front.

This is the contract ticket — it blocks every other ticket in the feature. Land this first.

Scope

Add a shared package (or shared module — wherever existing FE/BE types live in this repo) that exports:

ProposalEnvelope

  • proposal_id: string (uuid)
  • parent_proposal_id: string | null — set on refinements so FE can diff
  • session_id: string
  • version: number — bumped each refinement
  • created_at: string (ISO)
  • summary: string — short fleet-level narrative ("how these agents work together")
  • agents: ProposedAgent[]
  • refinements_used: number
  • refinements_soft_cap: number (default 20)
  • catalog_hash: string — snapshot identifier; FE warns if drifted at accept time

ProposedAgent

Shape must match the existing agent_config write path (audit the current roster store to confirm). Fields:

  • name: string
  • role: string (one sentence)
  • system_prompt: string
  • model_tier: "haiku" | "sonnet" | "opus" + model_tier_reason: string
  • skills: string[] (skill IDs from catalog)
  • tool_permissions: { tool: string; mode: "allow" | "deny"; rationale?: string }[] — per-grant rationale, not whole-agent
  • mcp_servers: { id: string; setup_required: boolean; setup_notes?: string }[]
  • rationale: string — one line, why this agent is in the fleet

CatalogSnapshot

  • skills: { id: string; name: string; description: string }[]
  • mcp_servers: { id: string; name: string; configured: boolean }[]
  • tools: { id: string; sensitive: boolean }[]
  • model_tiers: string[]
  • hash: string

Deliverables

  • TypeScript types exported from a shared module both FE and BE import
  • JSON Schema (draft 2020-12) for ProposalEnvelope — used by BE to constrain Claude's structured output
  • Unit tests covering: round-trip JSON, schema validation rejects malformed proposals, agent_config write path accepts a ProposedAgent as-is

Out of scope

  • Endpoint implementation (separate ticket)
  • FE rendering (separate ticket)
  • Catalog collection (separate ticket)

Notes for implementer

Audit the existing roster store before finalizing ProposedAgent — if agent_config has fields not listed above, mirror them. The goal is zero translation on accept.


Blocks: all other tickets in the Agents Roster AI Assistant feature.
Depends on: none.

## Context Part of the **Agents Roster AI Assistant** feature. The assistant proposes complete fleets (one or more agents) as structured data; FE renders the preview and BE generates it from a Claude call. To keep accept-to-roster a direct write (no parsing), FE and BE must agree on a typed shape up front. This is the **contract ticket** — it blocks every other ticket in the feature. Land this first. ## Scope Add a shared package (or shared module — wherever existing FE/BE types live in this repo) that exports: ### `ProposalEnvelope` - `proposal_id: string` (uuid) - `parent_proposal_id: string | null` — set on refinements so FE can diff - `session_id: string` - `version: number` — bumped each refinement - `created_at: string` (ISO) - `summary: string` — short fleet-level narrative ("how these agents work together") - `agents: ProposedAgent[]` - `refinements_used: number` - `refinements_soft_cap: number` (default 20) - `catalog_hash: string` — snapshot identifier; FE warns if drifted at accept time ### `ProposedAgent` Shape must match the existing `agent_config` write path (audit the current roster store to confirm). Fields: - `name: string` - `role: string` (one sentence) - `system_prompt: string` - `model_tier: "haiku" | "sonnet" | "opus"` + `model_tier_reason: string` - `skills: string[]` (skill IDs from catalog) - `tool_permissions: { tool: string; mode: "allow" | "deny"; rationale?: string }[]` — per-grant rationale, not whole-agent - `mcp_servers: { id: string; setup_required: boolean; setup_notes?: string }[]` - `rationale: string` — one line, why this agent is in the fleet ### `CatalogSnapshot` - `skills: { id: string; name: string; description: string }[]` - `mcp_servers: { id: string; name: string; configured: boolean }[]` - `tools: { id: string; sensitive: boolean }[]` - `model_tiers: string[]` - `hash: string` ## Deliverables - [ ] TypeScript types exported from a shared module both FE and BE import - [ ] JSON Schema (draft 2020-12) for `ProposalEnvelope` — used by BE to constrain Claude's structured output - [ ] Unit tests covering: round-trip JSON, schema validation rejects malformed proposals, `agent_config` write path accepts a `ProposedAgent` as-is ## Out of scope - Endpoint implementation (separate ticket) - FE rendering (separate ticket) - Catalog collection (separate ticket) ## Notes for implementer Audit the existing roster store before finalizing `ProposedAgent` — if `agent_config` has fields not listed above, mirror them. The goal is *zero translation* on accept. --- **Blocks**: all other tickets in the Agents Roster AI Assistant feature. **Depends on**: none.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/agent-hooks#1210
No description provided.