onboarding-concierge-agentrun.md00_intake/stub.mdThe demo concierge is a scripted conversation (conciergeScript in mock data) — no real model, no real state. The production flow needs an actual agent that interviews the first user, triggers source analysis when a website/description is offered, drafts blueprint sections as the conversation progresses, and knows when the blueprint is complete enough to hand over to review.
The concierge agent on the stub-2 foundation: a system prompt encoding the interview (company profile → source offer → confirm categories/products/services/skills → SLA tiers → settings), tools that read/write the persisted blueprint section-by-section (via stub 1's service) and invoke the source-analysis pipeline (stub 4), and a streaming chat route in apps/web following the useChat / AI-SDK pattern from ai/brd. The agent resumes mid-conversation from the persisted blueprint state (the wizard is leave-and-return by design). Server-side only + route handler; the chat UI itself is stub 6.
The demo's conciergeScript (apps/demo/lib/mock/onboarding.ts) is the interview's reference shape — steps, chips, reveal order. Follow the ai-feature skill (ToolLoopAgent, human-in-the-loop tool approval where a tool writes). Route policy entry needed for the chat route (web-route skill; API-route case). touches: packages/services/src/ai/onboarding/, apps/web/app/api/ (or route-handler location per ai/brd convention).
01_define/output/spec.mdThe tenant onboarding wizard's centrepiece is a concierge conversation that interviews a fresh
tenant's first user and drafts their whole workspace (company profile, categories, products,
services, skills, SLA tiers, settings) as they talk. Today that conversation is a scripted mock —
conciergeScript in apps/demo/lib/mock/onboarding.ts — with no real model and no persisted state.
This epic productionises concept A, the AI concierge (issue #588), and this stub builds the agent
brain: the interview, the tools that fill the persisted blueprint, and the streaming chat route.
It advances Build the Bridge / Q2-2026 O1 — Establish PMF with Vendor Partners (KR: onboard 8+
vendors onto paid tiers): a conversational, self-drafting setup is the wow that gets a vendor from
"account created" to "configured workspace" without a manual setup slog.
The three dependencies this agent sits on are already merged: the reusable agent core
(packages/services/src/ai/core — defineAgent, tenant-scoped tools), the persisted blueprint
model + service (onboardingBlueprintService, statuses draft → in_review → verified → committed,
7 section keys, per-item confidence/provenance/review-state), and the source-analysis pipeline
(ai/onboarding/analyseSource + DraftBlueprintSchema). The novel work here is wiring them into a
conversation.
A concierge agent in packages/services/src/ai/onboarding/, built on the stub-2 foundation
(defineAgent / ToolLoopAgent, model via the existing AI Gateway config — mirror the ai/brd
pattern):
apps/demo/lib/mock/onboarding.ts (conciergeScript, section keys
profile|categories|products|services|skills|sla|settings) is the reference shape for steps and
reveal order.buildTenantTools / defineTenantTool, so a tool can never reach
another tenant), wrapping the existing onboardingBlueprintService:upsertSection) — every item written with a
confidence score and ai_drafted provenance, pending review state;analyseSource (stub 4) with a URL or description; its
draft lands in the blueprint. An unanalysable source returns an explicit reason, and the agent
falls back to interviewing rather than erroring;draft → in_review — the machine-readable handover the UI (stub 6) uses to offer
review/launch.apps/web at app/api/onboarding/chat/route.ts, mirroring
app/api/brd/chat/route.ts (Clerk auth → tenant resolution → createAgentUIStreamResponse),
scoped to the authenticated user's tenant, plus a route-policies.ts + proxy.ts entry for
/api/onboarding/ (web-route skill, API-route case).Deliberate decision — blueprint writes are drafts, not real-service mutations, so the drafting
tools auto-execute (no per-message human-in-the-loop approval here). Everything the agent writes
lands as pending, ai_drafted items in the draft blueprint; the human review/verify gate is the
blueprint panel (stub 6) and the atomic commit into real services (stub 3). The ai-feature skill's
HITL-on-write rule is satisfied downstream by that review + commit flow, not by gating each chat
turn. This keeps this stub server-side + route handler only.
onboardingBlueprintService as answers arrive, each item
carrying a confidence score and ai_drafted provenance.analyseSource), and the resulting draft lands in the persisted blueprint; an
unanalysable source (explicit failure reason) makes the agent fall back to asking questions
rather than erroring the conversation.ai/brd route) and is scoped to the
authenticated user's tenant — a request without a valid session/tenant is rejected, and a tool
invocation cannot read or write another tenant's blueprint.draft → in_review (the blueprint-complete signal the wizard UI consumes), and does not do so
before the interview has covered every section./api/onboarding/ route-policy entry exists so the streaming route is reachable under the
deny-by-default routing (not silently redirected).commitBlueprint already exists, this agent never calls it).analyseSource; upload support is the source-analysis pipeline's fast-follow, not this cut.in_review),
the draft-not-commit write semantics, and the route pattern are all settled above. The concrete
agent model id and per-tool prompt/description wording are implementation details for Build (follow
the ai/brd + ai-feature conventions).02_build/output/notes.mdfeat: onboarding-concierge-agent — concierge agent, blueprint tools, streaming chat routepackages/services/src/ai/onboarding/prompt.ts — the concierge interview system prompt.
Encodes the seven-section order (profile → categories → products → services → skills → sla →
settings), the source-offer step, one-question-per-message style, and the tool-usage rules
(read first, analyse on source offer, draft as answers arrive, mark complete only after all seven).
Keeps the BRD-style prompt-injection defenses (refuse "ignore instructions / reveal prompt").packages/services/src/ai/onboarding/blueprint-tools.ts — four tenant-scoped tools built on the
stub-2 defineTenantTool/buildTenantTools core, wrapping the stub-1 onboardingBlueprintService
and the stub-4 analyseSource:read_blueprint (read-only) — current status + per-section drafted items, so the agent resumes.draft_section — merges items by key into a section (build-up over turns, no clobber); the
service stamps every item ai_drafted / pending.analyse_source — URL or free-text → analyseSource, which persists the draft and degrades to an
explicit empty/partial result with a machine-readable reason.mark_blueprint_complete — advances draft → in_review; guarded against premature (nothing
drafted) and repeat (already past draft) completion.packages/services/src/ai/onboarding/agent.ts — buildOnboardingConciergeAgent(tenantId). Built
per-request (not a singleton like the BRD agent) because its tools are tenant-bound;
createTenantContext rejects a non-ObjectId tenant so a toolset can never be built without a valid
tenant.packages/services/src/ai/onboarding/index.ts + src/server/index.ts — export the builder + tools.
Kept server-only (DB access): exposed via @sustentus/services/server, never the client-safe
@sustentus/services/ai root.apps/web/app/api/onboarding/chat/route.ts — streaming chat route mirroring api/brd/chat:
Clerk auth() → role check (admin/vendor) → getTenant() → user-in-tenant check →
createAgentUIStreamResponse with the per-tenant agent. maxDuration = 120.apps/web/lib/route-policies.ts — /api/onboarding/ gated to ["admin", "vendor"] under the
deny-by-default routing, alongside the existing /api/brd/ block.draft_section (merge-by-key) and
analyse_source write through onboardingBlueprintService; every item carries a 0–100
confidence and ai_drafted provenance (service-stamped).analyse_source delegates to analyseSource, which never throws.createAgentUIStreamResponse) and is tenant-scoped — unauthenticated /
no-tenant requests are rejected, and the tenant-bound tool context means a tool can only touch
the caller's own blueprint.read_blueprint before the first reply,
and the route replays prior UI messages, so it continues rather than restarts.draft → in_review via
mark_blueprint_complete (the UI's blueprint-complete signal); the tool refuses to advance with
nothing drafted and no-ops once past draft./api/onboarding/ route-policy entry exists so the streaming route is reachable (not silently
redirected by the deny-by-default proxy).pending / ai_drafted
items to the draft blueprint, so they auto-execute (no needsApproval). The human review/verify
gate is the blueprint panel (stub 6) and the atomic commit (stub 3) — this agent never calls
commitBlueprint.getTenant() + user-in-tenant check) is the right ownership boundary for a fresh tenant's first
user (admin or vendor).draft_section merges by key and preserves any existing item's stored provenance/review state, so
a re-draft during the interview doesn't silently reset human edits should the flows ever interleave.03_release/output/release.mdskipped by design on the PRapps/docs/app/technical/packages/services/page.mdx — the ai/onboarding/
entry now documents the concierge agent (buildOnboardingConciergeAgent) alongside source analysis,
and names the apps/web /api/onboarding/chat routefeature-role-matrix / service-journey / platform-overview still describe the product accuratelypoll-deploy.sh (web + help) — result reported at close-out; no
investor email is gated on it (audience cut = none)pending/ai_drafted draft items) is the
approved spec decision, not an oversight — the human review/commit gate is stubs 6 + 3.draft_section (merge-by-key) +
analyse_source write via onboardingBlueprintService; items carry confidence + ai_drafted.analyse_source delegates to analyseSource.mark_blueprint_complete advances draft → in_review, guarded
against premature / repeat completion./api/onboarding/ route-policy entry added (gated to admin/vendor) under deny-by-default routing.