Skip to Content

← All archived intake epics

Intake: agentic-app-foundation

breakdown.md

Breakdown: Agentic app foundation — spin up apps/ai with a basic conversation

  • scope-slug: agentic-app-foundation · source: the agentic-layer architecture report (approved by David, 2026-08-27) + Jamie's instruction to cut a minimal first-win batch; no scope.md behind this batch.
  • initiative: Scale the bridge / objective: Q2-2026 Objective 3 — Validate Technical Infrastructure & Payout Flow
  • personas: Admin, CSM, SDM, Expert, Vendor, Customer

What I understood

David's agentic-interface concept was researched and the architecture settled: the agentic layer is a separate app (apps/ai, its own Vercel project, eventually ai.sustentus.com), living on top of and independently from the classic screens, sharing the Clerk session and the workspace packages. The full plan is phased; Jamie has asked for the smallest batch that produces a real first win: the app exists in the monorepo, deploys, sits behind sign-in, and a signed-in user can hold a basic streamed conversation built on the Vercel AI Gateway (AI SDK v6) and the @sustentus/ui AI primitives. Nothing more: no persona registers, no tenant-data tools, no conversation persistence, no auth-core lift — those are later batches. Two seams: the app scaffold (monorepo + deploy + sign-in gate) and the conversational interface on top of it.

Where it sits

Cross-cutting — this batch creates a new application rather than touching a service-journey step. Feature-role-matrix: none yet (the surface reads no domain entities in this batch). Lands as a new apps/ai plus small additions to turbo.json, root package.json, the root ESLint config, and the deployment/CI accounting docs.

Build order

  1. agentic-app-scaffold — new apps/ai Next.js app: monorepo wiring, sign-in gate, deployable shell — depends-on: none
  2. agentic-chat-interface — the basic streamed conversation via the AI Gateway using @sustentus/ui AI components — depends-on: agentic-app-scaffold

Parallelizable

A plain chain — stub 2 builds inside the app stub 1 creates.

Out of scope (whole scope)

  • Lifting the auth/tenant/permission core out of apps/web — the sign-in gate here is "authenticated user", nothing finer; role registers and the policy table arrive with the next batch.
  • Any tenant-data tools, the claim primitive, generated views, personas/registers, levers.
  • Conversation persistence (the chat is ephemeral) and per-tenant cost accounting.
  • Vercel AI Gateway funding — already cut as ai-platform-enablement/ai-gateway-billing-unlock; stub 2 is only live-testable once that ships (noted in its stub).
  • The ai.sustentus.com domain go-live decision and the Clerk production root-domain verification — operator actions recorded in the stubs' notes, not feature work.

_done/agentic-app-scaffold.md

Stub: Scaffold the agentic app

  • feature-slug: agentic-app-scaffold
  • scope: agentic-app-foundation
  • personas: Admin, CSM, SDM, Expert, Vendor, Customer
  • initiative: Scale the bridge / objective: Q2-2026 Objective 3 — Validate Technical Infrastructure & Payout Flow
  • depends-on: none
  • sequence: 1 of 2

Problem

The approved agentic-layer architecture calls for a separate app beside the platform — living on top of and independently from the classic screens — and no such app exists. Until it does, every agentic feature has nowhere to land: there is no seventh app in the monorepo, no deploy target, and no signed-in surface to build the conversation into.

Proposed change

Create apps/ai, the agentic layer's home, as a minimal but production-shaped Next.js app in the monorepo: it builds in CI alongside the other apps, runs locally on its own port, deploys as its own Vercel project, and every route sits behind the shared Clerk sign-in (same production instance as the platform — a signed-in platform user is signed in here too). The landed surface is a branded shell page confirming who is signed in; the conversation itself is stub 2. The classic apps are untouched.

Acceptance criteria (rough)

  • apps/ai builds green in the Quality workflow and has a working local dev command on its own port, without affecting any existing app's build or dev flow.
  • Visiting the deployed app while signed out redirects to sign-in; signed in, the shell page renders and reflects the signed-in user.
  • The app deploys as its own Vercel project, and an AI-only change does not trigger a platform (apps/web) rebuild — nor the reverse.
  • Deployment and repository docs account for the new app (the pages Ship's docs-sync names).

Out of scope (this feature)

  • The chat interface, any AI call, and any @sustentus/services data access — stub 2 and later.
  • Role-aware routing, a route-policy table, View As, and the auth-core lift out of apps/web.
  • The ai.sustentus.com production domain cut-over — the app ships on its Vercel domain until the operator attaches the subdomain.

Notes for Define

Decisions from the approved architecture report that bind this stub: separate app in the monorepo, own Vercel project (that boundary later carries the AI Gateway project budget), Clerk shared-session via the common production instance. Operator preconditions to flag at pickup, not build work: point the Vercel project at the app's directory, mirror the Clerk env vars, and verify the Clerk production instance's root domain is sustentus.com before any subdomain go-live. Note for pickup: a Vercel project named agentic-interface already exists (as does tenant-management), both rooted at apps/console — a directory not in the repo, so every push currently errors on them. Settle the app directory name with Jamie/David at pickup (apps/ai vs apps/console), then re-point or retire those projects so the stray errors stop; this stub assumes apps/ai until they say otherwise. Monorepo wiring the repo's conventions require: catalogue versions only, a per-app turbo dev task (only @sustentus/web#dev exists today), vercel.json with the standard turbo-ignore command, a root-ESLint block for the new app, and any new env var into turbo.json globalEnv in the same PR. touches: apps/ai (new), turbo.json, root package.json, eslint.config.ts, .icm/_shared/ci.md, apps/docs (deployment + repository-structure pages).

_done/agentic-chat-interface.md

Stub: Basic conversational interface in the agentic app

  • feature-slug: agentic-chat-interface
  • scope: agentic-app-foundation
  • personas: Admin, CSM, SDM, Expert, Vendor, Customer
  • initiative: Scale the bridge / objective: Q2-2026 Objective 3 — Validate Technical Infrastructure & Payout Flow
  • depends-on: agentic-app-scaffold
  • sequence: 2 of 2

Problem

Once the scaffold ships, the agentic app is a shell with nothing to say. The first win the concept needs is the simplest true version of its promise: a signed-in user asks a question and watches a real answer stream back — proving the app, the shared session, the gateway wiring and the shared UI components work together end to end.

Proposed change

A conversation page in apps/agent built from the shared @sustentus/ui AI components (prompt input, streamed message rendering, thinking shimmer), talking to a streaming chat route in the same app. The route follows the house agent pattern — an agent defined in packages/services/src/ai/ with no tools in this stub, addressed through the Vercel AI Gateway — and requires a signed-in user. Responses render as streamed markdown (no raw HTML, so no new sanitisation surface). When the gateway declines, the user sees friendly retry copy, never a provider error. The conversation is ephemeral by design — a refresh starts fresh — and the route carries a simple per-user rate limit so a single user cannot run up unbounded spend.

Acceptance criteria (rough)

  • A signed-in user sends a message and the reply streams into the conversation using the shared AI components; a signed-out request to the chat route is rejected.
  • The model is reached through the AI Gateway using the house default model constants — no provider SDK, no hardcoded model string in the app.
  • A gateway decline (no credits / quota) shows friendly retry copy; no provider error or billing detail reaches the user.
  • One user hammering the route hits a rate limit rather than unbounded spend.
  • Stated and accepted in the PR: conversation state is ephemeral in this stub.

Out of scope (this feature)

  • Tools of any kind, tenant data access, personas/registers, the claim primitive.
  • Conversation persistence, history, and resumability.
  • Canned/replay mode for the demo tenant (worth wiring when the surface does real work).
  • Per-tenant cost metering — the gateway project budget is the only backstop for now.

Notes for Define

Live end-to-end testing depends on ai-platform-enablement/ai-gateway-billing-unlock (cross-batch — the gateway currently 403s on the free tier); the surface can build and review before it, but the DoD smoke needs funded credits, so check that stub's state at pickup. Follow the current code patterns, not the stale skill text: defineAgent in packages/services/src/ai/core/agent.ts (default model constants live there), createAgentUIStreamResponse route with maxDuration, and the packages/ui compound/ai primitives; the ai-feature skill predates several of these. Rate limiting per the platform docs is Vercel WAF / @vercel/firewall checkRateLimit keyed by the signed-in user — keep it to one rule. Open question for Define: whether the v0 agent gets a minimal Sustentus-aware system prompt (tone, refusal rules, prompt-injection defences mirroring the BRD prompt) or ships as a plain assistant — recommend the former, it is a prompt file, not scope. touches: apps/agent (chat page + route), packages/services/src/ai/ (new agent folder), turbo.json globalEnv (only if a new env var appears).