# Agent Onboarding — Conversational Booking-Presence Setup

Stand up a performer's whole GigOrganizer presence *from the conversation* — no
settings pages. When someone says "set me up on GigOrganizer," "get me started,"
"build my booking page," or "import my team," this is the flow.

**The whole setup is FREE for any signed-in user.** Standing up your own presence
is acquisition, not live-gig management. Within this setup flow, Pro gates a handful
of specific pieces — the per-identity **money defaults** (default fee, default
team-member pay), the full **website-match lead-form styling** (branding/logo +
auto-response copy), the **enhanced/custom contract presets**, and
`team_invoicing_enabled` — plus the **live-gig actions** (send a contract for
signature, mark a payment, invite team to a booked gig, email a client).
Everything else in this skill works on a free account; where a Pro-only **field**
appears, the tools silently drop it for free users — note it and move on.
Public-profile **photos are free** (account setup) — include them for any user.

## The principle: gather once → produce many

To do any one of these well, you already gather the artist's context — act name,
brand (colors / fonts / logo / business name), instrument, typical gigs, fees,
regular bandmates. **That same gathered context feeds every other output.** Ask the
short series of questions once, then compose the setup tools below from one pool of
answers. Don't re-interview the user per surface.

A complete run produces, from one gathering pass:
- a **performer identity** (their act name + defaults),
- a **lead/contact form** that matches their website,
- a **free public booking page** at `/p/{slug}` with that form attached,
- sensible **contract defaults** (fee, ensemble size, legal posture, cancellation,
  deposit, typical event types),
- a **team roster** imported from their contacts, plus **team defaults** (default pay,
  arrival, notes),
- optionally their **regular venues**,
- and, on request, a **free prefilled contract-wizard link** to draft a contract.

## Tools this composes (all free-tier setup)

Every tool below is reachable for any authenticated agent (MCP). The setup **write**
tools pass `{ freeAllowed: true }` in `_pro-gate.ts`; `build_contract_prefill_link`
has no Pro gate at all (it's a pure link builder — no DB write). Exact request/response
shapes live in
[api-reference.md](api-reference.md); style-capture + form placement live in
[lead-form-appearance.md](lead-form-appearance.md). Don't duplicate those here —
read them when you need a body shape.

| Step | Tool | Sets up |
|------|------|---------|
| 1 | `manage_performer_name` | The act identity (name, is_default, musician count on create; `is_self` via a follow-up update) |
| 2 | `create_lead_form` | A website-matched contact/booking form |
| 3 | `manage_public_profile` | The public page `/p/{slug}` (bio, photos, publish) + attaches the form |
| 4 | `manage_contract_defaults` | Fee, size, legal posture, cancellation, deposit, event types |
| 5 | `manage_contacts` | Saved contacts / team roster (names, emails, roles, default team pay) |
| 6 | `manage_team_defaults` | Team-default cascade (default pay, arrival offset, notes template, headcount alerts, auto-send, team-portal visibility) |
| 7 | `manage_venues` | Regular venues (optional) |
| 8 | `build_contract_prefill_link` | A free prefilled contract-wizard link — the free "draft a contract" path |

## The flow

### Step 0 — Gather (one pass)

Ask a short, friendly series — don't make them open a settings page. Capture:

- **Act name** and whether it *is* them personally (a solo "Spanish Guitar" is the
  user; "Trio Paz" is a band they lead). Whether it's their default identity.
- **Brand**, if they have a site: colors, fonts, button style, logo URL, business
  name. (For style capture from a live site, follow
  [lead-form-appearance.md](lead-form-appearance.md) — the agent renders the page and
  reads computed styles; it's platform-agnostic, WordPress/Squarespace/Wix all work.)
- **Typical gig**: instrument/role, usual ensemble size, typical fee, event types
  they play (weddings, private parties, corporate…).
- **Regular bandmates** (names + emails) — these become the saved roster.
- **Logos/images come in by URL**, never file upload (agent paths are JSON; the
  server fetches the URL behind an SSRF guard).

Then produce the outputs below. **Confirm before each write** — never create or
publish without the user saying "yes / go ahead."

### Step 1 — Performer identity (`manage_performer_name`)

Create the act identity first; the form, public page, and contract defaults all
reference it. On `action=create`, set `name`, `is_default` (their primary act), and
`default_musician_count` (all free). The create response is
`route_response.performerName.id` — that UUID is the value you pass as
`performer_name_id` to the later steps.

**`is_self` is a two-call sequence — do NOT pass it on create.** `manage_performer_name`
rejects `is_self` on `action=create`; sending it fails the create, so you never get
the id. When the act is the user's personal/solo identity, create it first (without
`is_self`), then make a second `action=update` call passing that id as
`performer_name_id` plus `is_self: true`.

The money defaults `default_fee` and `default_team_member_pay_cents` are **Pro-only** —
for a free user they're silently dropped, so capture the number and tell them it'll
apply once they upgrade, rather than failing the call.

### Step 2 — Matching lead form (`create_lead_form`)

Create a contact/booking form, styled to their site if you gathered brand context.
Pass `performer_name_id` (from Step 1), `event_types`, and either `computed_styles` (a
`getComputedStyle` snapshot) or `branding`, plus `logo_url`. (These are the
`create_lead_form` MCP tool's snake_case arguments — `lead-form-appearance.md` shows
the same fields in the REST route's camelCase, e.g. `computedStyles`/`logoUrl`; use
the snake_case names here when calling the tool.) Full appearance schema, presets, and
the host **placement recipe** (WordPress + generic iframe) are in
[lead-form-appearance.md](lead-form-appearance.md) — that doc owns story A. Pro
styling is a field-strip: a free user still gets a working form, just without the
full website-match branding. The Pro-only, field-stripped pieces on `create_lead_form`
are `branding` / `computed_styles` / `logo_url` **and** the auto-response copy
(`auto_response_subject` / `auto_response_body`) — all silently dropped for free users.

**Free accounts get ONE active form** — `action=create` returns a **403** ("Free plan
allows 1 active form. Upgrade to Pro for unlimited forms.") once a free user already
has one. (The same cap fires from `manage_public_profile` if you attach a
`lead_form_id` that would activate a second form.) There is **no MCP tool that lists
forms**, so you can't always pre-check. Two cases:

- **New user, no form yet** → `action=create` with full styling. (Best case — the
  website-match applies to this fresh form.)
- **They may already have a form** → the only MCP way to find its id is
  `manage_public_profile` `action=get`. The attached form id comes back in the response
  as **`leadFormId`** (the `route_response.leadFormId` field — the DB column
  `public_profile_lead_form_id` surfaces under that camelCase key), and only *if* a form
  is attached to their public page. With that id, `action=update` can change
  non-appearance fields. Without it, just attempt `action=create`; on the **403**, tell
  the user they already have their one free form (manageable in the dashboard) rather
  than stalling — don't claim an update you can't target.

**Styling + logo are create-only** — `action=update` rejects `computed_styles` /
`branding` / `logo_url` and changes only non-appearance fields (name, copy,
`event_types`). So website-match styling applies to a *freshly created* form; you can't
restyle an existing one via update. (Unlimited forms — and re-creating to restyle — are
effectively Pro, since a free user is capped at the one.)

### Step 3 — Public booking page (`manage_public_profile`)

Stand up the free `/p/{slug}` page from the same brand assets: `slug`, `bio`, and
`profile_public: true` — all free. **Attach the Step-2 form** so the page captures
bookings: set `lead_form_id` on `manage_public_profile` (the route stores it as
`public_profile_lead_form_id`) — see
[lead-form-appearance.md](lead-form-appearance.md) → "Bundling a free GigOrganizer
public page"). Publishing the page is free.

**Photos are free** — include them (by https URL, up to 3) for any user. There is
no Pro-gated field on the public page: bio, slug, photos, video links, and
publishing are all free account setup.

The honest pitch for why an artist wants one (lead with discoverability + free, not
salesy): it's a zero-maintenance booking page that auto-updates from their
GigOrganizer data, built around lead capture and reviews, on a domain that ranks for
booking-intent searches a lone artist site rarely reaches.

### Step 4 — Contract defaults (`manage_contract_defaults`)

Seed their cascade so future contracts come pre-filled: fee, ensemble size, **legal
posture/tier**, cancellation preset, deposit habits, and typical event types. The
**standard preset is free**; the **enhanced/custom legal presets are Pro** and are
gated at the route — a free user gets standard, which is the right default. Scope a
global layer first; per-event-type / per-performer overrides are optional.

### Step 5 — Team from contacts (`manage_contacts`)

Import their regular bandmates into the saved address book with `manage_contacts`:
`name`, `email`, the **`roles` array** (e.g. `roles: ["team_member"]`), and optional
`default_pay_cents`. Use `roles` (array) on create — the singular `role` input is only
a list *filter* and is silently dropped from the create body, which would leave the
bandmate out of the team-member roster. Building saved contacts is free account setup;
names + emails are enough.

Note the boundary: `manage_contacts` is the **setup** surface (free). Adding a person
to a **specific booked gig's** roster later uses `manage_team_member`, which is
**Pro** and per-gig live-gig management — not part of free onboarding. Don't reach for
it here; the onboarding job is to populate the reusable contact list.

### Step 6 — Team defaults (`manage_team_defaults`)

Separate from the saved contacts (Step 5), `manage_team_defaults` configures the
**team-default cascade** — default team-member pay, arrival offset, notes template,
headcount alerts, auto-send, team-portal visibility — so future gigs inherit sensible
team settings. Configuring team defaults is free account setup. It uses the same
`scope` / `scope_key` / `settings` args as `manage_contract_defaults` (scope a global
layer first), but its **write action is `action=set`** (full-replace a layer), with
`action=clear` to drop keys — **not** `action=update` as in `manage_contract_defaults`.
One field is Pro: `team_invoicing_enabled` returns a tier error for non-Pro — leave it
off for a free user.

### Step 7 — Venues (`manage_venues`, optional)

If they named regular venues, save them so future gigs autofill the address.

### Step 8 — Draft a contract, free (`build_contract_prefill_link`)

The capstone, optional: hand the user a **free** prefilled contract-wizard link
(`https://gigorganizer.com/create/<type>?prefill=…`) built from the logistics you
already gathered. Pass `performer_type` and the `fields` you have (the encoder keeps
only the allow-listed structured keys). The user opens the link, reviews/edits, and
downloads a free PDF or copies the text — **no credit, no saved record**. This is the
FREE draft path. Saving a real draft to the gig inbox, sending it for e-signature, or
collecting payment are the **Pro** paths (the live-gig moments) — don't attempt them
from the agent for a free user; hand off the link instead.

## Tax during onboarding — stage only, never call

W-9 collection is part of team setup but **W-9 sending calls the TaxBandits API,
which is in-app-only**. An agent may **stage**: read team data, flag which teammates
still need a W-9, and prompt the user — but the user clicks **send in-app**. Never
call `/api/tax/*` W-9, filing, or payor routes from the agent. 1099 filing has
nothing to do with onboarding; don't raise it. (See the off-limits rule in the main
[SKILL.md](SKILL.md).)

## What stays Pro (hand back, don't force)

Setup is free; the outbound, live-gig moments are Pro and run from the website:

- Sending a contract for e-signature, marking/managing payments, inviting team to a
  **booked** gig, emailing a client.

And these per-step Pro **fields** within setup (all described in their steps above):

- Per-identity **money defaults** — default fee, default team-member pay (Step 1).
- Full **website-match lead-form styling** — `branding` / `computed_styles` / `logo_url`
  + auto-response copy (Step 2); a free form is functional but not fully brand-matched.
- Enhanced/custom contract **legal presets** — standard is free (Step 4).
- **`team_invoicing_enabled`** on team defaults (Step 6).

When a free user hits one of these, don't error out the whole flow — finish the free
setup, capture the values, and tell them which step finishes after they upgrade (or
point them to the dashboard). The website path always works. (Photos are the exception:
don't send them for a free user at all — they 403 rather than silently dropping.)

## Ordering & rules

- **Identity first.** Step 1's create returns `route_response.performerName.id`; that id
  is the `performer_name_id` Steps 2–4 reference.
- **Confirm before every write/publish.** Same rule as the main skill — never
  create, publish, or attach without an explicit "yes."
- **JSON only, logos by URL.** Agent transport is JSON; images come by URL, never
  multipart upload.
- **One gather, many writes.** Reuse the Step-0 answers across all steps; don't
  re-interview per surface.

## Reference files

- **[lead-form-appearance.md](lead-form-appearance.md)** — style capture from a live
  site, appearance schema/presets, the embed **placement recipe** (WordPress +
  generic), and public-page bundling (stories A/B/C).
- **[api-reference.md](api-reference.md)** — exact request/response shapes for every
  route the tools above wrap.
- **[SKILL.md](SKILL.md)** — the main skill:
  reading data, live-gig actions, the off-limits (dashboard-only) tax rule.
- Product rationale (internal): `docs/plans/agent-booking-presence-setup.md`.
