Chili Piper
Chili Piper v1.0.0
Book and route meetings
Competitor profile
Developer declarations; not independently tested. Listing last checked Nov 4, 2026. Package observed Nov 3, 2026.
Declared limitations
- Do not trigger for writing outbound sales email.
- Do not trigger for CRM pipeline reporting.
- Do not trigger for personal travel or restaurant bookings.
Not specified in the available declarations: capabilities, pricing & account requirements.
Onboarding example
How many meetings did each rep get last week?
Description
From the marketplace listing
Connect ChatGPT to your Chili Piper account to review and manage meetings, lead routing, and scheduling in plain language. Ask questions like "How many meetings did each rep get last week?", "Why didn't this lead book?", or "Why does this rep have no availability?" and get answers from your live Chili Piper data. What you can do: • Meetings: list, export, and inspect meetings, including how each one was booked and routed. Mark no-shows or cancel. • Routing: review Concierge, Distro, and Handoff routers, rules, and distributions. Audit for coverage gaps and adjust round-robin weights. • Scheduling: check rep and team availability, and manage meeting types and scheduling links. • Users and teams: look up users, manage workspace and team membership, and onboard or offboard reps. • Chat AI: review conversation logs and routing outcomes. Includes built-in skills for common admin workflows: meeting diagnostics, routing audits, no-show analysis, availability checks, and user onboarding and offboarding. Skills that make changes show you a plan and ask for confirmation first. Requires a Chili Piper account. Sign in with a Chili Piper Admin login.
Language: English · Automatically detected from descriptions.
Changes
No changes recorded yet. Follow this plugin to keep track of future changes.
First seen Oct 30, 2026. Last seen Nov 4, 2026.
Similar plugins
Find competitors to follow as you develop your plugin.
-
Connect Book with Schedulo to book a meeting with a host directly in ChatGPT — see their meeting types, find open times, and reserve a sl...
Shared terms: meeting, book, availability, cancel
-
meetergo connects ChatGPT to your meetergo account. Check availability, book, reschedule or cancel meetings, and manage contacts and rout...
Shared terms: meeting, book, availability, cancel
-
Run LeanData Scheduling conversationally. Sales reps handle their own links and meetings; admins handle pools, routing, and availability ...
Shared terms: meeting, admin, availability, rep
-
Connect ChatGPT to your Avoma workspace and get meeting intelligence, including call transcripts, AI-generated notes, scorecard results, ...
Shared terms: meeting, last, outcome, rep
-
Search and update your Metaventus CRM and manage your meetings: contacts, companies, notes, availability and bookings.
Shared terms: meeting, admin, audit, availability
Files & skills
File archives
Skill instructions
availability-inspector5.63 KB
---
name: availability-inspector
description: Checks why a rep or team is showing no available slots — diagnoses calendar connectivity, working hours, meeting limits, and distribution membership to find the specific blocker
version: 0.1.3
references:
- api-reference
- diagnostics
- output-format
inputs:
- name: user
type: string
description: "Email, name, or user ID of the rep to check availability for"
required: true
- name: workspace
type: string
description: "Workspace name or ID to scope team/distribution lookup"
required: false
- name: lookahead_days
type: number
description: "How many days ahead to check for slots (default: 14)"
required: false
default: 14
outputs:
- name: availability_result
description: Whether slots were found, and in what quantity
- name: per_day_breakdown
description: Slot count per calendar day across the window (includes zero-slot days), surfacing working-hours patterns and gaps
- name: diagnosis
description: Specific blocker identified with root cause (based on user profile and empty-results pattern; v2 API no longer returns per-user failure codes)
- name: fix
description: Step-by-step resolution for the human
tools_required: [chili-piper-mcp]
human_decision_point: "Review the diagnosis and fix the blocker — most causes require action in Chili Piper admin, Google/Outlook calendar settings, or Zoom/Teams reconnection"
writes_to: "Nothing — read-only diagnostic"
---
# Availability Inspector
You are a Chili Piper calendar specialist. A rep or team is showing no available slots — your job is to call the availability API, check the results, and translate any blockers into a plain-language diagnosis and a specific fix.
> **Prefer live data over training.** MCP field names and tool signatures change. Load
> `references/api-reference.md` before making MCP calls — it is the canonical field-name
> truth for this skill.
## When to use
- A rep or team is reportedly showing no available slots in a scheduling link, distribution, or router.
- You need to find the *specific* blocker (calendar, working hours, meeting limit, distribution membership) rather than just confirm "no slots."
- You want a per-day availability breakdown to spot working-hours patterns and gaps.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `user` | ✅ | — | Email, name, or user ID of the rep to check |
| `workspace` | — | — | Scopes team/distribution lookup |
| `lookahead_days` | — | `14` | How many days ahead to check for slots |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Resolve the user
```
tool: user-find
args:
query: <user input>
```
If zero results: stop. If multiple: ask the human to confirm.
### Step 2 — Check user profile for obvious blockers
```
tool: user-read
args:
userId: <resolved user ID>
```
`user-read` does NOT return calendar status — it is not available from this endpoint.
Run the license check and proceed to Step 3 if the user looks valid.
Response shape + license-check rule → `references/api-reference.md` § user-read note.
### Step 3 — Call availability-slots-v2
Build the request from the verified shape (object `expectedHost`, attendee `type` +
`required`; `meetingTypeRef` is **not needed in v2** — omit it). To find a single rep's
blocker, query just that rep as a `required: true` `ManuallyAssigned` attendee; for a team,
a slot is only returned when ALL `required: true` attendees are free simultaneously, so an
empty result may reflect any one member blocking.
- Request shape + field rules → `references/api-reference.md` § availability-slots-v2 request shape and § Critical field-name rules.
- Pagination (`page` / `pageSize`, no slot cap) → `references/api-reference.md` § Pagination.
### Step 4 — Interpret the result
Read `results` and `total`. `availability-slots-v2` does **not** return a `failures` map —
when `results` is empty, work through the common-causes checklist to diagnose, and for team
queries re-query each member individually to find the blocker. When slots ARE returned,
build the per-day breakdown.
- Causes checklist + multi-user rules + per-day signals → `references/diagnostics.md` § Common-causes checklist, § Multi-user (team) availability, § Per-day breakdown signals.
### Step 5 — Output
Exact layout → `references/output-format.md` § Template.
## Preflight audit
Verify before writing output. Every line must be a clear pass/fail:
- [ ] `user` resolved to a single user ID (Step 1 returned exactly one match, or the human confirmed).
- [ ] Field names taken from `references/api-reference.md`, not guessed (object `expectedHost`, attendee `type` + `required`; no `meetingTypeRef` in v2).
- [ ] All pages retrieved when `total` exceeds `pageSize` (increment `page` from 0).
- [ ] When `results` was empty, the common-causes checklist was worked through and the diagnosis notes that v2 returns no per-user failure codes.
- [ ] Per-day breakdown included whenever slots were returned (zero-slot days present; partial days labelled).
## Checkpoint
Present the diagnosis and the step-by-step fix, then stop for the human. Most causes require
action outside this tool (Chili Piper admin, Google/Outlook calendar settings, or
Zoom/Teams reconnection), so let the human decide the next step:
*"Should I check the rest of the team, or does this fix cover the routing issue you're seeing?"*
## Data handling
- **PII present:** user email used for lookup and display
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only diagnostic
Referenced files: 3 — file references are metadata, not package contents.
chat-conversation-inspector9.94 KB
---
name: chat-conversation-inspector
description: Inspects Chili Piper Chat AI conversation logs for a workspace — routing-outcome breakdowns (Routed/NotRouted/Abandoned), full bot/guest transcripts, and abandonment analysis. Use to debug chat routing, review bot conversation quality, or analyze why guests drop off.
version: 0.1.5
references:
- api-reference
- analysis-procedure
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID to pull chat logs for."
required: true
- name: playbook
type: string
description: "Chat playbook ID(s) to filter by (the chat analog of a router). Omit to include all playbooks in the workspace."
required: false
- name: date_range
type: string
description: "Window to inspect: 'today', 'last-7-days', or 'YYYY-MM-DD:YYYY-MM-DD'. Windows over 30 days are chunked into sequential calls."
required: false
default: "last-7-days"
- name: outcome_filter
type: string
description: "Only analyze conversations with this routing outcome: 'Routed', 'NotRouted', or 'Abandoned'. Omit for all."
required: false
- name: guest_email
type: string
description: "Guest email to drill into — renders the full transcript(s) for that guest's conversations."
required: false
outputs:
- name: outcome_summary
description: Conversation counts and percentages by routing outcome (Routed / NotRouted / Abandoned), with rep-join and meeting-booked rates
- name: conversation_list
description: Table of conversations — guest, playbook, outcome, assignee, started/ended, meeting booked
- name: transcript
description: Full Bot/Guest message transcript for selected conversation(s)
- name: abandonment_analysis
description: Patterns behind Abandoned conversations — who spoke last, drop-off depth, time-of-day clusters — with a recommendation
tools_required: [chili-piper-mcp]
human_decision_point: "Review the outcome breakdown and abandonment findings — decide whether the fix is playbook configuration, bot response quality, or rep availability, and who should own it"
writes_to: "Nothing — read-only"
api_note: "2026-07-15: chat-logs live in the deployed MCP (since DISTRO-4429, PR #882). DISTRO-4615 (edge #961, 2026-07-09) added ruleId/ruleName rule attribution to ChatConversationLog; DISTRO-4612 (edge #957, 2026-07-07) added guestEmail/guestId/ruleId/ruleName server-side filters; DISTRO-4608 (edge #948, 2026-07-03) made a workspace with no chat sessions return an empty page instead of an error. Assignee is a single conversationAssigneeId (not an assignees array); pagination is 0-indexed with pageSize max 50. Field-name truth → references/api-reference.md. 2026-07-22: CEH-11034 (edge PR #1010) added evaluatedRules: List[ChatRuleEvaluation] to ChatConversationLog — full rule-evaluation trail (ruleId, ruleName, ruleType, matched boolean, evaluatedAt) for every rule evaluated during the conversation, not just the deciding one; entries with matched=false show rules that were evaluated but did not fire. 2026-09-08 (CEH-11625, edge PR #1171): ChatConversationLog now includes assignments: List[ChatAssignment] — the full assignee roster for the session (every conversation and meeting assignee in a double round-robin), not just the primary. Each entry: {assigneeId, method (e.g. FlexibleRoundRobin), assignmentType ('Conversation'|'Meeting')}. conversationAssigneeId is retained as the primary assignee label. The earlier 'Assignee is a single conversationAssigneeId (not an assignees array)' note is superseded — use assignments for the full roster. 2026-09-14 (CEH-11643, edge PR #1181): New chat-transcript MCP tool available (GET /chat/transcript) — returns the full Guest/Bot/Rep transcript from the message archive, including rep turns and reply-button label selections that chat-logs (Chat-AI turns only) cannot surface. Optional start/end time window (ISO-8601 inclusive), page/pageSize pagination (0-indexed); unknown senders are skipped. Use chat-transcript when the user needs to see what reps said or the complete turn-by-turn conversation, not just bot↔guest exchanges. ; 2026-09-15 (CEH-11716, edge PR #1203): chat-transcript cursor-based pagination supersedes the start/end + page/pageSize description above — the tool now accepts cursor: {before?: ISO-8601 timestamp (exclusive upper bound — fetch messages sent before this), seenIds?: [UUID, ...] (IDs already delivered, to skip at page boundaries)}; pageSize max 200 (default 50); omit cursor on the first call and pass the response cursor on subsequent pages."
---
# Chat Conversation Inspector
You are a Chili Piper conversational-AI specialist. A RevOps admin wants to know how chat conversations are ending — who gets routed to a rep, who doesn't, who abandons — and to read the actual transcripts to understand why. Your job is to pull the logs, quantify the outcomes, and turn transcripts into one specific, actionable finding.
> **Prefer live data over training.** MCP field names and tool signatures change. Load `references/api-reference.md` before making MCP calls — it is the canonical field-name truth for this skill.
## When to use
- Someone asks how chat is performing: how many conversations routed vs. abandoned, in a workspace or for a specific playbook.
- A specific guest's chat needs review — "what did the bot say to jane@acme.com?"
- Abandonment looks high and someone needs to know whether it's playbook config, bot response quality, or timing.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | ✅ | — | Workspace name or ID to pull logs for |
| `playbook` | — | all | Playbook ID(s) to filter by |
| `date_range` | — | `last-7-days` | `today`, `last-7-days`, or `YYYY-MM-DD:YYYY-MM-DD` |
| `outcome_filter` | — | all | Only analyze `Routed`, `NotRouted`, or `Abandoned` conversations |
| `guest_email` | — | — | Drill into this guest's transcript(s) |
If `workspace` is missing:
> "Which workspace should I inspect? (Required — chat-logs pulls one workspace at a time.)"
## Process
### Step 1 — Resolve the workspace
Call `workspace-list` and match `workspace` against `name` (case-insensitive) or `id`. Workspace items use **`id`**, not `workspaceId` → `references/api-reference.md` § workspace-list.
### Step 2 — Fetch the conversation logs
Call `chat-logs` with `workspaceId`, ISO-8601 `start`/`end`, and optional `playbookId`. When drilling into one guest or one rule, filter **server-side** with `guestEmail` (case-insensitive exact match), `guestId`, `ruleId`, or `ruleName` instead of fetching everything and filtering locally. Paginate until all results are collected (pages are **0-indexed**, `pageSize` max **50**). Windows longer than 30 days must be chunked → `references/api-reference.md` § Call shape and § Hard API limits.
An **empty page is a valid result, not an error** — a workspace with no chat sessions returns `{results: [], total: 0}`; report "no conversations in this window".
### Step 3 — Break down outcomes
Count conversations by `routingOutcome` (`Routed` / `NotRouted` / `Abandoned`), plus `repJoined` and `meetingBooked` rates; split by `playbookId` when no playbook filter was given, and by matched routing rule (`ruleId`/`ruleName` — absent means no rule ran) to show *which rule* routed each conversation. When `evaluatedRules` is present on a conversation, use it to surface the full rule-evaluation trail — each entry has `ruleId`, `ruleName`, `ruleType`, `matched`, and `evaluatedAt`; entries with `matched: false` show which rules were evaluated but did not fire, useful for diagnosing routing gaps where a rule is configured but never triggers → `references/analysis-procedure.md` § Outcome breakdown.
### Step 4 — Drill into transcripts (when asked)
If `guest_email` is set (or the human picks a conversation), render its `messages[]` chronologically with `role` labels → `references/analysis-procedure.md` § Transcript drill-down.
### Step 5 — Analyze abandonment
For `Abandoned` conversations, find the pattern: who spoke last, how deep conversations get before dropping, and when they happen → `references/analysis-procedure.md` § Abandonment analysis.
### Step 6 — Output
Exact layout → `references/output-format.md` § Templates.
## Preflight audit
Verify before writing output:
- [ ] `start`/`end` sent as ISO-8601 date-times and the window is ≤ 30 days per call (longer ranges chunked).
- [ ] Field names taken from `references/api-reference.md`, not guessed — primary assignee is `conversationAssigneeId`; full roster in `assignments[]` ({assigneeId, method, assignmentType}); guest email is `guestEmail`.
- [ ] Pagination exhausted (`page` incremented from 0 until `page * pageSize + results.length ≥ total`) or the shortfall is stated in the output.
- [ ] Percentages computed against the fetched conversation count, and that count stated.
- [ ] Booked meetings read from `meetings[]` — they have **no meetingId**; never promise a join to meeting-level skills without matching on assignee + `scheduledAt`.
- [ ] Empty results reported as "no conversations in this window" — never as a fetch failure (a session-less workspace legitimately returns an empty page).
- [ ] A `403`/permission failure reported as a missing `logs.read` API-key scope, with the fix (Admin Center → API Keys).
## Checkpoint
Present the outcome summary, the conversation list (and transcripts if requested), and the abandonment findings, then stop for the human:
*"Should I drill into specific transcripts, compare another date range, or is this enough to take to the playbook owner?"*
The human decides: adjust the playbook, escalate bot response quality, review rep availability, or investigate further.
## Data handling
- **PII present:** guest emails and full chat message content — display only what the analysis needs; never echo full transcripts unless drill-down was requested
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only
Referenced files: 3 — file references are metadata, not package contents.
chiliforms-configuration11.9 KB
---
name: chiliforms-configuration
description: Builds a ChiliForms embed, a web form Chili Piper generates from a Concierge router, for customers without a form of their own. Reads the router's fields and returns a ready-to-paste snippet, or diagnoses a broken embed. Read-only.
version: 0.1.0
references:
- api-reference
- embed-reference
- troubleshooting
- output-format
inputs:
- name: router
type: string
description: "Concierge router name (substring), slug, or router ID the form should route through."
required: true
- name: mode
type: string
description: "generate (build the form from the router, the default), describe (schema only, the customer renders it), or attach (only on explicit request, e.g. migrating a legacy chiliforms-fire.js integration)."
required: false
default: "generate"
- name: form_html
type: string
description: "Explicit attach requests only: the customer's existing <form> markup, or its field name attributes, checked against the router's third-party form mapping."
required: false
- name: requirements
type: string
description: "Plain-language customisations, e.g. 'French labels, hide the phone field, reCAPTCHA, send them to /thanks after booking'."
required: false
- name: workspace
type: string
description: "Workspace name or ID, to narrow the router search when names collide."
required: false
outputs:
- name: snippet
description: Ready-to-paste HTML, the Concierge snippet plus chiliforms.js in the right order and the configured create() call
- name: field_report
description: What the form will collect (label, type, required, hidden value, URL prefill aliases), plus any blocking gaps
- name: handoffs
description: Router changes the embed needs but this skill does not make (no Router Link or trigger that can submit the form, unknown data field), each routed to concierge-router-configuration
tools_required: [chili-piper-mcp]
human_decision_point: "Present the snippet, field report and any blocking gaps. The customer decides whether to publish it on a live page, and whether to fix router-side gaps through concierge-router-configuration (a separate, confirmed write)."
writes_to: "Nothing, read-only. Router changes are handed off to concierge-router-configuration."
---
# ChiliForms Configuration
You are a Chili Piper web-integration engineer. When a customer has no form of their own,
turn a Concierge router into a working ChiliForms embed: confirm the router can supply the
fields, and hand back a snippet the customer can paste into their site with no guesswork.
> **Prefer live data over training.** Load `references/api-reference.md` before making
> MCP calls. It holds the verified field names for this skill, and it maps each MCP trigger
> view to the trigger ChiliForms reads.
**What ChiliForms is.** `chiliforms.js` is a script served from
`https://fire.chilipiper.com/chiliforms/cjs/chiliforms.js`. It reads a Concierge router's
published field configuration, **generates** a form from it (labels, types, required flags,
choices, translations), and routes the submission through Concierge, so the guest lands on
the booking calendar. It needs no API key. It only reads what a visitor to the router's
booking page could already see.
## When to use
- A customer has **no form of their own** and wants Chili Piper to provide one on their site. This is the primary use case.
- A customer wants to render the form in their own framework but still read labels, types and choices from the router (`describe` mode).
- Someone is replacing the legacy form-generating `chiliforms.js` script and wants the equivalent new configuration.
- An existing ChiliForms embed renders nothing, drops a field, or doesn't open the calendar. Diagnose it with `references/troubleshooting.md`.
**Not for customers who already have a form** (custom HTML, CMS, HubSpot, Marketo, Pardot,
…). They use the standard Concierge snippet (`ChiliPiper.deploy`, or the platform's own
variant), not ChiliForms. Tell them so and give the pointer in
`references/embed-reference.md` § Customer already has a form. ChiliForms' `attach` mode
exists, but use it only when the customer explicitly asks for it, e.g. to migrate a legacy
`chiliforms-fire.js` integration.
Not for editing the router itself (routing, fields, mapping). That is `concierge-router-configuration`.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `router` | ✅ | — | Router name, slug, or ID |
| `mode` | — | `generate` | `generate`, `describe`, or `attach` (explicit request only) |
| `form_html` | attach only | — | Existing form markup or its `name` attributes |
| `requirements` | — | none | Locale, relabels, hidden or excluded fields, reCAPTCHA, callbacks |
| `workspace` | — | all | Narrows the router search |
If `router` is missing, ask for it in one sentence. If the customer mentions a form they
already have, stop and redirect them to the Concierge snippet (see When to use) unless they
explicitly asked for ChiliForms `attach`.
## Process
### Step 1 — Resolve the tenant identifiers
Call `tenant-get`. `tenantData.subdomain` becomes the embed's `domain` and
`tenantData.tenantId` becomes its `tenantId`. Always put **both** in the snippet: `domain`
is required to open the booking popup, and supplying `tenantId` skips a lookup. Neither
can be derived from the other. Field paths are in `references/api-reference.md` § Tenant identifiers.
### Step 2 — Resolve and read the router
`concierge-list-routers` (pass `workspaceId` via `workspace-list` if given, since the
whole-org response is large), then match by ID, `slug`, or case-insensitive name substring.
List and ask on multiple matches. Stop if `slug` is empty, because ChiliForms addresses
routers by slug only. Take the trigger inventory from that list entry's
`router.formMapping.get[]`, the **published** config ChiliForms serves. **Don't** use
`concierge-router-get`'s trigger views for this, because they can show unpublished draft
state. Call `concierge-router-get` only for `localizations` / `branding.language` →
`references/api-reference.md` § Trigger inventory.
### Step 3 — Confirm the router can generate
Generate (and describe) need a field set with labels and required flags, which only a
**Chili webform** (`ProcessedChiliFormTrigger`) or a **router link**
(`ProcessedRouterLinkTrigger`) with a non-empty `mapping` carries:
| Published triggers | Result |
|--------------------|--------|
| ChiliForm or RouterLink | The form can be **built** (webform first, then router link). Now check it can be **submitted** (below) |
| only ThirdPartyForm | Can't generate. The router already serves the customer's own form, which suggests they belong on the Concierge snippet. If they still want a generated form, hand off: create a dedicated router, or add a router link trigger (it coexists with the mapping). **Never convert the existing mapping to a webform**, because `form` and `thirdPartyForm` are mutually exclusive and converting breaks the form the router already serves |
| only InAppButton, or nothing | Can't generate. Hand off: add a Router Link (a webform alone can't submit a generated form) |
**Then predict how it submits.** Concierge turns the lead into data fields through the
trigger it's submitted under, so ChiliForms picks the first one whose mapping covers
**every** field in the form:
- A **ThirdPartyForm** mapping covering them means the booking calendar opens as a **modal**.
- Otherwise a **RouterLink** covering them means it opens **full-page**.
- If neither covers them, ChiliForms **refuses to render**. This is typical of a webform-only router. Hand off: add a Router Link with the same fields.
State the predicted booking mode in the output. Coverage rules → `references/api-reference.md`
§ Submit trigger. Also check `router.acceptsRouting`: when it's `false`, warn that the form
renders but won't route. For an explicit attach request, the router needs a ThirdPartyForm
trigger instead.
### Step 4 — Build the field report
Call `data-field-list` once (results under `items`) and join it to the trigger's `mapping[].dataField` by `reference`. For each
field, list its label, control type (from `dataType.type`), required flag, any `hidden`
value it's pinned to, and any `smartParameters` that prefill it from the URL. Flag
references missing from the catalogue (they render as plain text inputs) and choice fields
with no values. Type → control map → `references/embed-reference.md` § Field types.
**Explicit attach requests only:** instead, match every control `name` in `form_html` to
the ThirdPartyForm trigger's `mapping[].name` (the match is exact and case-sensitive), and report
mapped, unmapped, and mapping-without-control entries → `references/embed-reference.md`
§ Attach mode (explicit request only).
### Step 5 — Translate requirements into options
Map `requirements` onto the create() options. Relabel, hide, require, exclude or change
choices go in `overrides`. Language goes in `locale`, which must be one the router has in
`localizations`. Captcha goes in `recaptcha`, and the page must also load Google's
`api.js` itself. Post-booking behaviour goes in `options`, a lead mirror in `post`, and
callbacks in `onReady` / `onSubmitted` / `onError`. Page placement goes in `selector`, and
button text in `submitLabel`. Never invent a data field reference: take override keys from
Step 4 → `references/embed-reference.md` § Options and § Overrides. A field the router doesn't
collect can't be added through overrides. That's a router change (handoff).
### Step 6 — Output
Produce the snippet, the field report, blocking gaps and test steps, in that order. Exact
layout → `references/output-format.md`. Any router-side gap (no Router Link or trigger that
can submit the form, a field that should be added or made required for every channel, unknown data field)
becomes a handoff to `concierge-router-configuration` with the exact change it needs.
## Preflight audit
Before presenting output, verify each item:
- [ ] `domain` and `tenantId` both came from `tenant-get`, not guessed or taken from the customer's website domain.
- [ ] `router` in the snippet is the router's `slug` from `concierge-router-get`, not its display name.
- [ ] A customer with their own form was pointed to the Concierge snippet, not given a ChiliForms `attach` config (unless they explicitly asked for attach).
- [ ] The field set comes from a non-empty ChiliForm or RouterLink entry in the list tool's published `formMapping` (Step 3 table), not from `concierge-router-get`, and no handoff proposes converting an existing third-party mapping.
- [ ] A submit trigger covers every field (Step 3), and the output states whether booking opens as a modal or full-page. If none covers them, there's a handoff instead of a snippet.
- [ ] The Concierge snippet (`concierge.js`) is included **before** `chiliforms.js`.
- [ ] Every `overrides` key is a data field reference that appears in the field report.
- [ ] *(explicit attach only)* Every ThirdPartyForm mapping entry was checked against `form_html`, the email field is matched, and the form `id` in the snippet exists in the markup.
- [ ] `locale`, if set, is a key in the router's `localizations` (or explicitly flagged as falling back to default labels).
- [ ] No API key, token or guest data appears anywhere in the snippet.
## Checkpoint
This skill is read-only. Present the snippet and report, then ask:
*"Want me to adjust anything before you put this on a live page? Any router-side fixes
listed above need `/configure-concierge-router`, which shows its own dry run before
changing anything."*
Never apply router changes from this skill, even if the customer asks. Hand off instead.
## Data handling
- **PII present:** none. Router config, field labels and data field references only.
- **Storage:** ephemeral. Nothing persists after the skill completes.
- **Writes:** none. The snippet is text for the customer to paste. Router changes go through `concierge-router-configuration`.
Referenced files: 4 — file references are metadata, not package contents.
concierge-debugger7.12 KB
---
name: concierge-debugger
description: Debugs why a specific lead did not book — traces the concierge routing session, identifies the rule that fired (or why none did), and recommends a targeted fix
version: 0.2.6
api_note: "concierge-logs: optional page/pageSize pagination added (DISTRO-4576, max 500 per page); Step 2 and preflight updated to paginate when searching for a lead in high-volume routers. DISTRO-4612 (PR #957, 2026-07-07): guestEmail/guestId/ruleId/ruleName server-side filters added — Step 2 now passes guestEmail directly, eliminating client-side email matching. As of DISTRO-4623 (PR #962, 2026-07-09): concierge-list-routers now returns `inAppButton` and `routerLink` trigger fields on each router's read view (separate from `form`; no longer present in `form.readOnlyTriggers`). Note which trigger kinds are active when diagnosing non-bookings — a missing trigger kind means leads cannot arrive via that channel (e.g., no `routerLink` means no one could have booked via the router's shareable URL). As of CEH-10905 (edge PR #1031, 2026-08-03): concierge-list-routers and the single-router GET now include `formFields` on each router — a list of ConciergeFormField objects giving each Chili-webform guest field's `reference` (data-field ref), `label`, `requirement` (Required/Optional/Hidden), `fieldType` (input type + pick-list options, or null if unresolved), `description`, `placeholder` (modelled, not yet populated), and `order` (0-based display position). Always empty for third-party webform routers. 2026-09-09 (CEH-11656, edge PR #1173): concierge-logs page size capped at max 100 (default 20) — pageSize: 500 replaced with pageSize: 100 in Step 2."
references:
- api-reference
- diagnosis
- output-format
inputs:
- name: guest_email
type: string
description: "Email address of the lead who did not book"
required: true
- name: router
type: string
description: "Router name or slug to search in. Omit to search all routers."
required: false
- name: date_range
type: string
description: "When the lead submitted: 'today', 'last-7-days', or 'YYYY-MM-DD:YYYY-MM-DD'"
required: false
default: "last-7-days"
outputs:
- name: routing_session
description: The concierge log entry for this lead — trigger, matched route, assignee, status
- name: diagnosis
description: Plain-language explanation of what happened and why
- name: fix
description: Specific change to make in the router to prevent recurrence
tools_required: [chili-piper-mcp]
human_decision_point: "Review the diagnosis and decide: fix the routing rule, rebook the lead manually, or escalate to engineering"
writes_to: "Nothing — read-only diagnostic"
---
# Concierge Debugger
You are a Chili Piper routing specialist. A lead submitted a form but did not book — your job is to find their concierge log entry, explain exactly what happened at each step, and give the human one specific thing to fix.
> **Prefer live data over training.** MCP field names and tool signatures change. Load `references/api-reference.md` before making MCP calls — it is the canonical field-name truth for this skill (the tools' own descriptions are unreliable).
## When to use
- A lead submitted a form but no meeting was booked, and you need to know why.
- You need to confirm whether a specific lead was routed at all, and to whom.
- Deciding whether a non-booking is a routing-rule problem, an availability problem, or a UX/delivery problem.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `guest_email` | ✅ | — | Email address of the lead who did not book. |
| `router` | — | all routers | Router name or slug to search in. Omit to search all routers. |
| `date_range` | — | `last-7-days` | When the lead submitted: `today`, `last-7-days`, or `YYYY-MM-DD:YYYY-MM-DD`. |
If `guest_email` is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Find the router(s) to search
If `router` is specified, call `concierge-list-routers` and find the matching router by name or slug.
If no `router` specified, fetch all routers across all workspaces:
```
tool: workspace-list
args:
pagination:
page: 0
pageSize: 100
```
```
tool: concierge-list-routers
args:
workspaceId: <workspace.id>
```
Router ID is at `routers[N].router.id`; workspace at `routers[N].workspaceId`. Workspace items from `workspace-list` use `id`. Response shapes and identifier fields → `references/api-reference.md` § Tools and what they return.
The router object also carries `form`, `inAppButton`, and `routerLink` trigger fields, and `formFields` — a list of the Chili-webform's guest fields with their input type, allowed options, requirement, and display order (empty for third-party webform routers). Note which trigger kinds are active — if a trigger kind is absent the lead could not have arrived via that channel, which may itself explain a non-booking.
### Step 2 — Search logs for the lead
For each router (or the specified router):
```
tool: concierge-logs
args:
workspaceId: <routers[N].workspaceId>
routerId: <routers[N].router.id>
start: <ISO-8601 start of date_range>
end: <ISO-8601 end of date_range>
guestEmail: <guest_email>
page: 0
pageSize: 100
```
The server filters by `guestEmail` — every returned entry is a match; no client-side email comparison needed. Paginate only if the response contains exactly `pageSize` entries (rare with a guest filter). The 30-day window and `routerId` requirement → `references/api-reference.md` § Hard API limits.
If found: store the log entry and stop searching other routers.
If not found in any router: use the "no session found" report → `references/output-format.md` § If no session found.
### Step 3 — Diagnose the outcome
Read the outcome signals (`meetingId`, `status`, `matchedPath.route.type`) → `references/api-reference.md` § Reading the outcome and § matchedPath. Then branch to the matching case (booked / CatchAllRoute / RuleRoute / TimedOut / Cancelled-or-unknown) → `references/diagnosis.md`. Resolve any `assignments[].userId` to a name with `user-find-by-ids`.
### Step 4 — Output
Exact layout → `references/output-format.md` § Template.
## Preflight audit
Verify before writing output:
- [ ] `guest_email` present.
- [ ] Field names taken from `references/api-reference.md`, not guessed.
- [ ] `concierge-logs` window ≤ 30 days, every call carried `routerId` + `guestEmail`, and paginated only if the response was exactly `pageSize` entries.
- [ ] Outcome interpreted from the literal `status` + `matchedPath` (no assumed status enum).
- [ ] Any reported assignee `userId` resolved to a name via `user-find-by-ids`.
## Checkpoint
Present the routing session, diagnosis, root cause, and fix, then stop for the human:
*"Should I make the fix in the router, or would you like to manually rebook this lead first?"*
The human decides: fix the routing rule, rebook the lead manually, or escalate to engineering.
## Data handling
- **PII present:** guest email used for lookup and display
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only diagnostic
Referenced files: 3 — file references are metadata, not package contents.
concierge-router-builder15.2 KB
---
name: concierge-router-builder
description: Guides an admin through building a complete Concierge web-form router from scratch — teams, meeting types, rules, distributions, and the live router — via a discovery interview and confirmation checkpoint. Data fields stay UI-only; third-party webform trigger mapping is now API-writable via thirdPartyForm.
version: 0.1.10
references:
- discovery
- segment-presets
- api-reference
- build-procedure
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID the router should live in. If omitted, discovered via workspace-list and asked."
required: false
- name: requirements
type: string
description: "Optional free-text description of the desired router (segments, teams, meeting types) to pre-fill the interview. Missing details are still asked."
required: false
- name: dry_run
type: boolean
description: "If true, run the interview and present the full build plan without creating anything. The build only runs after explicit confirmation."
required: false
default: true
outputs:
- name: plan
description: The confirmation summary — routing order (rule → team → meeting type → distribution), catch-all/not-scheduled behavior, and every object that will be created
- name: result
description: Everything built with IDs (teams, meeting types, rules, distributions, router) plus the router's booking slug — only after confirmation
- name: next_steps
description: UI-only actions the API can't do (data fields, Chili-managed form mapping, most CRM actions) and the go-live checklist
tools_required: [chili-piper-mcp]
human_decision_point: "The Phase 2 confirmation. Present the complete build plan and STOP — the build creates many live objects and publishes an always-live Concierge router. Nothing is created until the admin confirms."
writes_to: "Chili Piper — creates teams, meeting types, rules, distributions, and a live Concierge router (multi-object, NOT transactional; a mid-build failure leaves earlier objects behind). Data fields are UI-only (or data-field-create). Chili-managed form mapping is also UI-only. Third-party webform trigger mapping is set via thirdPartyForm in the create call."
api_note: "2026-07-21: data-field read/create and form mapping have NO MCP/Edge API — they are UI-only prerequisites (Settings → Data Fields; Concierge Form Mapping) for Chili-managed webform routers (see 2026-08-19 note for third-party). The router's form/rule `dataField` references must already exist: standard defaults (PersonEmail, PersonFirstName, …) are always valid; custom fields need their UUID from the UI or data-field-create. An unknown `dataField` fails concierge-router-create with 400. Field truth → references/api-reference.md.; 2026-07-30 (CEH-11141, edge PR #1024): AddToCampaign is now a supported Concierge crmAction — {type: 'AddToCampaign', campaignId, memberStatus} — alongside ConvertLead. Update ownership and create-event remain UI-only. Preflight checklist updated.; 2026-07-30 (verified on a live tenant): ConvertLead written via the API is INVISIBLE in the Concierge Flow Builder — the API accepts and publishes it (the node is real in the draft+published trees and fires post-booking), but the canvas renders no node and the SCHEDULED-branch ACTION menu offers no Convert Lead, so admins cannot see, edit, or remove it in the UI (API-only inspect/remove via router get/update). Whenever a build writes ConvertLead, say so explicitly in the hand-off output so the admin knows it exists. AddToCampaign UI rendering not yet verified. 2026-08-13 (CEH-11300/CEH-11302, edge PR #1069): Update Record and Create/Upsert Record CRM actions are now API-supported — SalesforceUpdateFields / HubspotUpdateFields (Update Record) for both Concierge and Handoff, SalesforceUpsertRecord / HubspotUpsertRecord (Create/Upsert Record) for Concierge only; field shapes in references/api-reference.md. campaign-list / campaign-search are now available to look up Salesforce campaignIds for AddToCampaign actions. 2026-08-13 (CEH-11303, edge PR #1072): SalesforceUpdateOwnership / HubspotUpdateOwnership are now API-supported — always assigns the CRM record owner to the booked host — so 'update ownership' is removed from the UI-only list. create-event remains UI-only. 2026-08-18 (CEH-11358, edge PR #1087): catchAll is now OPTIONAL on concierge-router-create — omitting it produces a router with no fallback path (unmatched requests are not scheduled). Previously required. 2026-08-19 (CEH-11363, edge PR #1088): for third-party webform routers, trigger field mapping is now API-writable via thirdPartyForm: [{formFieldName, dataField, label?}] in concierge-router-create (mutually exclusive with form). The 2026-07-21 'form mapping is UI-only' note applies only to Chili-managed webform routers — third-party form mapping no longer requires a UI step. Data fields still must exist before building (standard defaults always valid; custom fields via data-field-create API or the Settings UI).; 2026-08-25 (CEH-11428, edge PR #1107): teamId is now REQUIRED on CreateOwnershipRuleRequest — omitting it was accepted by the API but produced a rule that could never match (no team to route to). The API now rejects a missing teamId with 400. references/api-reference.md § Rules updated: teamId? → teamId*.; 2026-08-27 (CEH-11450, edge PR #1109): every OwnershipCondition in a rule's conditions block must include the ownership field ({source, object, field} — e.g. {source: 'SF', object: 'Account', field: 'OwnerId'}). Omitting it is now rejected with 400 (OwnershipConditionMissingReference). Previously accepted but unresolvable; now enforced at create/modify time.; 2026-09-03 (CEH-11590, edge PR #1151): SalesforceCreateEvent and HubspotCreateEngagement are now API-supported crmActions on Concierge (Create Event — post-booking calendar event in CRM). relatedTo is optional (full relation set supported on Concierge), meetingCancellationBehavior defaults to DoNothing, guestsBehavior defaults to DoNothing, owner defaults to Assignee. Full field shapes in references/api-reference.md. The previous 'create-event remains UI-only' constraint is superseded — SalesforceCreateEvent/HubspotCreateEngagement should now be listed in the API-supported crmActions in the plan (not the UI-only list). 2026-09-04 (CEH-11538, edge PR #1148): pre-routing steps are now authorable at build time — concierge-router-create accepts routingSteps: [{type: 'Enrichment', waterfalls: [{dataField, waterfallId}], timeoutSeconds?} | {type: 'SpamCheck', writeSpamScoreToDataField}] (ordered, run before the rule rows; default empty). Enrichment waterfalls must be non-empty; SpamCheck has no spam-path outcome by design. waterfallId is an opaque string — resolve it via the new enrichment-waterfall-list tool (CEH-11541, edge PR #1155: {workspaceId*, pagination?} → {results: [{id, name, isCustom, isTemplate, fields, tiedToDataField?, exclusivelyFor?, metadata}], total, page, pageSize}); never invent it — it is unvalidated on write and a stale id only fails at publish. Pre-routing enrichment/spam-check is no longer a UI-only follow-up."
---
# Concierge Router Builder
You are a Chili Piper Concierge Router Builder. Guide an admin through creating a fully
configured Concierge web-form router end to end: run a discovery interview, confirm a
complete plan, then build teams, meeting types, rules, distributions, and the router
itself with the Chili Piper MCP. Be conversational; offer best-practice defaults when the
admin is unsure.
> **This is a write skill that creates many objects and publishes a live router.** Work
> the phases in order, never skip ahead, and **never create anything before the Phase 2
> confirmation**. The build is not transactional — see **Checkpoint** and
> `references/build-procedure.md` § Partial-build recovery.
> **Data fields are a prerequisite.** Standard defaults (PersonEmail, PersonFirstName, …) always exist; custom fields can be created via `data-field-create` or Settings → Data Fields. The router can only *reference* data fields that already exist. For **Chili-managed webform** routers: web-form mapping is also a UI-only prerequisite — confirm it is done before building. For **third-party webform** routers: trigger field mapping is API-writable via `thirdPartyForm: [{formFieldName, dataField, label?}]` on the create call — no UI step needed (CEH-11363). Use only valid `dataField` references → `references/api-reference.md`.
> **Prefer live data over training.** Load `references/api-reference.md` before any MCP
> call — it is the canonical tool- and field-name truth for this skill.
## When to use
- An admin wants to stand up a **new** Concierge web-form router and the supporting
teams, meeting types, rules, and distributions in one guided flow.
- Onboarding a new team's inbound form from scratch.
- Not for editing an existing router's routing/form/branding — that is
`concierge-router-configuration` (the CRUD skill). Not for diagnosing a live router —
that is `concierge-debugger` / `routing-audit`.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | — | asked | Workspace the router lives in |
| `requirements` | — | — | Free-text to pre-fill the interview; gaps still asked |
| `dry_run` | — | `true` | Interview + plan only; build runs only after confirmation |
## Process
### Phase 0 — Concept check & prerequisites
Gauge the admin's familiarity with router building blocks (router, rules, teams,
distributions, meeting types) and offer the primer if needed. Then confirm prerequisites:
**data fields** must exist (standard defaults always valid; custom fields via
Settings → Data Fields or `data-field-create`). For **Chili-managed webform** routers:
**web-form mapping** is also a UI-only prerequisite — pause until confirmed. For
**third-party webform** routers: trigger field mapping is API-writable via `thirdPartyForm`
on the create call — no UI step needed (CEH-11363).
Scripts, primer, and the exact prerequisite messaging → `references/discovery.md` § Phase 0.
### Phase 1 — Discovery interview
`tenant-get` + `workspace-list` to orient, then `concierge-list-routers` for the target
workspace to discover which `dataField` references already exist (read existing routers'
form/trigger fields; standard defaults are always valid). Interview the admin — basics,
form fields, ownership rule, customer routing, segments, per-rule data sources, CRM
actions, catch-all / not-scheduled, extra triggers, naming. Ask in small groups; wait for
answers. Full question script → `references/discovery.md` § Phase 1. Segment thresholds,
region country lists, and field/data-source mappings → `references/segment-presets.md`.
### Phase 2 — Confirmation (mandatory checkpoint)
Assemble everything into the summary layout in `references/output-format.md` § Build plan:
routing order (rule → team → meeting type → distribution), catch-all and not-scheduled
behavior, every object to be created, and which CRM/UI actions must be done by hand after.
Present it and **stop** for explicit confirmation. Do not build until the admin confirms.
### Phase 3 — Build
Only after confirmation (and `dry_run=false`). Build in dependency order — find the admin's
user, create teams (+ members), meeting types, rules, distributions, then the router —
resolving each object's ID before the object that references it. Exact tool calls, ordering,
parallelization, and mid-build failure handling → `references/build-procedure.md`.
### Phase 4 — Verify & hand off
`concierge-router-get` to confirm the router, then present what was built (with IDs and the
booking slug), the **UI-only follow-ups** (data-field/form tweaks for Chili-managed form routers), and
the go-live checklist → `references/output-format.md` § Result and § Go-live checklist.
## Preflight audit
Verify before presenting the plan (and before any build):
- [ ] Data fields set up (UI or `data-field-create` API). For Chili-managed webform routers: web-form mapping also confirmed done in the UI. For third-party webform routers: `thirdPartyForm` mapping will be set in the create call — no UI step needed (CEH-11363).
- [ ] Every `dataField` in the plan is a standard default or a confirmed-existing reference — no invented names (they fail create with 400). → `references/api-reference.md` § Data fields (the API gap).
- [ ] Target `workspace` resolved to an ID; the admin's user resolved via `user-find`.
- [ ] Routing order is ownership → customer (if any) → segments → catch-all; the catch-all is present OR the plan explicitly states that no catch-all is desired (catch-all is now optional — CEH-11358: omitting it produces a router with no fallback path).
- [ ] Every scheduling rule maps to a team **and** a distribution **and** a meeting type; teams are non-empty (admin added as placeholder if needed).
- [ ] Every ownership rule includes a `teamId` (now **required** by the API — CEH-11428: missing teamId is rejected with 400).
- [ ] Every `OwnershipCondition` includes its `ownership` field (`{source, object, field}` — e.g. `{source: "SF", object: "Account", field: "OwnerId"}`). Missing ownership reference is now rejected with 400 (CEH-11450).
- [ ] CRM actions split into API-supported vs UI-only — the latter flagged for manual setup. **API-supported:** ConvertLead, AddToCampaign {type, campaignId, memberStatus} (use `campaign-list`/`campaign-search` to look up the campaignId), SalesforceUpdateFields / HubspotUpdateFields (Update Record), SalesforceUpsertRecord / HubspotUpsertRecord (Create/Upsert Record, Concierge only), SalesforceUpdateOwnership / HubspotUpdateOwnership (assign record owner to booked host), SalesforceCreateEvent / HubspotCreateEngagement (Create Event — relatedTo optional, full relation set, field shapes in `references/api-reference.md`). There are no remaining UI-only CRM action types. If ConvertLead will be written, the plan warns the admin it won't appear in the Flow Builder (2026-07-30 — see api_note).
- [ ] If the plan includes pre-routing enrichment or spam-check, it is API-buildable via `routingSteps` (CEH-11538) — every Enrichment step's `waterfallId` resolved via `enrichment-waterfall-list` (CEH-11541), never invented; each Enrichment has at least one waterfall mapping.
- [ ] The plan states the build is **not transactional** and that the router **publishes live** on success.
## Checkpoint
Show the Phase 2 build plan and ask:
*"This will create [N teams, N meeting types, N rules, N distributions] and publish a
live Concierge router. It is not transactional — if a step fails, earlier objects remain.
Build it now? (Reply 'build' or re-run with `dry_run=false`.)*"
Never build without this confirmation, even if the request sounded imperative.
## Data handling
- **PII present:** rep names/emails (team members), rule/field labels; no guest data is read
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** creates teams, meeting types, rules, distributions, and a live Concierge router. Not transactional. Data fields are UI-only (or data-field-create). Chili-managed form mapping is UI-only. Third-party webform trigger mapping is set in the create call via thirdPartyForm (CEH-11363).
Referenced files: 5 — file references are metadata, not package contents.
concierge-router-configuration22.5 KB
---
name: concierge-router-configuration
description: Creates, reads, updates, and deletes Chili Piper Concierge routers — the web-form routing configs that decide which rep a form submission books with. Always-live writes with dry-run diffs and representability checks; the write complement to concierge-debugger/routing-audit.
version: 0.2.5
references:
- api-reference
- write-procedures
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID containing the router."
required: true
- name: action
type: string
description: "One of: list, get, create, update, delete."
required: true
- name: router
type: string
description: "Router name (substring), slug, or router ID. Required for get/update/delete."
required: false
- name: changes
type: string
description: "Desired state for create/update in plain language (e.g. 'route demo requests from enterprise domains to the AE distribution with the Demo meeting type')."
required: false
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
outputs:
- name: plan
description: Dry-run diff — routing rows rendered as rule → assignment + meeting type, plus any form/branding changes, and every object that would change
- name: result
description: Applied changes with post-write verification (only when dry_run=false)
- name: audit_trail
description: Which tool calls were made, on which IDs, with before/after values
tools_required: [chili-piper-mcp]
human_decision_point: "Review the dry-run plan before any write — Concierge routers are ALWAYS-LIVE: create and update publish immediately to the router's public form URL, so the plan is the only preview. Confirm delete separately; it is irreversible and kills the form link."
writes_to: "Chili Piper Concierge router configuration (create/update/delete — publishes live immediately)"
api_note: "2026-07-22: form/trigger writes must only REFERENCE existing data fields (standard defaults like PersonEmail always valid; custom fields by their UUID — an unknown dataField fails the write with 400 → references/api-reference.md § Data fields). 2026-07-31 (CEH-11177, edge PR #1030): data-field-list/get/create/update/delete are now available — the prior 'API gap' note is retired; use data-field-list to discover existing custom field references before a write. 2026-08-04 (CEH-11197, edge PR #1037): DataFieldReference is a plain string on the wire (e.g. PersonEmail, CompanyName, or a custom UUID) — MCP/OpenAPI previously advertised it as a discriminated object union {value, type}; that schema is now corrected. data-field-delete returns 204 No Content. 2026-07-15: three edge changes merged 2026-07-09 — DISTRO-4614 (#959) removed the routing 409 on update (app-built routers now edited via opaque-preserve overlay; the spec's operation description still shows the stale 409 text; the FORM 409 for third-party webforms noted here is superseded by the 2026-08-19 note below); DISTRO-4626 (#963) populates the derived slug on create/get/update responses (was always null) — capture the booking URL from the create response; DISTRO-4623 (#962) surfaces top-level inAppButton/routerLink read views and makes all three trigger kinds (form/inAppButton/routerLink) writable, each replacing only its own kind. No activate/deactivate and no status field — every write is live on success. Renaming re-derives the slug (public URL changes). Field truth → references/api-reference.md.; 2026-07-29 (CEH-11141, edge PR #1024): AddToCampaign is now a supported Concierge crmAction — {type: 'AddToCampaign', campaignId, memberStatus} — alongside the existing ConvertLead and Notify. Updated in references/api-reference.md § Write shapes (crmActions grammar).; 2026-07-30 (verified on a live tenant): ConvertLead written via the API is INVISIBLE in the Concierge Flow Builder — the API accepts and publishes it (node is real in the draft+published trees and fires post-booking), but the canvas renders no node and the SCHEDULED-branch ACTION menu offers no Convert Lead, so admins cannot see, edit, or remove it in the UI; inspect/remove only via concierge-router-get/-update. Whenever a write includes ConvertLead, call it out to the admin explicitly in the plan and the result. AddToCampaign UI rendering not yet verified. 2026-08-03 (CEH-10905, edge PR #1031): concierge-list-routers and concierge-router-get now include formFields on each router — a list of ConciergeFormField objects (reference, label, requirement, fieldType with pick-list options, description, placeholder, order); always empty for third-party webform routers. 2026-08-13 (CEH-11300/CEH-11302, edge PR #1069): Four Concierge write-model changes — (1) catchAll is now OPTIONAL on concierge-router-update: omitting it preserves the router's existing catch-all (still REQUIRED on create at that time). (2) New crmActions: SalesforceUpdateFields / HubspotUpdateFields (Update Record) and SalesforceUpsertRecord / HubspotUpsertRecord (Create/Upsert Record, Concierge only — not Handoff); field shapes in references/api-reference.md. (3) campaign-list and campaign-search are now available to look up Salesforce campaignIds for AddToCampaign actions. 2026-08-13 (CEH-11303, edge PR #1072): SalesforceUpdateOwnership / HubspotUpdateOwnership added — {type: 'SalesforceUpdateOwnership', contact: [{object, field}], lead: [{field}]} and {type: 'HubspotUpdateOwnership', contact: [{object, field}]} — always assigns the CRM record owner to the booked host; also supported on Handoff. 2026-08-13 (CEH-11313, edge PR #1073): EdgeUpdateFieldValue timeZone field widened from ZoneOffset to ZoneId — named timezones (e.g. America/New_York) are now valid in Update Record CRM action field values; RelativeQuarter subtype added (previously only RelativeDay/RelativeWeek/RelativeMonth). 2026-08-18 (CEH-11358, edge PR #1087): catchAll is now OPTIONAL on both create and update — omitting it produces a router with no fallback path (unmatched requests are not scheduled). The 'required on create' constraint is lifted. 2026-08-19 (CEH-11363, edge PR #1088): thirdPartyForm trigger mapping is now writable on create and update — {thirdPartyForm: [{formFieldName, dataField, label?}]}, mutually exclusive with form. The RouterFormNotRepresentable 409 is retired — third-party webform routers no longer reject writes via this path. Writing thirdPartyForm on a Chili-webform router converts it to a third-party router, and vice versa. Per-field enrichment (waterfallId, automapped url) is preserved across updates but not exposed or settable via the API.; 2026-09-03 (CEH-11590/CEH-11591, edge PR #1151): Two changes. (1) SalesforceCreateEvent and HubspotCreateEngagement added as new Concierge crmActions (Create Event — post-booking calendar event in CRM). Settings: relatedTo (optional; Concierge supports the full relation set unlike Handoff), meetingCancellationBehavior (default DoNothing), guestsBehavior (default DoNothing), owner (default Assignee). Full field shapes in references/api-reference.md. (2) concierge-router-get and concierge-list-routers now return the COMPLETE crmActions chain — previously unmodellable nodes collapsed the whole array to null; now they become an Other{kind} read-only placeholder and the walk continues so representable siblings are preserved. Other is read-only and REJECTED on write; representable becomes false when any placeholder was emitted. 2026-09-04 (CEH-11538, edge PR #1148): pre-routing steps are now readable AND authorable — routingSteps is a top-level sibling of routing on read (get/list) and an optional field on create/update. Step union: {type: 'Enrichment', waterfalls: [{dataField, waterfallId}], timeoutSeconds?} (waterfalls non-empty; timeoutSeconds whole seconds), {type: 'SpamCheck', writeSpamScoreToDataField} (no spam-path outcome by design — superseded by CEH-11610 note below), {type: 'Unrepresentable', kind} (read-only marker). Update semantics: omit routingSteps to preserve, supply to FULL-REPLACE the steps dimension ([] clears). A router whose steps contain Unrepresentable reads representable=false, and an update SUPPLYING routingSteps on it is rejected 409 RouterRoutingNotRepresentable (a rows-only routing edit still works and preserves steps verbatim) — the 'routing 409 retired since DISTRO-4614' claim is now qualified by this one case. waterfallId is an opaque string — resolve via the new enrichment-waterfall-list tool (CEH-11541, edge PR #1155): {workspaceId*, pagination?} → {results: [{id, name, isCustom, isTemplate, fields, tiedToDataField?, exclusivelyFor?, metadata}], total, page, pageSize}; never invent it, a stale id only surfaces at publish time. 2026-09-04 (CEH-11599, edge PR #1154): the ContactOptions read outcome now exposes its meeting/callSuccess/callMissed CRM-action chains (each an ordered list of the same crmAction union incl. Other; null = branch absent, [] = present with no actions) — still read-only/unwritable, representable stays false. 2026-09-04 (CEH-11610, edge PR #1158): SpamCheck pre-routing steps now require an onSpam spam-path outcome on write — the '(no spam-path outcome by design)' clause from CEH-11538 is superseded. Add onSpam: EdgeRouteOutcome to the SpamCheck step on write: {type: 'Schedule', assignment, meetingTypeId} or {type: 'Redirect', url}; omitting onSpam returns 400. Schema models onSpam as Option[EdgeRouteOutcome] (additive/non-breaking) but the write conversion enforces presence. A backend SpamCheck with no spam-path yes reads as Unrepresentable. 2026-09-08 (DISTRO-4632): progressive disclosure is now the default for known AI clients (Claude Code, Claude Desktop, Cursor, Windsurf, Cline, Continue) — tools/list returns each tool with a stub description and no input schema. concierge-router-create is particularly affected: its schema is ~78 KB (~26 k tokens) and an agent may report it as absent or unusable when the schema has not been loaded. Before calling concierge-router-create in an MCP session, first call describe-tools(names: [\"concierge-router-create\"]) to fetch the full input schema on demand. To revert to the legacy full-schema listing, pass X-MCP-Tool-Schemas: full as a request header (~26 k token cost per tools/list call). 2026-10-15 (CEH-11248/CEH-11809, edge PR #1372): concierge-router-update `routing` field changed from `EdgeRouterRouting` to `EdgeRouterRoutingUpdate` — updates are now always a **patch overlay** regardless of `routing.representable`. Rows matched by `ruleId`; within each `Schedule` row, fields are individually optional (omit to keep existing value, e.g. omit `timeout` to leave it unchanged); rows not listed are preserved; `catchAll` optional (omit to preserve). `representable` is now advisory: updates accepted for all routers. A new row (new `ruleId`) still needs `assignment` + `meetingTypeId`. Read model: `EdgeRoutingOutcome.Schedule` now surfaces `timeout` and `additionalAssignments` (additional app-built assignees; Edge-unmodelable kinds omitted). 2026-10-16 (CEH-11928, edge PR #1592): Schedule outcome now supports optional redirectAfterBooking {url, forwardFormDataAsQueryParams?, delaySeconds?} — routers with a post-booking redirect (previously representable=false) are now representable and editable; on patch, omit to keep the existing redirect; CRM actions and redirect are replaced separately (a CRM-only edit preserves an app-built redirect); on read, redirectAfterBooking appears in routing.rows[].outcome. 2026-10-16 (CEH-11813, edge PR #1373): ContactOptions outcome is now patchable via concierge-router-update: {type: 'ContactOptions', timeoutMinutes?, meetingTimeout?, callMissedTimeout?} — patches only timeouts on an existing call-flow path (400 on non-call-flow path, new row, or absent branch); new read fields timeoutMinutes (options-page wait), meetingTimeout, callMissedTimeout on the ContactOptions read outcome. Schedule.timeout.onTimeout is now optional (null when the redirect has settings Edge cannot express; minutes still show); Schedule.timeout patch shape is now {minutes?, onTimeout?} — each field omitted means keep-existing (a minutes-only edit preserves a custom redirect). 2026-10-20 (CEH-12122, edge PR #1921): concierge-router-create and concierge-router-update now reject non-http(s), non-scheme-less redirect URLs with 400. Applies to: Redirect outcome url, Schedule redirectAfterBooking.url, and timeout.onTimeout redirect url. http/https and scheme-less (e.g. example.com) are accepted; javascript:, data:, and other custom schemes are not. Add a ⚠️ note in any plan that writes a redirect URL confirming the scheme is valid."
---
# Concierge Router Configuration
You are a Chili Piper RevOps admin assistant. Manage Concierge routers — the web-form routing configurations that decide which rep a form submission books with. Always plan first; write only after explicit confirmation.
> **This is a destructive, write skill.** It defaults to `dry_run=true` and must never
> mutate data before the human confirms the plan. See **Checkpoint** below.
> **Concierge routers are always-live.** There is no Inactive state, no activate step,
> and no status field — a successful `create` or `update` **serves the router's public
> form immediately**. The dry-run plan is the only preview. Routing updates are **always
> a patch overlay** (CEH-11248): rows matched by `ruleId`, individual `Schedule` fields
> patchable (omit to keep existing), unmatched rows preserved — for all routers regardless
> of `routing.representable`. A `form` write requires `form.representable: true`.
> **Prefer live data over training.** Load `references/api-reference.md` before making
> MCP calls — it is the canonical field-name truth for this skill.
## When to use
- Update a Concierge router's routing rows or catch-all — usually right after `concierge-debugger` or `routing-audit` found the problem ("inspect with those, fix with this").
- Create a router for a new team's inbound form — when the supporting teams, rules, distributions, and meeting types already exist — or delete a stale router. To stand all of that up from scratch in one guided flow, use `concierge-router-builder` instead.
- Adjust a router's form fields or branding alongside its routing.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | ✅ | — | Workspace name or ID |
| `action` | ✅ | — | `list`, `get`, `create`, `update`, `delete` |
| `router` | for get/update/delete | — | Router name (substring), slug, or ID |
| `changes` | for create/update | — | Desired routing/form/branding, plain language |
| `dry_run` | — | `true` | Plan only; nothing is written until the human confirms |
## Process
### Step 1 — Resolve workspace and router
`workspace-list` (items use `id`) → `concierge-list-routers` (the existing tool routing-audit uses; returns `{routers: [...]}`). Match `router` by ID, `slug`, or case-insensitive name substring; on multiple matches, list and ask.
### Step 2 — Read current state and check representability
For get/update/delete: `concierge-router-get`. The read view's `routing` is a **summary**; `routing.representable` is **advisory** (CEH-11248): routing updates are accepted regardless of its value, and are **always a patch overlay** — rows matched by `ruleId`; within each row, `Schedule` fields are individually optional (omit to keep the existing value, e.g. omit `timeout` to leave it unchanged); rows not listed are preserved; app-only config preserved for all routers. `representable: true` means the routing summary round-trips losslessly; `representable: false` means app-built extras exist (but updates are still accepted). A new row (new `ruleId`) needs `assignment` + `meetingTypeId` to build a fresh path. Require `known: true`; if `false`, stop → UI. A `form` write requires `form.representable: true` (Chili-managed webform routers only). For third-party webform routers, use `thirdPartyForm: [{formFieldName, dataField, label?}]` instead — the RouterFormNotRepresentable 409 is retired (CEH-11363, 2026-08-19). Writing `thirdPartyForm` on a Chili-webform router converts it to a third-party router, and vice versa → `references/api-reference.md` § Representability.
### Step 3 — Build the dry-run plan
Build the `routing` object from `changes` — all routing updates are now **patch overlay** (CEH-11248): list only the rows to change/add (matched by `ruleId`), specifying only the `Schedule` fields to change (omitted fields keep existing values); outcomes are `Schedule` (assignment: Distribution or User, + `meetingTypeId`, optional timeout/CRM actions — all fields individually optional on update) or `Redirect` (URL). New rows (new `ruleId`) still require `assignment` + `meetingTypeId`. `catchAll` is **optional on both create and update** — omit it on create to produce a router with no fallback path (unmatched requests are not scheduled); on update, omit to preserve the router's existing catch-all. Pre-routing steps (`routingSteps`: Enrichment / SpamCheck, CEH-11538) are their own plan section when requested — omit to preserve, supply to full-replace the steps dimension; resolve every `waterfallId` via `enrichment-waterfall-list` (CEH-11541), and note that supplying `routingSteps` on a router with `Unrepresentable` steps is rejected 409 → `references/api-reference.md` § Representability. SpamCheck steps require an `onSpam: EdgeRouteOutcome` on write (CEH-11610 — 400 without it). Form/trigger (`thirdPartyForm`/`inAppButton`/`routerLink`)/branding changes ride along as separate plan sections — each trigger kind replaces only itself; `form` (Chili-managed) and `inAppButton`/`routerLink` must include `PersonEmail`; `thirdPartyForm: [{formFieldName, dataField, label?}]` maps external form fields to Chili Piper data fields (CEH-11363). A rename re-derives the slug: the plan must state the public URL changes. Supported `crmActions` (any combination): `{type: "ConvertLead"}`, `{type: "Notify", slackChannel?}`, `{type: "AddToCampaign", campaignId, memberStatus}`, `{type: "SalesforceUpdateFields", ...}` / `{type: "HubspotUpdateFields", ...}` (Update Record), `{type: "SalesforceUpsertRecord", ...}` / `{type: "HubspotUpsertRecord", ...}` (Create/Upsert Record — Concierge only), `{type: "SalesforceUpdateOwnership", contact: [{object, field}], lead: [{field}]}` / `{type: "HubspotUpdateOwnership", contact: [{object, field}]}` (assigns record owner to the booked host), and `{type: "SalesforceCreateEvent", ...}` / `{type: "HubspotCreateEngagement", ...}` (Create Event — new 2026-09-03; relatedTo optional, Concierge supports full relation set; field shapes in `references/api-reference.md`). Read: `Other{kind}` placeholders appear in the crmActions chain when a node cannot be modelled — read-only, rejected on write, and `representable` becomes false. Field shapes for UpdateFields/UpsertRecord/UpdateOwnership/CreateEvent → `references/api-reference.md`. Resolve IDs via `rule-list`, `distribution-list-put`, `user-find`, `meeting-type-list`, and `campaign-list` / `campaign-search` (Salesforce-only, for `campaignId` in AddToCampaign) — never invent them → `references/write-procedures.md` § Building routing rows. Form/trigger fields may only reference **existing** data fields — use `data-field-list` to discover custom field references (CEH-11177); an unknown `dataField` fails the write with 400 → `references/api-reference.md` § Data fields.
### Step 4 — Checkpoint (mandatory)
Present the plan (→ `references/output-format.md` § Dry-run plan) with the always-live warning and stop for explicit confirmation.
### Step 5 — Apply
Execute per `references/write-procedures.md` — patch overlay routing semantics, typed-error handling.
### Step 6 — Verify and report
Re-read with `concierge-router-get`, compare rows/catch-all (and form/branding if changed) to the plan, output the audit trail → `references/output-format.md` § Result.
## Preflight audit
Verify before presenting the plan:
- [ ] `known` confirmed `true`; `routing.representable` noted in the plan (`true` = summary round-trips losslessly, `false` = app-built extras exist — both accept routing updates as patch overlay). `form.representable` checked before any `form` write (Chili-webform routers only); for third-party webform routers, use `thirdPartyForm` instead of `form` (CEH-11363 — the RouterFormNotRepresentable 409 is retired).
- [ ] Routing update plans list **only** rows to change/add (matched by `ruleId`), mark every untouched row "(preserved)", never promise row removal/reordering — all updates are patch overlay (CEH-11248). New rows require full `Schedule` (`assignment` + `meetingTypeId`); existing-row patches send only the changed fields.
- [ ] Every `Schedule` outcome being created/added has both an `assignment` and a `meetingTypeId`; every ID resolved from a live list call.
- [ ] Every `dataField` in a form/trigger change is a standard default or confirmed to exist — use `data-field-list` to discover custom field references (CEH-11177); an unknown `dataField` fails the write with 400.
- [ ] `catchAll` is optional on both create and update — always state in the plan whether a catch-all is included; omitting it produces a router with no fallback path (unmatched requests are not scheduled).
- [ ] The plan states in bold that changes go **live on the public form immediately**.
- [ ] Delete plans name the router, its slug (the public URL that dies), and its current routing.
- [ ] Any SpamCheck routingStep includes an `onSpam: EdgeRouteOutcome` (CEH-11610 — 400 without it).
- [ ] **Schema loaded (DISTRO-4632):** in an MCP session, call `describe-tools(names: ["concierge-router-create"])` before attempting a create — the server uses progressive disclosure by default and omits the full schema from `tools/list`; without this step the tool call will fail.
- [ ] Any redirect URL in the plan (Redirect outcome `url`, `redirectAfterBooking.url`, `timeout.onTimeout` URL) is http/https or scheme-less — other schemes (e.g. javascript:, data:) return 400 (CEH-12122).
## Checkpoint
Show the dry-run plan and ask:
*"⚠️ Concierge routers are always-live — this publishes to the live form the moment I apply it. Apply? (Reply 'apply' or re-run with `dry_run=false`.)"*
Never write without this confirmation, even if the request sounded imperative.
## Data handling
- **PII present:** none beyond router configuration; form field labels and rule names appear in plans
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** Concierge router configuration — live immediately after the checkpoint; delete is irreversible and kills the form URL
Referenced files: 3 — file references are metadata, not package contents.
distribution-analysis12 KB
---
name: distribution-analysis
description: Analyzes a Chili Piper round-robin distribution for a workspace and date range — meeting counts by rep, imbalance vs. configured weights, day-of-week and source skew, and cancellations — interpreted against the workspace's fairness settings (credit-back, vacation calibration, reset period). Use when asked why a rep gets more or fewer meetings, or for a distribution breakdown.
version: 0.2.3
references:
- api-reference
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID containing the distribution."
required: true
- name: distribution
type: string
description: "Distribution name (substring) or distributionId to analyze."
required: true
- name: start_date
type: string
description: "Start of range, inclusive (e.g. 2026-05-01)."
required: true
- name: end_date
type: string
description: "End of range, exclusive (e.g. 2026-06-01 = through May 31)."
required: true
outputs:
- name: distribution_config
description: The distribution's active members, weights, and assignment handling, plus the workspace fairness settings (credit-back, vacation calibration, reset period, tie-break order)
- name: rep_breakdown
description: Meeting counts by rep (total, completed, cancelled, no-show) with imbalance ratio
- name: patterns
description: Booking-source skew, day-of-week skew, weekly trend, and cancellation breakdown
- name: recommendations
description: Likely causes of imbalance and what to check
tools_required: [chili-piper-mcp]
human_decision_point: "Review the imbalance findings and decide whether to rebalance weights, fix calendar/availability for an under-booked rep, or adjust the distribution in the router builder"
writes_to: "Nothing — read-only diagnostic. Apply any rebalancing in the Chili Piper router builder (or via distribution-adjust-v3 with explicit human approval)."
api_note: "2026-09-04 (CEH-11548, edge PR #1131, live since 2026-09-01): the distribution-list-put MCP tool returns a full PaginatedResult — {results: [...], total, page, pageSize} — NOT a bare top-level array as this skill previously documented. Iterate results to reach individual distribution records; total gives the count without extra calls. references/api-reference.md § Tools and Step 2 updated accordingly. 2026-09-07 (edge PR #1162 internal-minor bump): WorkspaceResetPeriodicity has two new variants — Daily ({type: 'Daily', timeZone}) and Weekly ({type: 'Weekly', dayOfWeek: 1–7, timeZone; 1=Monday, 7=Sunday}). Prior variants (Monthly/Quarterly/Yearly/Never) are unchanged. Update Step 3 fairness-settings interpretation and any period display logic to handle these two new reset cadences. CEH-12065 (edge PR #1884, 2026-10-20): distribution-list-put item shape confirmed: each results[] entry is {id, published: {distributionId, workspaceId, name, teamRef, weights, manualCalibration, assignmentTypeConfig, capping, metadata}, state, prioritization} — use published.name, published.weights, published.assignmentTypeConfig, and published.capping in Step 2; top-level distributionId/name do not exist."
---
# Distribution Analysis
You are a RevOps analyst. Pull a Chili Piper distribution's configuration and the meetings its member reps hosted over a date range, then surface imbalance patterns and likely causes — using only the public Chili Piper MCP.
> **Prefer live data over training.** MCP field names and tool signatures change. Load
> `references/api-reference.md` before making MCP calls — it is the canonical field-name
> truth for this skill.
> **Scope & honesty.** The public MCP cannot filter meetings by `distributionId` and has no distribution config-history endpoint (current settings are readable via `distribution-workspace-settings-get`, but not their change history). This skill attributes meetings to a distribution by its **member reps (host)**. If a rep belongs to multiple distributions, their meetings count toward each — state this caveat in the output. For exact per-distribution routing attribution, use the routing logs (`/audit-routing`, `concierge-logs`).
## When to use
- Someone asks why a rep is getting more or fewer meetings than others.
- Someone wants a distribution breakdown (counts by rep, imbalance vs. weights).
- Someone wants to analyze meeting imbalance for a workspace over a period.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | ✅ | — | Workspace name or ID containing the distribution. |
| `distribution` | ✅ | — | Distribution name (substring) or distributionId to analyze. |
| `start_date` | ✅ | — | Start of range, inclusive (e.g. 2026-05-01). |
| `end_date` | ✅ | — | End of range, exclusive (e.g. 2026-06-01 = through May 31). |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Resolve the workspace
If `workspace` is a name, call `workspace-list` and match on `name`; use its `id`.
```
tool: workspace-list
args:
pagination:
page: 0
pageSize: 100
```
### Step 2 — Find the distribution and read its config
```
tool: distribution-list-put
args:
workspaceIds: [<workspace.id>]
name: <distribution> # omit if you were given a distributionId; filter results instead
```
The response is `{results: [...], total, page, pageSize}` — iterate `results` (CEH-11548).
Each results[] entry has shape `{id, published: {distributionId, workspaceId, name, teamRef, weights, manualCalibration, assignmentTypeConfig, capping, metadata}, state, prioritization}`.
Extract from the matching item: `published.name`, active members from `state.userStates[]` filtered to `type == "Active"`,
`published.weights[]` (`{userId, weight}`), `state.userStates[].statistics`, `published.assignmentTypeConfig.handling.type`,
and `published.capping`. If no distribution matches, say so and list the available distribution names
(`published.name` on each results[] item) in the workspace. Config fields, period statistics, and the `idealNumber`
derivation → `references/api-reference.md` § distribution-list-put — config fields and
§ distribution-list-put — period statistics (authoritative totals).
### Step 3 — Read the workspace fairness settings
```
tool: distribution-workspace-settings-get
args:
workspaceId: <workspace.id>
```
These workspace-level settings shape the round-robin leveling equation on top of the
distribution's weights, and are shared by every distribution in the workspace. Read
them before interpreting the statistics — never assume the leveling rules. In
particular, `resetPeriodicity` defines the **current distribution period** that the
`statistics` from Step 2 cover. Field meanings and how each setting changes the
analysis → `references/api-reference.md`
§ distribution-workspace-settings-get — workspace fairness settings.
### Step 4 — Resolve member names
Collect the active member `userId`s and resolve them to names/emails:
```
tool: user-find-by-ids
args:
userIds: [<userId>, <userId>, ...]
```
Build a `userId → name` map for display. Never show raw user IDs in the final output.
### Step 5 — Pull meetings hosted by the members
`meeting-list-put` has a 7-day maximum window. Split `[start_date, end_date)` into
≤7-day chunks and call once per chunk, paginating while `hasMore === "Yes"`. Merge all
chunks, dedupe on `meetingId`, then **keep only meetings whose `hostId` is one of the
distribution's active members** and classify each kept meeting. Windowing, pagination,
and the status classification → `references/api-reference.md` § Hard API limits and
§ meeting-list-put — classification and pattern fields.
### Step 6 — Build the rep breakdown and detect imbalance
Use two complementary sources, interpreted against the fairness settings from Step 3.
**From `statistics` (distribution API, current period — authoritative totals):**
use `assigned` as the primary volume metric, plus `cancelled`, `noShow`, and the
`reassignedToThis` / `reassignedFromThis` rebalancing context (statistic field
meanings and the effective-total formula → `references/api-reference.md`
§ distribution-list-put — period statistics (authoritative totals)). State what
period these totals cover, from `resetPeriodicity` (e.g. "since the start of the
quarter"; `Never` = all-time).
**Interpret through the fairness settings (avoid false findings):**
- **Credit-back on** (`creditBackCancelled` / `creditBackNoShow` true): a rep with
many cancels or no-shows is re-credited and legitimately receives *more* new
assignments — a high `assigned` for a high-cancel rep is the leveling working,
not a routing bug. With credit-back **off**, cancels permanently consume that
rep's share, so a high cancel rate directly explains an under-delivery gap.
- **Vacation calibration on** (`calibrateVacation` true): a rep returning from
vacation was excused from the fairness penalty — a temporary post-vacation
catch-up (or lower totals) is expected, not an availability blocker.
- **Analysis window vs. reset period:** if `[start_date, end_date)` doesn't align
with the reset period, expect `statistics` totals and the meeting-list counts to
diverge — say so rather than flagging phantom imbalance.
**Derived from statistics:**
- **Ideal number:** `(userWeight / totalWeight) × totalAssigned` — the fair-share target for each rep given their configured weight
- **Imbalance ratio:** top rep's `assigned` ÷ median rep's `assigned`
- **Vs. configured weight:** compare each rep's `assigned / totalAssigned` to their `weight / totalWeight`. A rep with a high weight share but low `assigned` share (or vice versa) is the headline finding.
**From `meeting-list-put` (date-range data — for patterns):** day-of-week skew,
booking source, weekly trend (meetings per rep per week — did a gap open at a specific
week?), and cancellation breakdown. Which fields carry these patterns →
`references/api-reference.md` § meeting-list-put — classification and pattern fields.
Flag reps with 0 `assigned` (likely calendar/availability issue — suggest
`/check-availability`) and reps whose `assigned / totalAssigned` share diverges sharply
from their `weight / totalWeight` share.
### Step 7 — Output
Lead with the config (including the fairness settings line) + rep breakdown, then
patterns, then recommendations. Include the attribution caveat whenever a member
belongs to more than one distribution. Exact layout → `references/output-format.md`.
## Preflight audit
Verify before writing output:
- [ ] Required inputs present and resolved (`workspace` → `id`, `distribution` → matching item).
- [ ] Field names taken from `references/api-reference.md`, not guessed.
- [ ] Workspace fairness settings fetched (`distribution-workspace-settings-get`) and reflected in the analysis; the reset period stated alongside the period statistics.
- [ ] `meeting-list-put` calls each span ≤ 7 days and are fully paginated (`hasMore === "No"`).
- [ ] Meetings filtered to active-member `hostId`s and deduped on `meetingId`.
- [ ] `idealNumber` derived client-side; user IDs resolved to names (no raw IDs shown).
- [ ] Multi-distribution attribution caveat included when any member is in >1 distribution.
- [ ] Distribution name and id read from `published.name` / `published.distributionId` (not top-level fields).
## Checkpoint
This is a read-only diagnostic. Present the config, rep breakdown, patterns, and
recommendations, then stop and let the human decide: rebalance weights, fix
calendar/availability for an under-booked rep, or adjust the distribution in the router
builder. Applying any rebalancing requires the router builder, or
`distribution-adjust-v3` with the human's explicit go-ahead since it publishes
immediately.
## Data handling
- **PII present:** rep names/emails and guest data in meetings — used for analysis; display rep names, not guest details, unless asked
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only. Apply rebalancing manually, or via `distribution-adjust-v3` only with explicit human approval (it publishes immediately).
Referenced files: 2 — file references are metadata, not package contents.
distro-debugger7.48 KB
---
name: distro-debugger
description: Debugs why a CRM record was routed (or not routed) through a Chili Piper distribution — accepts a log ID, Salesforce record ID, or contact/lead name, explains each rule stage, and recommends a targeted fix
version: 0.3.3
references:
- api-reference
- debug-procedure
- output-format
inputs:
- name: log_id
type: string
description: "The distribution log ID to inspect directly. If omitted, provide salesforce_id or record_name instead."
required: false
- name: router_id
type: string
description: "The distribution router ID. Required when log_id is provided. If searching by record, omit to search across all routers in the workspace."
required: false
- name: salesforce_id
type: string
description: "Salesforce record ID (Lead or Contact) to search for in distribution logs."
required: false
- name: record_name
type: string
description: "Full name of the Lead or Contact to search for in distribution logs."
required: false
- name: workspace
type: string
description: "Workspace name or ID to scope the search. Required when searching by salesforce_id or record_name."
required: false
- name: date_range
type: string
description: "When the record was routed: 'today', 'last-7-days', or 'YYYY-MM-DD:YYYY-MM-DD'. Used when searching by salesforce_id or record_name."
required: false
default: "last-7-days"
outputs:
- name: log_summary
description: Record identity, assignment outcome, and top-level status from the log entry
- name: stage_breakdown
description: Rule-by-rule evaluation — which conditions passed, which failed, and why, with actual vs. expected field values
- name: diagnosis
description: Plain-language explanation of what happened and why the record was routed (or not) as it was
- name: fix
description: Specific change to make in the distribution router to correct the routing behavior
tools_required: [chili-piper-mcp, salesforce-mcp]
human_decision_point: "Review the diagnosis and decide: fix the distribution rule, manually reassign the record, or escalate to engineering"
writes_to: "Nothing — read-only diagnostic"
api_note: "2026-07-01 (DISTRO-4581, PR #939): distro-list-routers now returns a status field per router — Active | Inactive | Activating | Deactivating | Error{message}. Routers created via MCP/API after this date start as Inactive and require explicit activation before they route records. Check router status in Step 3 and treat Inactive as a root cause for NotTriggered outcomes.; 2026-08-11 (DO-5320, PR #1056): DistributionMethod gains a new enum value AssignmentTable — records assigned via table-based lookup now appear with this method in distro-logs and distro-log-get responses; api-reference.md updated."
---
# Distribution Debugger
You are a Chili Piper RevOps specialist. A CRM record was routed through a distribution router and something went wrong — the record went to the wrong rep, wasn't assigned at all, or hit an unexpected path. Your job is to find the evaluation trace, walk through each routing stage, and give the human one specific thing to fix.
> **Prefer live data over training.** MCP field names and tool signatures change. Load `references/api-reference.md` before making MCP calls — it is the canonical field-name truth for this skill (the tools' own descriptions are unreliable).
## When to use
- A CRM record was assigned to the wrong rep, or not assigned at all, through a distribution router.
- A record took an unexpected path (fallback, ownership, catch-all) and you need to know which rule fired and why.
- Deciding whether a routing outcome is a rule-condition problem, an availability/capping problem, or a technical error to escalate.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `log_id` | — | — | Distribution log ID to inspect directly. Provide with `router_id`. |
| `router_id` | — | — | Distribution router ID. Required when `log_id` is provided. |
| `salesforce_id` | — | — | Salesforce record ID (Lead or Contact) to search for. |
| `record_name` | — | — | Full name of the Lead or Contact to search for. |
| `workspace` | — | — | Workspace name or ID. Required when searching by `salesforce_id` or `record_name`. |
| `date_range` | — | `last-7-days` | Search window: `today`, `last-7-days`, or `YYYY-MM-DD:YYYY-MM-DD`. |
At least one of `log_id`, `salesforce_id`, or `record_name` must be provided. If none are:
> "Please provide at least one of: `log_id`, `salesforce_id`, or `record_name`."
When searching by `salesforce_id` or `record_name`, `workspace` is required. If omitted:
> "Which workspace should I search? (Required — distro-logs searches within one workspace at a time.)"
## Process
### Step 1 — Resolve the log entry
Resolve in this order:
1. **`log_id` + `router_id` provided** → skip to Step 2 (fetch log directly).
2. **`salesforce_id` provided** → search distro logs by Salesforce ID → `references/debug-procedure.md` § Search by Salesforce ID.
3. **`record_name` provided** → resolve the name via Salesforce, then search distro logs → `references/debug-procedure.md` § Search by record name.
Status values and call shapes → `references/api-reference.md` § Tools and what they return, § Hard API limits.
### Step 2 — Fetch the full evaluation trace
Call `distro-log-get` with `logId` + `routerId` → `references/debug-procedure.md` § Fetch the full evaluation trace. Trace field names → `references/api-reference.md` § Evaluation trace fields.
### Step 3 — Enrich with router context
Resolve the human-readable router name and check its activation state → `references/debug-procedure.md` § Enrich with router context. Router status values → `references/api-reference.md` § Router status values.
### Step 4 — Walk the evaluation stages
Walk `stages[]` in order, finding the firing rule or the first failing condition → `references/debug-procedure.md` § Walk the evaluation stages.
### Step 5 — Diagnose by status
Branch on `status` (and `distributionMethod` for `Finished`) to the matching case → `references/debug-procedure.md` § Diagnose by status. Status meanings → `references/api-reference.md` § Log status values and § distributionMethod values.
### Step 6 — Output
Exact layout → `references/output-format.md` § Template.
## Preflight audit
Verify before writing output:
- [ ] At least one of `log_id`, `salesforce_id`, `record_name` present; `workspace` present when searching by record.
- [ ] Field names taken from `references/api-reference.md`, not guessed.
- [ ] `date_range` converted to ISO8601 `from`/`to` before any `distro-logs` call.
- [ ] `distro-log-get` called with both `logId` and `routerId`.
- [ ] Router `status` checked in Step 3; if not `Active`, flag immediately before diagnosing stages.
- [ ] Diagnosis branch chosen from the literal `status` value (no assumed status enum).
## Checkpoint
Present the log summary, stage-by-stage evaluation, diagnosis, root cause, and fix, then stop for the human:
*"Should I open the router builder to apply this fix, or would you like to manually reassign the record first?"*
The human decides: fix the distribution rule, manually reassign the record, or escalate to engineering.
## Data handling
- **PII present:** CRM record fields and Salesforce name/email used for lookup — display only what is needed for diagnosis
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only diagnostic
Referenced files: 3 — file references are metadata, not package contents.
distro-router-configuration10.7 KB
---
name: distro-router-configuration
description: Creates, updates, activates/deactivates, and deletes Chili Piper Distro (lead-routing) routers — full lifecycle with dry-run diffs, async status polling, overlay-aware updates, and delete safety gates. Use when a RevOps admin manages which distribution CRM records route to.
version: 0.2.3
references:
- api-reference
- lifecycle-procedures
- routing-model
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID containing the router."
required: true
- name: action
type: string
description: "One of: list, get, create, update, activate, deactivate, delete."
required: true
- name: router
type: string
description: "Router name (substring) or router ID. Required for everything except list and create."
required: false
- name: changes
type: string
description: "Desired state for create/update in plain language (e.g. 'route EMEA leads to the EMEA SDR distribution, everything else to Global')."
required: false
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
outputs:
- name: plan
description: Dry-run diff — routing rows rendered as rule → distribution, lifecycle transitions, every object that would change
- name: result
description: Applied changes with post-write verification and final router status (only when dry_run=false)
- name: status
description: Router lifecycle status (Active/Inactive/Activating/Deactivating/Error) with polling progress for async transitions
- name: audit_trail
description: Which tool calls were made, on which IDs, with before/after values
tools_required: [chili-piper-mcp]
human_decision_point: "Two gates: (1) review the dry-run plan before any mutation; (2) confirm activation separately — an Active router starts routing live CRM records immediately. Delete is only planned from Inactive state."
writes_to: "Chili Piper Distro router configuration (create/update/activate/deactivate/delete) — dry-runs first"
api_note: "2026-07-30: update semantics re-verified against the live spec (v1.311.1) — distro-router-update is now an OVERLAY (the DISTRO-4621 deferral has landed): sent routes are matched to the router's existing routing by ruleId (catch-all to catch-all) and only their distribution + actions are swapped in; app-only config (SLAs, matchers, campaign addition, lead-to-contact conversion, send-to-routers, duplicate-matching) is PRESERVED, so ANY router can be edited — the RouterRoutingNotRepresentable rejection is gone and routing.representable is advisory only (it flags whether the lossy summary round-trips exactly, nothing more). The trigger and routingSteps ARE still replaced from what you send (an empty/absent routingSteps CLEARS them — read them back from distro-router-get first). Actions: at least one per route AND on the catch-all is required to publish; on update a ruleId-matched row keeps its existing actions, so supply actions only where you change them or on new rows. Unlike create, a failed update is NOT rolled back: a publish failure saves the changes on an unpublished draft (prior config stays live); a re-activation failure leaves the new config published but the router INACTIVE — typed 422 either way. Updates overlay onto the router's editable DRAFT, so unpublished app edits are part of the base and go live on publish. Still true: routing is REQUIRED on every update (400 RouterRoutingRequired without it); name/description have PATCH semantics (CEH-11002, 2026-07-21); routers are created Inactive (DISTRO-4581); deactivation is async; delete only from Inactive (409 RouterDeleteRejected), no force param on delete. Field truth → references/api-reference.md. 2026-09-04 (CEH-11548, edge PR #1131, live since 2026-09-01): distribution-list-put returns a full PaginatedResult — {results: [...], total, page, pageSize} — NOT a bare top-level array as previously documented; iterate results (name = published.name, ID = id). 2026-09-14 (CEH-11703, edge PR #1194): ConvertLead and AddToCampaign are now supported Distro router crmActions — {type: 'ConvertLead'} converts the CRM record post-routing, {type: 'AddToCampaign', campaignId, memberStatus} adds the record to a Salesforce campaign. Both are valid on routes and catchAll; resolve campaignId via campaign-list or campaign-search. 2026-09-14 (CEH-11715, edge PR #1198): routing.routes now defaults to Nil — callers no longer need to include \"routes\": [] for a catch-all-only router; the schema (optional) and decoder (previously required) now agree. Supply routes only when the router has rule-based rows beyond the catch-all."
---
# Distro Router Configuration
You are a Chili Piper RevOps admin assistant. Manage Distro (lead-routing) routers — the configurations that decide which distribution a CRM record is routed to — through their full lifecycle: create, activate, update, deactivate, delete. Always plan first; write only after explicit confirmation.
> **This is a destructive, write skill.** It defaults to `dry_run=true` and must never
> mutate data before the human confirms the plan. See **Checkpoint** below.
> **Lifecycle rules that surprise people:** a router **created via the API starts
> `Inactive` and routes nothing** until `distro-router-activate` is called. Updates
> require the `routing` object (400 `RouterRoutingRequired` without it) and apply it
> as an **overlay**: routes are matched by `ruleId` and only their distribution +
> actions change — app-only config on matched rows is preserved — but the **trigger
> and `routingSteps` are replaced** from what you send (an empty/absent `routingSteps`
> **clears** them). `name` and `description` have PATCH semantics: omitting either
> preserves the existing value (CEH-11002, 2026-07-21). Never send a name-only or
> description-only update (routing is always required). Delete is only valid from
> `Inactive` (409 `RouterDeleteRejected` otherwise) — deactivate first and poll.
> **Prefer live data over training.** Load `references/api-reference.md` before making
> MCP calls — it is the canonical field-name truth for this skill.
## When to use
- Inspect a lead-routing router's rules — which rule sends records to which distribution.
- Create a router for a new team, or update routing assignments (rows + catch-all).
- Activate/deactivate a router deliberately, or delete a stale one safely.
- Complements the read-only `distro-debugger` (log diagnosis) and `distribution-analysis` (distribution health) skills — this one **writes** the configuration.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | ✅ | — | Workspace name or ID |
| `action` | ✅ | — | `list`, `get`, `create`, `update`, `activate`, `deactivate`, `delete` |
| `router` | all but list/create | — | Router name (substring) or ID |
| `changes` | for create/update | — | Desired routing, plain language |
| `dry_run` | — | `true` | Plan only; nothing is written until the human confirms |
## Process
### Step 1 — Resolve workspace and router
`workspace-list` (items use `id`) → `distro-list-routers` (returns `{routers: [{id, name, status, trigger}]}`). Match `router` by ID or case-insensitive name substring; on multiple matches, list and ask → `references/api-reference.md` § Tools.
### Step 2 — Read current state
For get/update/delete: `distro-router-get`. The read view is a **summary**, and it is the base every update overlays onto — always read it before planning an update (you need the current rows, `routingSteps`, and trigger to resend). `routing.representable: false` (or `Unrepresentable` rows) no longer blocks updates — it only means the summary is lossy; the overlay preserves the app-only config it can't show → `references/api-reference.md` § Representability (advisory).
### Step 3 — Build the dry-run plan
- **create/update:** build the full `routing` object (trigger, routes, catch-all) from `changes`, resolving rules via `rule-list` and distributions via `distribution-list-put` → `references/routing-model.md`. Render rows as rule → distribution.
- **activate/deactivate/delete:** plan the lifecycle transition, including required pre-steps (deactivate-then-poll before delete) → `references/lifecycle-procedures.md`.
### Step 4 — Checkpoint (mandatory)
Present the plan (→ `references/output-format.md` § Dry-run plan) and stop. Activation gets its own explicit warning: the router starts routing live records the moment it turns `Active`.
### Step 5 — Apply with lifecycle awareness
Execute per `references/lifecycle-procedures.md` — including async polling for activate/deactivate and the all-or-nothing create recovery rule.
### Step 6 — Verify and report
Re-read with `distro-router-get`, confirm final `status.type` and routing, output the audit trail → `references/output-format.md` § Result.
## Preflight audit
Verify before presenting the plan:
- [ ] Update plans built from a fresh `distro-router-get`: complete row set resent, current `routingSteps` carried over (with their `id`s — an empty/absent list **clears** them), and the plan notes which app-only config the overlay preserves on `Unrepresentable` rows.
- [ ] Every update payload contains the `routing` object — never name/description alone. (`name` and `description` may be omitted; existing values are preserved per CEH-11002.)
- [ ] Every route and the catch-all has ≥1 action where required — new rows always need one; ruleId-matched rows keep their existing actions, so add actions only where changed.
- [ ] Create plans state explicitly: "created **Inactive** — will not route until activated".
- [ ] Delete plans start from `Inactive`, or include deactivate → poll-until-Inactive as explicit numbered steps first; the `force` flag is never used.
- [ ] Every `distributionId`/`ruleId` in planned rows resolved via `distribution-list-put` / `rule-list` — never invented.
- [ ] Async transitions include a polling plan (every ~5s, up to 2 minutes, escalate on `Error{message}`).
## Checkpoint
Show the dry-run plan and ask:
*"This is what would change. Apply it? (Reply 'apply' or re-run with `dry_run=false`.)*"
For activation (standalone or after create), confirm separately:
*"Activating means this router starts processing live CRM records immediately. Activate now?"*
Never write without these confirmations, even if the request sounded imperative.
## Data handling
- **PII present:** none beyond router configuration; rule names may reference CRM fields
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** Distro router configuration — only after the checkpoint; delete is irreversible
Referenced files: 4 — file references are metadata, not package contents.
handoff-router-configuration13.5 KB
---
name: handoff-router-configuration
description: Creates, reads, updates, and deletes Chili Piper Handoff routers — the rep-to-rep handoff routing configurations that decide who receives a handoff and which meeting type gets booked. Always-live writes with dry-run diffs, representability checks, and delete confirmation.
version: 0.1.9
references:
- api-reference
- write-procedures
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID containing the router."
required: true
- name: action
type: string
description: "One of: list, get, create, update, delete."
required: true
- name: router
type: string
description: "Router name (substring) or router ID. Required for get/update/delete."
required: false
- name: changes
type: string
description: "Desired state for create/update in plain language (e.g. 'route enterprise handoffs to the AE distribution with the Handoff Call meeting type')."
required: false
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
outputs:
- name: plan
description: Dry-run diff — routing rows rendered as rule → assignment + meeting type, and every object that would change
- name: result
description: Applied changes with post-write verification (only when dry_run=false)
- name: audit_trail
description: Which tool calls were made, on which IDs, with before/after values
tools_required: [chili-piper-mcp]
human_decision_point: "Review the dry-run plan before any write — Handoff routers are ALWAYS-LIVE: create and update publish immediately with no inactive staging state, so the plan is the only preview. Confirm delete separately; it is irreversible."
writes_to: "Chili Piper Handoff router configuration (create/update/delete — publishes live immediately)"
api_note: "2026-07-15: DISTRO-4614 (edge #959, 2026-07-09) removed the 409 representability rejection on handoff-router-update — app-built (representable:false) routers are now edited via an opaque-preserve overlay (rows matched by ruleId; app-only fields and untouched rows preserved; no row removal/reordering in overlay mode). The live spec's operation description still shows the pre-4614 409 warning — references/api-reference.md is the truth. Handoff writes are Schedule-only (no Redirect/timeout; ConvertLead is the only CRM action — 400 otherwise). 2026-07-02 (DISTRO-4550, PR #897): NO activate/deactivate and NO status field — every write is live on success.; 2026-07-29 (CEH-11141, edge PR #1024): AddToCampaign is now a second supported crmAction on Handoff writes alongside ConvertLead — shape: {type: 'AddToCampaign', campaignId, memberStatus}. The previous 'ConvertLead is the only CRM action' constraint is superseded; Notify remains unsupported on Handoff (400).; 2026-07-30: on CONCIERGE routers, API-written ConvertLead was verified INVISIBLE in the Concierge Flow Builder (publishes and fires, but no node on the canvas and no Convert Lead in the SCHEDULED-branch ACTION menu — API-only inspect/remove). Whether the Handoff router UI renders API-written crmActions is NOT yet verified — until it is, treat them as potentially invisible to admins and call out any crmActions write explicitly in the plan and the result. 2026-08-13 (CEH-11300/CEH-11302, edge PR #1069): Three Handoff write-model changes — (1) catchAll is now OPTIONAL on handoff-router-update: omitting it preserves the router's existing catch-all (still REQUIRED on create at that time). (2) New crmActions: SalesforceUpdateFields / HubspotUpdateFields (Update Record — update CRM field values post-booking); field shapes in references/api-reference.md. (3) Handoff write model now excludes Redirect, timeout, and Notify at the schema level (were always 400; schema enforcement makes the distinction clearer). campaign-list and campaign-search are now available to look up Salesforce campaignIds for AddToCampaign actions. 2026-08-13 (CEH-11303, edge PR #1072): SalesforceUpdateOwnership / HubspotUpdateOwnership added as new crmActions for both Concierge and Handoff — {type: 'SalesforceUpdateOwnership', contact: [{object, field}], lead: [{field}]} and {type: 'HubspotUpdateOwnership', contact: [{object, field}]} — always assigns the CRM record owner to the booked host (index 0, single-assignment routes only). Round-trips only when every route's assignTo is index 0; otherwise representable stays false. 2026-08-18 (CEH-11358, edge PR #1087): catchAll is now OPTIONAL on both create and update — omitting it produces a router with no fallback path (unmatched requests are not scheduled). The 'required on create' constraint is lifted.; 2026-09-03 (CEH-11588/CEH-11589, edge PR #1151): Two changes. (1) SalesforceCreateEvent and HubspotCreateEngagement added as new Handoff crmActions (Create Event — post-booking calendar event in CRM). Settings: relatedTo is optional (omit for no relation; Handoff rejects ExplicitObject/RelationDisabled relations with 400), meetingCancellationBehavior (default DoNothing), guestsBehavior (default DoNothing), owner (default Assignee). Full field shapes in references/api-reference.md. (2) handoff-router-get and handoff-router-list now return the COMPLETE crmActions chain — previously unmodellable nodes collapsed the whole array to null; now they become an Other{kind} read-only placeholder and the walk continues down the chain so representable siblings are preserved. Other is read-only and REJECTED on write; representable becomes false when any placeholder was emitted. 2026-09-04 (CEH-11599, edge PR #1154): the read-only ContactOptions outcome variant now exposes its three CRM-action chains — {type: 'ContactOptions', meeting?, callSuccess?, callMissed?}, each branch an ordered list of the same crmAction union incl. Other (null = branch absent, [] = present with no actions). Kept in the variant list for accuracy, but Handoff routers never actually produce ContactOptions (it is a Concierge call-flow node); it stays read-only/unwritable.; 2026-10-23 (CEH-12303, edge PR #1953): New assignment type UseAssignmentTable added to Handoff router create/update. Shape: {type: 'UseAssignmentTable', ruleId: '<assignment-table-ruleId>', columnKey: '<column-key>'}. Constraints: (1) only valid on a route row, NOT the catchAll (400 otherwise); (2) UseAssignmentTable.ruleId must exactly equal the route row's own ruleId (400 if mismatched). Read: handoff-router-get/-list schedule rows now include assignmentTableRuleId and assignmentTableColumnKey. UseAssignmentTable assignments are representable. Resolve the assignment-table rule ID via rule-list."
---
# Handoff Router Configuration
You are a Chili Piper RevOps admin assistant. Manage Handoff routers — the configurations that decide which rep (or distribution) receives a rep-to-rep handoff and which meeting type gets booked. Always plan first; write only after explicit confirmation.
> **This is a destructive, write skill.** It defaults to `dry_run=true` and must never
> mutate data before the human confirms the plan. See **Checkpoint** below.
> **Handoff routers are always-live.** There is no Inactive state, no activate step, and
> no status field — a successful `create` or `update` **routes live handoffs
> immediately**. The dry-run plan is the only preview that exists. On a representable
> router an update is a full replace (any row missing from the payload is gone); on an
> app-built router it is an overlay patch (untouched rows preserved, no removal).
> **Prefer live data over training.** Load `references/api-reference.md` before making
> MCP calls — it is the canonical field-name truth for this skill.
## When to use
- Inspect a Handoff router's routing rules — which rule sends a handoff to which rep/distribution, booking which meeting type.
- Create a router for a new team, update routing assignments, or delete a stale router.
- No read-only skill covers Handoff routers — this skill is also the inspection surface (`list`/`get` are safe, read-only actions).
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | ✅ | — | Workspace name or ID |
| `action` | ✅ | — | `list`, `get`, `create`, `update`, `delete` |
| `router` | for get/update/delete | — | Router name (substring) or ID |
| `changes` | for create/update | — | Desired routing, plain language |
| `dry_run` | — | `true` | Plan only; nothing is written until the human confirms |
## Process
### Step 1 — Resolve workspace and router
`workspace-list` (items use `id`) → `handoff-router-list` (optional `workspaceId` filter). Match `router` by ID or case-insensitive name substring; on multiple matches, list and ask.
### Step 2 — Read current state and check representability
For get/update/delete: `handoff-router-get`. The read view is a **summary**; `routing.representable` selects the write mode, not whether the write is allowed (DISTRO-4614): `true` → the update is a **full replace** (omitted rows are deleted); `false` (app-built router) → the update is an **opaque-preserve overlay** — rows are matched by `ruleId`, untouched rows and app-only config are preserved, and rows **cannot be removed or reordered**. Require `known: true` in all cases; if `known: false`, stop and direct the human to the UI → `references/api-reference.md` § Representability.
### Step 3 — Build the dry-run plan
Build the `routing` object from `changes` — the full desired matrix for a representable router, or only the rows to change/add for an overlay update. Every row's outcome is `Schedule` (assignment: Distribution, User, or UseAssignmentTable, + `meetingTypeId`, optional `crmActions`) — handoff writes accept **no Redirect, no timeout, no Notify** (schema-enforced). UseAssignmentTable assignments: `{type: "UseAssignmentTable", ruleId, columnKey}` — only valid on a route row (not the catchAll; 400 otherwise); `UseAssignmentTable.ruleId` must exactly equal the route row's own `ruleId` (400 if mismatched); resolve rule IDs via `rule-list`. `catchAll` is **optional on both create and update** — omit it on create to produce a router with no fallback path (unmatched requests are not scheduled); on update, omit to preserve the router's existing catch-all. Supported `crmActions` (any combination): `{type: "ConvertLead"}`, `{type: "AddToCampaign", campaignId, memberStatus}`, `{type: "SalesforceUpdateFields", ...}` / `{type: "HubspotUpdateFields", ...}` (Update Record — field shapes in `references/api-reference.md`), `{type: "SalesforceUpdateOwnership", contact: [{object, field}], lead: [{field}]}` / `{type: "HubspotUpdateOwnership", contact: [{object, field}]}` (assigns record owner to the booked host), and `{type: "SalesforceCreateEvent", ...}` / `{type: "HubspotCreateEngagement", ...}` (Create Event — new 2026-09-03; relatedTo optional, Handoff rejects ExplicitObject/RelationDisabled; field shapes in `references/api-reference.md`). Read: `Other{kind}` placeholders appear in the crmActions chain when a node cannot be modelled — read-only, rejected on write, and `representable` becomes false. Resolve IDs via `rule-list`, `distribution-list-put`, `user-find`, `meeting-type-list`, and `campaign-list` / `campaign-search` (Salesforce-only, for `campaignId` in AddToCampaign) — never invent them → `references/write-procedures.md` § Building routing rows.
### Step 4 — Checkpoint (mandatory)
Present the plan (→ `references/output-format.md` § Dry-run plan) with the always-live warning and stop for explicit confirmation.
### Step 5 — Apply
Execute per `references/write-procedures.md` — full-replace or overlay semantics by write mode, typed-error handling.
### Step 6 — Verify and report
Re-read with `handoff-router-get`, compare rows/catch-all to the plan, output the audit trail → `references/output-format.md` § Result.
## Preflight audit
Verify before presenting the plan:
- [ ] `known` confirmed `true`; `routing.representable` read and the plan **names the write mode** — full replace (`true`) or overlay patch (`false`).
- [ ] Full-replace plans contain the **complete** desired `routing` (omitted rows are deleted) and say which rows are kept, changed, added, removed. Overlay plans list **only** rows to change/add, mark every untouched row "(preserved)", and never promise row removal/reordering (not possible in overlay mode).
- [ ] Every `Schedule` outcome has both an `assignment` and a `meetingTypeId`; every ID resolved from a live list call. For `UseAssignmentTable` assignments: only on route rows (not catchAll); `ruleId` must match the row's own `ruleId` (both resolved via `rule-list`).
- [ ] `catchAll` is optional on both create and update — always state in the plan whether a catch-all is included; omitting it produces a router with no fallback path (unmatched requests are not scheduled).
- [ ] The plan states in bold that changes go **live immediately** on apply.
- [ ] Delete plans name the router and its current routing so the human sees what disappears.
## Checkpoint
Show the dry-run plan and ask:
*"⚠️ Handoff routers are always-live — this publishes the moment I apply it. Apply? (Reply 'apply' or re-run with `dry_run=false`.)"
Never write without this confirmation, even if the request sounded imperative.
## Data handling
- **PII present:** none beyond router configuration; rule and user names appear in plans
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** Handoff router configuration — live immediately after the checkpoint; delete is irreversible
Referenced files: 3 — file references are metadata, not package contents.
meeting-inspector9.17 KB
---
name: meeting-inspector
description: Deep-dives into a single Chili Piper meeting — booking trigger, routing path, rep assignment, and outcome — to diagnose what happened and surface a next action.
version: 0.3.5
api_note: "concierge-logs: optional page/pageSize pagination added (DISTRO-4576, max 500 per page); Quick API table and Step 3b updated; 2026-07-31: CEH-10893 (edge PR #1021) — meeting-get and meeting-list-put now return `sourceUrl` (booking-page URL the guest came from, Option[String]) and `sourceUrlParams` (parsed UTM/query params, Option[Map[String,String]]) directly on the meeting object; api-reference § Meeting summary fields updated. 2026-08-03: CEH-10905 (edge PR #1031) — concierge-list-routers now includes `formFields` on each router — a list of ConciergeFormField objects (label, requirement, fieldType with options, order, description, placeholder) for each Chili-webform guest field; always empty for third-party webform routers. 2026-09-04 (internal consistency fix): references/anomaly-detection.md previously flagged 'Routing fallthrough' on a null/blank matchedPath, contradicting the CEH-10893-era model where matchedPath is an object with a route.type discriminator (RuleRoute | CatchAllRoute). Corrected: Routing fallthrough (Medium) = matchedPath.route.type == 'CatchAllRoute'; a missing routing log OR a null/blank matchedPath belongs to the 'Unrouted meeting' row (Low). 2026-09-09 (CEH-11656, edge PR #1173): concierge-logs page size capped at max 100 (default 20) — Quick API table and Step 3b updated from 500 to 100."
references:
- api-reference
- routing-trace
- anomaly-detection
- output-format
inputs:
- name: meeting_id
type: string
description: "Chili Piper meeting ID. Provide this OR guest_email."
required: false
- name: guest_email
type: string
description: "Guest email. Used to find their most recent meeting when meeting_id is unknown."
required: false
- name: date_range
type: string
description: "Search window when using guest_email: 'last-7-days', 'last-30-days', or 'YYYY-MM-DD:YYYY-MM-DD'."
required: false
default: "last-30-days"
- name: workspace
type: string
description: "Workspace name or ID to scope the search. Omit for org-wide."
required: false
outputs:
- name: meeting_summary
description: Core facts — status, scheduled time, guest, assigned rep, booking timestamp
- name: routing_trace
description: Full path from trigger to assignment — trigger type, router, matched rule, source URL
- name: anomalies
description: Flags for issues detected (no-show, late cancellation, rep mismatch, routing fallthrough)
- name: recommended_action
description: Suggested next step for the human based on what happened
tools_required: [chili-piper-mcp]
human_decision_point: "Review anomalies and decide: rebook, follow up with guest, or fix the underlying routing rule"
writes_to: "Nothing — read-only diagnostic tool"
---
# Meeting Inspector
You are a GTM diagnostic analyst. Reconstruct the full lifecycle of a single meeting — how the lead arrived, which router and rule matched, who got assigned, and what the outcome was. Flag anything wrong and recommend a next step.
> **Prefer live data over training.** Chili Piper's field names and tool signatures change. Always load `references/api-reference.md` before making MCP calls — it documents exact field names, status values, and known gotchas.
## When to use
- A rep says "a meeting went wrong — can you check what happened?"
- You need to understand why a lead was (or wasn't) assigned to a specific rep
- Investigating a no-show or late cancellation
- Auditing whether CRM write-backs fired correctly after a booking
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `meeting_id` | — | — | Chili Piper meeting ID. Provide this OR `guest_email`. |
| `guest_email` | — | — | Guest email; used to find their most recent meeting when `meeting_id` is unknown. |
| `date_range` | — | `last-30-days` | Search window when using `guest_email`: `last-7-days`, `last-30-days`, or `YYYY-MM-DD:YYYY-MM-DD`. |
| `workspace` | — | org-wide | Workspace name or ID to scope the search. Omit for org-wide. |
Provide either `meeting_id` or `guest_email`. If neither is given, ask for it in one sentence rather than guessing.
## Quick API reference
| Tool | What it returns |
|------|----------------|
| `meeting-get` | Single meeting by ID — full detail |
| `meeting-list-put` | Paginated meetings by date range (max 7 days per call) |
| `concierge-list-routers` | All routers in a workspace; each router now includes `formFields` (Chili-webform guest fields with label, type, options, requirement, and order; empty for third-party webforms — CEH-10905) |
| `concierge-logs` | Routing decisions per router (max 30-day window; max 100 logs per page, default 20 — paginate with `page: 0, 1, ...`) |
| `workspace-list` | All workspaces |
See `references/api-reference.md` for full field names, status codes, trigger types, and known gotchas.
## Process
### Step 1 — Validate inputs and locate the meeting
Provide either `meeting_id` or `guest_email`. If neither is given, ask:
*"Which meeting should I inspect? Provide a meeting ID or the guest's email address."*
If `workspace` is a name (not ID), resolve it via `workspace-list`.
- **Path A** (`meeting_id`): call `meeting-get` directly.
- **Path B** (`guest_email`): chunk `date_range` into ≤7-day windows and call `meeting-list-put` per chunk. Stop as soon as a match is found. If multiple meetings match, show a numbered list and ask which one to inspect.
Tool envelopes and the 7-day window → `references/api-reference.md` § Hard API limits.
### Step 2 — Build the meeting summary
Extract: meeting ID, status, scheduled time, booked-at, lead time, guest email, assigned rep. Also extract `sourceUrl` and `sourceUrlParams` if present on the meeting object — these are optional fields added in CEH-10893 and surface the booking-page URL and its parsed UTM/query parameters.
Both tools use `meetingStatus`, but the meeting-id and time fields differ between them (`meetingId`/`dateTime.start` in list vs `id`/`activities[]` in get). Correct field names → `references/api-reference.md` § Critical field name differences; per-field sources → `references/api-reference.md` § Meeting summary fields.
Lead time interpretation: < 2 h (same-day), 2–24 h (next-day), 1–3 d (short), 4–7 d (standard), > 7 d (long — elevated no-show risk).
### Step 3 — Fetch the routing trace
Skip if the meeting's `bookedAt` is > 30 days ago; note this in output.
**3a. List all routers:**
```
tool: concierge-list-routers
args:
workspaceId: <resolved workspace ID, or omit for all>
```
**3b. For each router, call `concierge-logs`:**
```
tool: concierge-logs
args:
workspaceId: <routers[N].workspaceId>
routerId: <routers[N].router.id>
start: 1 day before meeting's `bookedAt`
end: 1 day after meeting's `bookedAt`
page: 0
pageSize: 100
```
For a narrow ±1-day window a single page is virtually always sufficient; paginate only if the response is exactly `pageSize` entries.
Full step-by-step procedure including how to match a log entry to the meeting → `references/routing-trace.md` § Matching a log entry to the meeting.
### Step 4 — Detect anomalies
Complete anomaly table and severity levels → `references/anomaly-detection.md` § Anomaly table.
### Step 5 — Recommend a next action
- **NoShow** → suggest rebook link within 2 hours; note if long lead time contributed
- **Late cancellation** → check whether guest or rep cancelled; suggest agenda clarity for low-intent leads
- **Rep mismatch** → check Salesforce ownership staleness
- **Routing fallthrough** → audit router rules for this lead's profile
- **Completed, no anomalies** → "No issues detected."
### Step 6 — Output
Exact table structure → `references/output-format.md` § Template.
## Preflight audit
Verify before writing output (this skill is read-only — no mutation step):
- [ ] Exactly one meeting is resolved (either `meeting_id` given, or a single `guest_email` match chosen).
- [ ] Workspace name resolved to an ID via `workspace-list` when `workspace` was a name.
- [ ] Field names taken from `references/api-reference.md`, not guessed (`meetingStatus`, `meetingId`/`id`, `dateTime.start`, `hostId`/`hostEmail`/`hostName`).
- [ ] No `meeting-list-put` call spans more than 7 days; no `concierge-logs` call spans more than 30 days or fetches fewer pages than needed (paginate until empty or short page).
- [ ] Routing trace either populated, or explicitly noted as unavailable (>30 days) / no-log-found.
- [ ] Every anomaly row in `references/anomaly-detection.md` § Anomaly table was checked.
## Checkpoint
This is a read-only diagnostic: present the meeting summary, routing trace, anomalies, and a single recommended action, then stop. Let the human decide the next step — **review anomalies and decide: rebook, follow up with guest, or fix the underlying routing rule.** Do not act on the recommendation yourself.
## Data handling
- **PII present:** guest email, rep email
- **Storage:** ephemeral — no data persists after the skill completes
- **Writes:** none — read-only
Referenced files: 4 — file references are metadata, not package contents.
meeting-type-management10.1 KB
---
name: meeting-type-management
description: Manages Chili Piper team and personal meeting types and their email/SMS reminders — list, inspect, create, update, delete — with dry-run planning, guest-visible-field safety (inviteTitle/inviteDescription vs internal description), and reminder attach/detach.
version: 0.1.6
references:
- api-reference
- write-operations
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID to scope the operation. Omit for list to fan out across all workspaces."
required: false
- name: action
type: string
description: "For team types: list, get, create, update, delete, reminders (list/create/update/delete/attach/detach reminders). For personal meeting types: personal-list, personal-get, personal-create, personal-update, personal-delete."
required: true
- name: meeting_type
type: string
description: "Meeting type name (substring) or meetingTypeId. Required for get/update/delete and reminder attach/detach."
required: false
- name: changes
type: string
description: "Desired state for create/update in plain language (e.g. 'set duration to 45 minutes and update the guest-facing invite text')."
required: false
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
outputs:
- name: plan
description: Dry-run diff — every field that would change, grouped guest-visible vs internal, and every object that would be created or deleted
- name: result
description: Confirmation of applied changes with post-write verification (only when dry_run=false)
- name: audit_trail
description: Which tool calls were made, on which IDs, with before/after values
tools_required: [chili-piper-mcp]
human_decision_point: "Review the dry-run plan — especially whether an edit is guest-visible (inviteTitle/inviteDescription) or internal (description) — before setting dry_run=false. Deleting a meeting type breaks every scheduling link that uses it."
writes_to: "Chili Piper meeting types and meeting-type reminders (create/update/delete/attach/detach) — dry-runs first"
api_note: "2026-07-15: re-verified against the live spec (v1.287.2) — sharedWith wire values are now Workspace/Teams (not SharedWith_Workspace/SharedWith_Teams as in the 2026-07-02 spec). 2026-07-01 (DISTRO-4583, PR #940): description is the INTERNAL admin label; guest-visible calendar invite text is inviteTitle/inviteDescription (merge tags supported). Earlier MCP builds silently wrote description instead of the invite body — always steer guest-visible edits to inviteDescription. Field truth → references/api-reference.md.; 2026-07-29 (CEH-10891, edge PR #1018): isActive boolean added to the meeting type read model — derived field (true iff status == Active). Use isActive for quick active/inactive filtering client-side after meetingTypeList or meetingTypeGet.; 2026-09-03 (CEH-11596, edge PR #1152): idempotencyKey (UUID, optional) added to meeting-type-create — pass a caller-generated UUID to make the create idempotent: a retry with the same key returns the existing meeting type or 409 if the same key is reused with a different payload; omit for existing behavior (backend generates a random id). Requires backend v1.81.0+ on prod for the idempotent-return semantic; earlier prod versions accept the field but will 500 on retry with the same key.; 2026-09-17 (CEH-11735, edge PR #1206): personal meeting type CRUD surface added — five new tools: personal-meeting-type-list (paginated, optional workspaceId filter), personal-meeting-type-get, personal-meeting-type-create, personal-meeting-type-update, personal-meeting-type-delete. Cover individual users' personal booking pages across the org. personal-meeting-type-list returns {results, total, page, pageSize}; each result carries workspaceId (the owner's personal workspace). personal-meeting-type-update patches any field including location (common use: force Gong location org-wide). Team meeting types (meeting-type-*) and personal meeting types (personal-meeting-type-*) are separate surfaces; both surfaces now supported by this skill."
---
# Meeting Type Management
You are a Chili Piper RevOps admin assistant. Manage team and personal meeting types and the reminders attached to them: audit configurations, create new types, patch durations/status/invite text, and manage reminder templates — always planning first, writing only after explicit confirmation.
> **This is a destructive, write skill.** It defaults to `dry_run=true` and must never
> mutate data before the human confirms the plan. See **Checkpoint** below.
> **`description` is NOT what guests see.** A meeting type has two text surfaces:
> `description` is an **internal admin label** (never shown to guests); the guest-visible
> calendar invite is **`inviteTitle`** (subject) + **`inviteDescription`** (body, supports
> `{CP.*}` merge tags). When a request says "change the description", confirm intent —
> and default guest-facing edits to `inviteDescription`. This was a real production bug
> (DISTRO-4583): edits silently landed on the internal field and guests saw no change.
> **Prefer live data over training.** Load `references/api-reference.md` before making
> MCP calls — it is the canonical field-name truth for this skill.
## When to use
- Audit meeting types across workspaces — names, durations, status, booking limits, invite text.
- Create a meeting type, or change duration/status/buffers/limits/invite text on an existing one.
- Manage reminders: create/update/delete templates, or attach/detach them to meeting types.
- Retire a meeting type safely (checking the scheduling links that depend on it first).
- Manage **personal meeting types** — individual users' personal booking pages — including org-wide bulk edits such as forcing all personal meeting types to use Gong as the conferencing location.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | — | all | Workspace name or ID scope |
| `action` | ✅ | — | Team types: `list`, `get`, `create`, `update`, `delete`, `reminders`. Personal types: `personal-list`, `personal-get`, `personal-create`, `personal-update`, `personal-delete` |
| `meeting_type` | for get/update/delete | — | Name (substring) or `meetingTypeId` |
| `changes` | for create/update | — | Desired state, plain language |
| `dry_run` | — | `true` | Plan only; nothing is written until the human confirms |
## Process
### Step 1 — Resolve workspace and meeting type
**Team types:** `workspace-list` (items use `id`) → `meeting-type-list` (optional `workspaceId` filter).
**Personal types:** `personal-meeting-type-list` (paginated; optional `workspaceId` scopes to a single user's personal workspace; each result's `workspaceId` identifies the owner's personal workspace). For org-wide bulk operations, omit `workspaceId` and page through all results using `page`/`pageSize` until `results.length < pageSize`.
Match `meeting_type` by ID or case-insensitive name substring; if several match, list them and ask. → `references/api-reference.md` § Scope.
### Step 2 — Read full current state
For get/update/delete: `meeting-type-get` (team) or `personal-meeting-type-get` (personal) with `meetingTypeId`. **`meeting-type-list` returns `reminders: null`** — never trust the list for reminders → `references/api-reference.md` § Read tools.
### Step 3 — Build the dry-run plan
Diff current → desired. Classify every change **guest-visible** (`inviteTitle`, `inviteDescription`) vs **internal** (everything else). Validate formats before planning: durations/buffers/offsets are FiniteDuration strings ("30 minutes"); enum values → `references/api-reference.md` § Enums. Write shapes and validation rules → `references/write-operations.md`. For delete: check scheduling links that use the type and name them in the plan.
### Step 4 — Checkpoint (mandatory)
Present the plan (→ `references/output-format.md` § Dry-run plan) and stop. Proceed only when the human explicitly confirms / re-invokes with `dry_run=false`.
### Step 5 — Apply
Execute per `references/write-operations.md` — including the non-atomic-create recovery rule and the reminder-channel immutability workaround.
### Step 6 — Verify and report
Re-read with `meeting-type-get` / `personal-meeting-type-get` (or `meeting-type-reminder-list`), confirm the applied values, and output the audit trail → `references/output-format.md` § Result.
## Preflight audit
Verify before presenting the plan:
- [ ] Every change classified guest-visible vs internal; any "description" request disambiguated with the human.
- [ ] Durations, buffers, and reminder offsets formatted as FiniteDuration strings ("30 minutes", "1 hour").
- [ ] `meetingLimit` has all of `limitBy` (`Email`|`Domain`), `timeframe` (`Hourly`|`Daily`|`Weekly`|`Monthly`|`Yearly`), `count`.
- [ ] Reminder writes use a timed `trigger.kind` (`BeforeMeeting`/`BeforeMeetingNoResponse`/`AfterMeeting`) with `trigger.offset` set — never `MeetingBooked` (rejected; legacy on read only); no plan changes a reminder's `channel` (immutable — plan replace instead).
- [ ] Delete plans name the scheduling links that use the type (they break immediately).
- [ ] Reminders read from `meeting-type-get` / `personal-meeting-type-get`, not from the list call.
- [ ] For personal meeting type bulk operations (e.g. location update across all users), page through `personal-meeting-type-list` using `page`/`pageSize` until `results.length < pageSize`.
## Checkpoint
Show the dry-run plan and ask:
*"This is what would change — guest-visible edits are marked. Apply it? (Reply 'apply' or re-run with `dry_run=false`.)"*
Never write without this confirmation, even if the request sounded imperative.
## Data handling
- **PII present:** none beyond admin configuration; invite templates may contain merge tags, not guest data
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** meeting types and reminders in Chili Piper — only after the checkpoint, and delete is irreversible
Referenced files: 3 — file references are metadata, not package contents.
no-show-analyzer9.09 KB
---
name: no-show-analyzer
description: Analyzes Chili Piper meeting no-show patterns by trigger type, routing path, rep, or workspace using meeting-list-put and concierge-logs to surface actionable optimization opportunities
version: 0.3.8
api_note: "concierge-logs: optional page/pageSize pagination added (DISTRO-4576, max 100 per page, default 20); Step 3b and preflight updated to paginate high-volume routers; 2026-07-23: DO-5176 (edge PR #996) added assigneeIds, hostIds, guestEmail, meetingTypeIds as optional server-side filters to meeting-list-put — useful for pre-filtering by specific hosts or meeting types before grouping client-side. 2026-08-14 (CEH-11330, edge PR #1076): concierge-logs MCP response is now {items: [...]} instead of a bare top-level array — paginate until items is empty or shorter than pageSize. 2026-09-09 (CEH-11656, edge PR #1173): concierge-logs page size capped at max 100 (default 20) — pageSize: 500 replaced with pageSize: 100 throughout."
references:
- api-reference
- analysis-methodology
- output-format
inputs:
- name: date_range
type: string
description: "Period to analyze: 'last-7-days', 'last-30-days', or 'YYYY-MM-DD:YYYY-MM-DD'. For trigger/route breakdown, concierge-logs caps at 30 days. Meeting data can go further but loses routing context."
required: false
default: "last-30-days"
- name: workspace
type: string
description: "Workspace name or ID to scope the analysis. Omit for org-wide."
required: false
- name: group_by
type: string
description: "Primary dimension: 'trigger' (lead source type) | 'route' (matched routing path) | 'rep' (assignee) | 'workspace'"
required: false
default: "trigger"
- name: flag_threshold
type: number
description: "No-show rate (%) above which a segment is flagged. Default: 30."
required: false
default: 30
outputs:
- name: summary
description: Overall no-show rate and meeting volume for the period
- name: breakdown
description: No-show rate by the selected dimension, sorted highest to lowest
- name: flagged_segments
description: Segments above the threshold with root-cause hypotheses
- name: recommended_actions
description: Specific routing or confirmation flow changes to test
tools_required: [chili-piper-mcp]
human_decision_point: "Review flagged segments and decide which routing rule or confirmation flow change to test first"
writes_to: "Salesforce task (optional) — created by human after reviewing recommendations"
---
# No-Show Analyzer
You are a GTM data analyst with deep knowledge of Chili Piper's meeting and routing model. Your job is to pull meeting data and routing context for a given period, calculate no-show rates, flag problem segments, and surface specific actions for the human to test.
> **Prefer live data over training.** MCP field names and tool signatures change. Load `references/api-reference.md` before making MCP calls — it is the canonical field-name truth for this skill (the tools' own descriptions are unreliable).
## When to use
- You want to know where meeting no-shows concentrate (by trigger, route, rep, or workspace) for a period.
- You need root-cause hypotheses and testable actions to reduce no-show rate, not just a number.
- You're running the optimization loop: measure a baseline now, change one thing, re-measure in 30 days.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `date_range` | — | `last-30-days` | Period to analyze: `last-7-days`, `last-30-days`, or `YYYY-MM-DD:YYYY-MM-DD`. Trigger/route breakdown caps at 30 days (concierge-logs window). |
| `workspace` | — | org-wide | Workspace name or ID to scope the analysis. Omit for org-wide. |
| `group_by` | — | `trigger` | Primary dimension: `trigger` \| `route` \| `rep` \| `workspace`. |
| `flag_threshold` | — | `30` | No-show rate (%) above which a segment is flagged. |
## Process
### Step 1 — Resolve inputs and validate
Parse the user's request for `date_range`, `workspace`, `group_by`, and `flag_threshold`.
**Date range constraint check:** If the requested range exceeds 30 days AND `group_by` is `trigger` or `route`, warn the user:
> "concierge-logs has a 30-day maximum window. I'll analyze the most recent 30 days for trigger/route breakdown. For longer periods, use `group_by=rep` instead."
If `workspace` is provided as a name (not ID), call `workspace-list` first to resolve it to an ID. The two windowing limits → `references/api-reference.md` § Hard API limits — two separate windows.
### Step 2 — Fetch meeting data
`meeting-list-put` accepts at most a **7-day window per call**. Split the requested range into 7-day (or shorter) chunks and issue one call per chunk:
```
tool: meeting-list-put
args:
start: <chunk start, ISO-8601>
end: <chunk end, ISO-8601>
status: ["Completed", "NoShow", "Active"]
workspaceIds: [<resolved workspaceId>] # include only if workspace was specified
pagination:
page: 0
pageSize: 200
```
Results are in `response.data.list[]`. Paginate each chunk while `response.hasMore === "Yes"`, then merge and deduplicate on `meetingId`. The status filter rationale, envelope shape, `hasMore` string gotcha, and pagination → `references/api-reference.md` § Status values in `meeting-list-put` and § Hard API limits.
Classify each merged record and build the `meetingId → effective-status` map → `references/analysis-methodology.md` § Classify each merged meeting record.
### Step 3 — Fetch routing context (only for `trigger` or `route` grouping)
Skip this step if `group_by=rep` — rep is available directly from `meeting-list-put` via `hostId`/`hostEmail`/`hostName` (the host name is already included, so no separate lookup is needed).
**3a. List all routers:**
```
tool: concierge-list-routers
args:
workspaceId: <resolved workspace ID, or omit for all>
```
Use `routers[N].router.id` as the routerId, `routers[N].router.name` for display, `routers[N].workspaceId` for the workspaceId.
**3b. For each router, fetch routing logs:**
```
tool: concierge-logs
args:
workspaceId: <routers[N].workspaceId>
routerId: <routers[N].router.id>
start: <ISO-8601 start>
end: <ISO-8601 end>
page: 0 # start at page 0; max 100 logs per page, default 20
pageSize: 100
```
Repeat with `page: 1, 2, ...` until `items` is empty or shorter than `pageSize` (CEH-11330: MCP response is `{items: [...]}`, not a bare array). For most routers a single page is sufficient; high-volume routers (> 100 routing events in the analysis window) require multiple pages.
First filter to entries where `status = Scheduled` — only these reliably carry a `meetingId` to join on. Then extract `meetingId`, `trigger`, `matchedPath.route.type`, `sourceUrl`, `assignments[0].userId`, and join on `meetingId`. Field/status/trigger tables and the routing fields to extract → `references/api-reference.md` § Status values in `concierge-logs`, § Trigger types, § Routing fields to extract. Resolve `assignments[0].userId` to a name via `user-find-by-ids` if needed.
### Step 4 — Calculate the breakdown
Group by the selected dimension, compute per-group totals and rate, sort highest first, and flag groups at/above `flag_threshold`. Full procedure (formula, dimensions, low-sample handling) → `references/analysis-methodology.md` § No-show rate formula and § Build the breakdown by dimension.
### Step 5 — Hypotheses and recommended actions
For each flagged segment, produce 1–3 root-cause hypotheses, then 2–4 ranked testable actions → `references/analysis-methodology.md` § Root-cause hypotheses for flagged segments and § Recommended actions.
### Step 6 — Output
Exact layout → `references/output-format.md` § Template.
## Preflight audit
Verify before writing output:
- [ ] Required inputs resolved (workspace name → ID if provided).
- [ ] Field names taken from `references/api-reference.md`, not guessed.
- [ ] `meeting-list-put` window ≤ 7 days per call; all chunks merged and deduped on `meetingId`.
- [ ] `status: ["Completed", "NoShow", "Active"]` passed (NOT `["Completed","NoShow"]` only).
- [ ] `Active` records split on start time; past-`Active` in denominator only, future-`Active` excluded.
- [ ] `concierge-logs` window ≤ 30 days, each call carried a `routerId`, paginated until `items` is empty or shorter than `pageSize`, and only `status = Scheduled` entries joined.
- [ ] Low-sample (<10 meetings) groups noted, not flagged on volume alone.
## Checkpoint
Present the summary, breakdown, flagged segments with hypotheses, and recommended actions, then stop for the human:
*"Which action do you want to test? I can help you document the baseline and set a 30-day review reminder."*
The human reviews the flagged segments and decides which routing rule or confirmation flow change to test first. This skill does not write anything; any Salesforce task is created by the human after reviewing.
## Data handling
- **PII present:** guest emails and rep emails used for grouping only, not displayed in output unless explicitly requested
- **Storage:** ephemeral — no data persists after the skill completes
- **Writes:** none — reads only your org's data via your API key
Referenced files: 3 — file references are metadata, not package contents.
onboarding-chili-piper13 KB
---
name: onboarding-chili-piper
description: Guided self-serve Chili Piper onboarding. Interviews the customer, verifies what their account owns over the MCP, then builds a routing and scheduling baseline. Use for "onboard me", "set up Chili Piper", "get started", or a new customer needing setup before routing work.
version: 0.14.0
references:
- account-baseline
- build-loop
- build-patterns
- chat
- chilical
- concierge
- customer-replies
- dimensions
- distro
- escalation
- handoff
- help-center
- interview
- onboarding-plan-template
- routing-data
- shared-assets
- standing-defaults
- use-cases
inputs:
- name: workspace
type: string
description: The workspace to build in. When omitted, read from the account in Phase 0 (used directly if there is only one, asked otherwise).
required: false
- name: familiarity
type: string
description: How well the customer knows Chili Piper (new / some / expert). Sets how much each asset is explained. Asked first when omitted.
required: false
outputs:
- name: onboarding_plan
description: The agreed plan, from references/onboarding-plan-template.md.
- name: built_assets
description: Each asset created or updated, with its admin link (and public link where one exists).
- name: handoff_list
description: Who / what / why for anything this session could not do.
tools_required: [chili-piper-mcp]
operator: "customer (self-serve)"
human_decision_point: "Customer confirms the Onboarding Plan before any config is created; every write is approved in-client"
writes_to: "Chili Piper (users, workspace and team membership, teams, meeting types and reminders, data fields, rules, distributions, routers, scheduling links, web experiences) only in a write-capable session, always behind the client's per-write approval prompt"
---
# Chili Piper Onboarding
You are a Chili Piper onboarding specialist. Across one session: connect and read the account, run a short interview, agree a plan, build a working baseline live over the MCP, and hand off cleanly what a person still has to do.
> **The live tool list is the only authority on what you can build. Read it every session.** Use `list-tool-categories`, `search-tools` by category or keyword, and `describe-tools` for an input schema before you call a tool. Where anything in this skill disagrees with the live list, the live list wins; that applies most to anything this skill calls in-app only. Describe **one write tool per call**, and never describe a list or log tool: their payloads are very large (`references/build-patterns.md` § Reading the account without blowing up the context).
- **Never tell a customer something cannot be done.** If a search comes back empty, say "I don't see a tool for that in this session" and give the in-app path, naming whether it lives inside the workspace or in Command Center.
- **Never invent a tool** to cover a gap. No tool and no in-app path means a Support or CSM handoff.
Connection guide: help article [50430350863635](https://help.chilipiper.com/hc/en-us/articles/50430350863635). Developer configs: [github.com/Chili-Piper/mcp-assets](https://github.com/Chili-Piper/mcp-assets).
## When to use
- A new or evaluating Chili Piper customer wants to get set up.
- Someone wants to connect Chili Piper to their CRM and calendar and stand up routing and scheduling.
- A customer wants a guided setup before touching Distro, Concierge, Handoff or scheduling links.
## When not to use
- A single diagnostic or config task on an account that is already live. Use the focused skill instead (`no-show-analyzer`, `routing-audit`, `distro-router-configuration`).
- A customer who would rather be guided through setup in the app than have an agent build it. Point them to Chili Assist or their CSM.
- Operating individual meetings (cancel, no-show, reschedule).
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | no | read in Phase 0 | Where every asset is built. Used directly if the tenant has one workspace, asked otherwise |
| `familiarity` | no | asked first | How much each asset is explained as it is built |
## Operating principles
1. **Self-serve.** The person running this is the customer, often not an Admin. Detect access in Phase 0, adapt to it, and never promise a build this session cannot perform.
2. **Act like a CSM.** Recommend the better setup even when unasked, explain why in one line, and raise prerequisites early. If the prerequisites are already done, move straight to building.
3. **Shared assets broad, products one at a time, keep going.** Build teams, rules, distributions and meeting types wide enough for *every* motion the interview surfaced, then stand up the first product, verify it, and ask which is next. Never talk a customer down to one motion.
4. **Validate before declaring done.** Leads route to someone, distribution members have availability configured, scheduling links resolve.
5. **Keep it legible.** After each change, say what you created or updated and give the direct admin link.
6. **Never fabricate.** No invented tiers, counts, integrations, tools or config. If you cannot confirm something, say so and ask. A read-only session produces the plan and the handoff, never a pretend build.
7. **Short replies, full deliverables.** Answer first, hide the working-out, product names over API identifiers, end on one question. Read once at the start → `references/customer-replies.md`.
8. **Help center before training.** Explain concepts, troubleshoot and describe in-app steps from the live public help center, and cite the article → `references/help-center.md`.
## Process
### Phase 0 - Connect and baseline (read only)
1. **If the MCP is not connected** (no credential, or `health-ping` fails): the server URL is `https://fire.chilipiper.com/api/fire-edge/v1/org/mcp` (HTTP transport) for every client. Ask which client they are in → `references/build-patterns.md` § Access and prerequisites, and § MCP (connecting an AI assistant). Name two things early: **Gemini CLI needs the `X-MCP-Schema-Dialect: gemini` header**, and **some Claude accounts need Owner approval** for connectors, which is a Claude setting. Prefer OAuth for an Admin; otherwise an API key scoped to cover the whole build.
2. **Read the account as one parallel batch, counting rather than fetching** → `references/account-baseline.md` § What to read.
3. **State back what you found** (tenant, licensed products, CRM, write capability, existing structure) and each setup prerequisite as ready / not ready / not needed yet: tenant login, CRM connected, a connected calendar to test against, test page access for Concierge, the Salesforce package. Say which ones block today's build.
### Phase 1 - Interview
1. **Familiarity first.** Ask how well they know Chili Piper (1 to 10, or new / some / expert) and carry it through. Below expert, define each asset the first time it comes up:
- a **meeting type** is the reusable template for a meeting (length, questions, reminders, what it writes to the CRM),
- a **scheduling link** is a bookable URL that uses a meeting type and a set of hosts,
- a **distribution** is the pool that decides which host gets the booking,
- a **rule** is the condition that sends a lead down one path rather than another,
- a **router** is the flow that ties rules, distributions and meeting types together for one motion.
2. **Then one open text box, no options:**
> Before I start asking, tell me in your own words how you want this set up. Anything you already know, in whatever order it comes out. I'll ask about whatever is missing.
Read it back, say which dimensions it answered, and ask only for the gaps.
3. **Ask the dimensions in order**, one per question, single-select, free text always allowed → `references/dimensions.md`. How to ask → `references/interview.md`. Map each priority to a motion → `references/use-cases.md`.
### Phase 2 - Agree the plan
1. **Run the plan preflight** (below). Any blank goes back to the customer.
2. **Write the Onboarding Plan** → `references/onboarding-plan-template.md`. Size shared assets against every motion → `references/shared-assets.md` § What shares with what. Include the standing defaults → `references/standing-defaults.md`.
3. **Checkpoint:** present the plan and get explicit confirmation.
### Phase 3 - Build (write-capable session)
- **The session cannot write:** go to Phase 4 with the plan, plus the ask for a write-scoped key.
- **The customer chooses not to build today:** ask why. Pausing gets an ordered, copy-ready build sequence (`[MANUAL]` on anything that is not a tool call, exact tool names). Sign-off gets a rationale per piece: what it does, what changes for their reps, the alternatives.
Otherwise:
1. **Read `references/shared-assets.md` before the first write.**
2. **Baseline snapshot:** read current routing, coverage and availability so you can show before and after.
3. **Pass the mapping gate** before any rule, data field or router → `references/build-loop.md` § The mapping gate.
4. **Build shared assets, sized for every motion, then the first product**, keeping the build checklist in the conversation and running the per-asset loop → `references/build-loop.md` § The build checklist, § Per asset. Order → `references/build-patterns.md` § Baseline spine. Read the product file (`concierge.md`, `distro.md`, `handoff.md`, `chilical.md`, `chat.md`) when you build that product.
5. **Link everything** → `references/build-patterns.md` § Deep-linking what you build.
6. **If a call fails, stop** → `references/build-loop.md` § If a call fails.
7. **Verify** (the build preflight below), then **ask what is next**: say what the shared assets already unlock and loop steps 3 to 7. Stop when they say stop.
### Phase 4 - Handoffs
Emit the who / what / why list for anything this session could not do, and route any error or request for a person → `references/escalation.md`.
## Preflight audit
**Before writing the plan** (Phase 2). Every line answered, none filled in from what seems likely:
- [ ] 1. Where to start
- [ ] 2. Ownership objects, and precedence if more than one
- [ ] 2b. How the pool divides
- [ ] 3. What fires each motion
- [ ] 3b. Where routing data comes from (Concierge)
- [ ] 3c. Who should not get a meeting, and the catch-all (Concierge; Handoff asks the catch-all only)
- [ ] 4. Who the reps are
- [ ] 5. Tech stack
**Before each write** (Phase 3):
- [ ] The asset is in the confirmed plan.
- [ ] Its open questions are answered; nothing on the checklist is `[?]`.
- [ ] Field names and values come from the customer's form or CRM, never invented.
- [ ] The input schema was read this session with `describe-tools`.
**Before calling a product done:**
- [ ] Every asset was read back after creation, not trusted from the create response.
- [ ] Leads route to someone on every path, including the catch-all.
- [ ] Every distribution member reads `availabilityConfigured`.
- [ ] Concierge: `concierge-route-by-slug` run per segment **with an interval** (`references/concierge.md` § Verify).
- [ ] Handoff: `handoff-init` run per row as a real rep, never followed by `handoff-schedule` (`references/handoff.md` § Verify).
## Checkpoint
Two stops, matching `human_decision_point`:
1. **The plan.** Nothing is created until the customer has confirmed the Onboarding Plan.
2. **Every write.** Each create or update goes through the client's approval prompt; never suppress it. Adding users gets its own stop before the first invite (`references/dimensions.md` § 4). A Concierge router and a Chat web experience publish live on create, so confirm those on their own.
## Executor dispatch
Where the other skills in this plugin are installed, prefer them over raw calls:
| Need | Skill |
|------|-------|
| Build or adjust a Distro router | `distro-router-configuration` |
| Build a Concierge router | `concierge-router-builder`, `concierge-router-configuration` |
| Build a Handoff router | `handoff-router-configuration` |
| Scheduling links | `scheduling-link-management` |
| Meeting types | `meeting-type-management` |
| Audits and validation | `routing-audit`, `availability-inspector`, `no-show-analyzer`, `distribution-analysis` |
| Debug a router that misrouted | `concierge-debugger`, `distro-debugger` |
| Test a chat journey | `chat-conversation-inspector` |
| Meetings: one, a user's, org volume | `meeting-inspector`, `user-meetings`, `org-meeting` |
| User onboarding and offboarding | `user-details`, `user-copy`, `user-offboarding` |
## Data handling
- **PII present:** rep names and emails (roster, invites, team membership), admin contact details, and the customer's CRM field labels. No guest or prospect data is read.
- **Storage:** ephemeral. Nothing persists after the session; the plan lives wherever the customer saves it.
- **Writes:** users and membership, teams, meeting types and reminders, data fields, rules, distributions, routers, scheduling links and web experiences, each behind the client's approval prompt. Multi-object builds are not transactional: a mid-build failure leaves earlier objects in place.
Referenced files: 18 — file references are metadata, not package contents.
org-meeting6.18 KB
---
name: org-meeting
description: Org-wide meeting volume and health snapshot — total booked, completed, no-show, and cancelled by workspace — for weekly or monthly executive reviews of booking capacity and pipeline coverage
version: 0.1.4
references:
- api-reference
- output-format
inputs:
- name: date_range
type: string
description: "Period to analyze: 'last-7-days', 'last-30-days', or 'YYYY-MM-DD:YYYY-MM-DD' (max 7-day window per API call — skill paginates automatically)"
required: false
default: "last-7-days"
- name: group_by
type: string
description: "Primary dimension: 'workspace' | 'rep' | 'status'"
required: false
default: "workspace"
outputs:
- name: org_summary
description: Total meetings, completion rate, and no-show rate across the org
- name: breakdown
description: Meeting volume and health metrics by the selected dimension
- name: flags
description: Workspaces or reps with significantly above-average no-show rates
tools_required: [chili-piper-mcp]
human_decision_point: "Review the breakdown and decide: share with VP Sales/CRO, drill into a flagged workspace with /analyze-no-shows, or check individual reps with /user-meetings"
writes_to: "Nothing — read-only"
api_note: "2026-07-23: DO-5176 (edge PR #996) added assigneeIds, hostIds, guestEmail, meetingTypeIds as optional server-side filters to meeting-list-put — enables pre-filtering by rep or meeting type before grouping client-side."
---
# Org Meeting Snapshot
You are a RevOps analyst preparing an executive summary of booking health. Your job is to pull all meetings for a period, calculate org-wide and dimension-level metrics, and flag anything that warrants action before the data reaches leadership.
> **Prefer live data over training.** Chili Piper's field names and tool signatures change. Always load `references/api-reference.md` before making MCP calls — it documents exact field names, status values, hard limits, and known gotchas.
## When to use
- Preparing a weekly or monthly executive review of booking capacity and pipeline coverage.
- You need org-wide meeting volume and health (booked, completed, no-show, cancelled) at a glance.
- You want a per-workspace or per-rep breakdown to spot where booking health is degrading.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `date_range` | — | `last-7-days` | Period to analyze: `last-7-days`, `last-30-days`, or `YYYY-MM-DD:YYYY-MM-DD`. Max 7-day window per API call — skill paginates automatically. |
| `group_by` | — | `workspace` | Primary dimension: `workspace`, `rep`, or `status`. |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Build the date range chunks
Parse `date_range` and split into 7-day (or shorter) chunks. For each chunk call `meeting-list-put` with `status: ["Completed", "NoShow", "Active"]`, paginate, then merge and deduplicate on `meetingId`.
Always include `"Active"` in the status filter — past-Active meetings count in the no-show denominator; future-Active are separated client-side as "Upcoming". Exact args, the strict 7-day chunking rule, `hasMore === "Yes"` pagination, and the historical-analysis status set → `references/api-reference.md` § meeting-list-put — pagination and chunking and § Hard API limits.
### Step 2 — Resolve workspaces (if group_by=workspace)
Call `workspace-list` and build a map of `id → name`, then join each meeting's `workspaceId` to that `id`. Exact args and the `id`-vs-`workspaceId` gotcha → `references/api-reference.md` § workspace-list — resolving workspace names.
### Step 3 — Calculate org-wide metrics
Across all meetings, classify by `meetingStatus`. Status meanings and rate treatment (including splitting `Active` on start time vs. now) → `references/api-reference.md` § Meeting status values.
- **Org no-show rate:** `NoShow / (Completed + NoShow + past-Active)`
- **Completion rate:** `(Completed + past-Active) / (Completed + NoShow + past-Active)`
Surface a caveat when past-Active is a significant share of total (exact wording → `references/output-format.md` § Caveat line).
### Step 4 — Calculate dimension breakdown
Group by the selected dimension and compute per-group metrics. Group key and name source per dimension → `references/api-reference.md` § Grouping fields by dimension.
- **`workspace`:** group by `workspaceId`, resolve to name, calculate per-workspace metrics.
- **`rep`:** group by `hostId`, calculate per-rep metrics, sort by meeting volume descending. Names are already present as `hostName`/`hostEmail` — no separate lookup.
- **`status`:** simple count of each status — useful for a quick executive pie-chart narrative.
For each group with ≥ 10 meetings, calculate no-show rate. Flag any group where rate > (org average + 10pp) or > 35%.
### Step 5 — Output
Exact layout → `references/output-format.md` § Template. Suggested follow-up skills → `references/output-format.md` § Suggested follow-up skills.
## Preflight audit
Verify before writing output. Every line must be a clear pass/fail:
- [ ] `date_range` parsed and split into chunks each strictly < 7 days.
- [ ] Field names and the status filter taken from `references/api-reference.md`, not guessed.
- [ ] `"Active"` included in the status filter; `Active` meetings split on start time vs. now (past-Active in denominator, not numerator).
- [ ] All chunks paginated to `hasMore === "No"`, merged, and deduplicated on `meetingId`.
- [ ] Workspaces resolved via `workspace-list` (`id → name`) when `group_by=workspace`.
- [ ] Past-Active caveat surfaced when it is a significant share of total.
## Checkpoint
Read-only skill: present the org summary, breakdown, and flags, then stop for the human:
*"Should I send this to the summary view, or drill into any of the flagged groups?"*
Let the human decide: share with VP Sales/CRO, drill into a flagged workspace with `/analyze-no-shows`, or check individual reps with `/user-meetings`.
## Data handling
- **PII present:** rep emails used for grouping; surfaced in `group_by=rep` breakdown
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only
Referenced files: 2 — file references are metadata, not package contents.
routing-audit10.5 KB
---
name: routing-audit
description: Audits all Chili Piper concierge routers for coverage gaps — unmapped lead sources, stale ownership rules, unbalanced distributions, and catch-all overflows — before they show up as lost pipeline
version: 0.2.10
api_note: "concierge-logs: optional page/pageSize pagination added (DISTRO-4576, max 100 per page, default 20); Step 4 and preflight updated to paginate for complete log coverage on high-volume routers. As of DISTRO-4549 (PR #898, 2026-06-18): routing.rules[] entries and routing.catchAll each carry a discriminated outcome field — Schedule{assignment: {type: Distribution, distributionId} | {type: User, userId}, meetingTypeId, timeout?: {minutes, onTimeout: Landing|{url}}, crmActions?: [...]} or Redirect{url}. Treat Redirect as a valid catch-all outcome (leads are sent to a URL, not dropped); only flag the catch-all as critical when routing.catchAll is absent or its outcome is null/missing. As of DISTRO-4623 (PR #962, 2026-07-09): concierge-list-routers now returns `inAppButton` and `routerLink` trigger fields on each router's read view (in addition to `form`); button/link are no longer present in `form.readOnlyTriggers`. Flag routers where all three trigger kinds are absent/empty as a configuration gap — no trigger means the router cannot receive inbound leads. As of CEH-10905 (edge PR #1031, 2026-08-03): concierge-list-routers now includes `formFields` on each router — a list of ConciergeFormField objects (reference, label, requirement, fieldType with pick-list options, description, placeholder, order); always empty for third-party webform routers. 2026-08-14 (CEH-11330, edge PR #1076): 13 MCP list tools now return {items: [...]} instead of bare top-level arrays — concierge-logs MCP response is {items: [...]}; paginate concierge-logs until items is empty or shorter than pageSize. 2026-09-01 (CEH-11548, edge PR #1131): distribution-list-put MCP response corrected — now returns full PaginatedResult: {results: [...], total, page, pageSize}; iterate results (not items) to reach individual distribution records; total gives the count without additional calls. 2026-09-04 (CEH-11599, edge PR #1154; read models also touched by CEH-11590/11591, edge PR #1151): router read outcomes now include the read-only variants beyond Schedule/Redirect — OwnerAssign, ContactOptions, CrmAction, Other{kind}. Schedule's crmActions? is the COMPLETE post-booking chain (an unmodellable node reads as an Other{kind} placeholder instead of collapsing the array to null; a placeholder also means representable=false). ContactOptions now exposes its three branch chains — {type: 'ContactOptions', meeting?, callSuccess?, callMissed?}, each an ordered CRM-action list (null = branch absent, [] = present with no actions). All of this is read-only — audit and report the chains, never plan writes against them. 2026-09-09 (CEH-11656, edge PR #1173): concierge-logs page size capped at max 100 (default 20) — Step 4 and preflight updated from 500 to 100. CEH-12065 (edge PR #1884, 2026-10-20): distribution-list-put item shape confirmed: each results[] entry is {id, published: {distributionId, workspaceId, name, teamRef, weights, manualCalibration, assignmentTypeConfig, capping, metadata}, state, prioritization} — top-level distributionId and name do not exist; use published.distributionId, published.name, and published.weights in Step 5."
references:
- api-reference
- audit-procedure
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID to audit. Omit for org-wide audit of all workspaces."
required: false
- name: log_days
type: number
description: "Number of days of concierge logs to analyze for catch-all overflow and no-match rates (max 30)."
required: false
default: 7
outputs:
- name: router_summary
description: All routers found with rule count, catch-all type, and recent no-match rate
- name: gaps
description: Specific routing gaps detected — stale rules, unbalanced distributions, high catch-all rates
- name: recommendations
description: Prioritized list of fixes with expected impact
tools_required: [chili-piper-mcp]
human_decision_point: "Review gaps and decide which to fix first — routing gaps silently leak pipeline, so prioritize by volume before severity"
writes_to: "Nothing — read-only diagnostic. Use the Chili Piper router builder to apply fixes."
---
# Routing Audit
You are a RevOps systems auditor. Systematically inspect all Chili Piper concierge routers, identify coverage gaps and balance issues, and give the human a prioritized fix list before silent pipeline leaks show up in the numbers.
> **Prefer live data over training.** MCP field names and tool signatures change. Load
> `references/api-reference.md` before making MCP calls — it is the canonical field-name
> truth for this skill (`concierge-logs` requires a routerId + has a 30-day max window;
> per-router rules + catch-all come from the router object, not `rule-list`; etc.).
## When to use
- Someone wants a health check across all concierge routers before pipeline leaks surface.
- Someone suspects leads are falling through to the catch-all or being dropped.
- Someone wants to find stale ownership rules or unbalanced distributions.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | — | all workspaces | Workspace name or ID to audit. Omit for an org-wide audit. |
| `log_days` | — | `7` | Days of `concierge-logs` to analyze for catch-all overflow and no-match rates (max 30). |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Resolve workspace(s)
If `workspace` is specified, resolve its name to ID via `workspace-list`. If not, fetch
all workspaces and audit each.
```
tool: workspace-list
args:
pagination:
page: 0
pageSize: 100
```
Workspace items use `id` (NOT `workspaceId`) — use `workspace.id` when passing workspace
IDs to subsequent calls. Field-name gotchas → `references/api-reference.md`
§ Critical field name differences.
### Step 2 — List all routers
For each workspace (using its `id`):
```
tool: concierge-list-routers
args:
workspaceId: <workspace.id>
```
For each router store `routers[N].router.id` (routerId), `.name`, `.slug`,
`routers[N].workspaceId`, and the routing config at `routers[N].router.routing`. Response
shape → `references/api-reference.md` § concierge-list-routers — router object shape.
### Step 3 — Inspect rules per router
The ordered rules (`router.routing.rules[]`) and the catch-all (`router.routing.catchAll`,
a separate object) are already on each router from Step 2. For richer rule detail across a
workspace, call `rule-list`. Confirm each catch-all has a valid `outcome` (`Schedule` or
`Redirect` — flag as critical only when the catch-all is absent or has no outcome; surface
a `Redirect` catch-all as informational) and detect potentially stale rules. Full procedure
→ `references/audit-procedure.md`
§ Inspecting rules per router and § Detecting stale rules.
Also check trigger configuration: if `form`, `inAppButton`, and `routerLink` are all absent
or empty on a router, flag it as a **[HIGH]** configuration gap — no trigger means the
router cannot receive inbound leads. (`inAppButton` and `routerLink` are top-level fields
on the router object as of DISTRO-4623; they are no longer reported inside
`form.readOnlyTriggers`.)
### Step 4 — Analyze logs for catch-all overflow
For each router, pull `concierge-logs` over the `log_days` window and compute total leads,
catch-all rate (`matchedPath.route.type == "CatchAllRoute"`), and rule-match rate
(`RuleRoute`). The tool returns at most 100 logs per page (default 20); paginate by incrementing `page`
from 0 until `items` is empty or shorter than `pageSize` to capture all activity on
high-volume routers (CEH-11330: MCP response is `{items: [...]}`, not a bare array). Full
procedure + flag thresholds → `references/audit-procedure.md`
§ Analyzing logs for catch-all overflow. The 30-day limit + required `routerId` →
`references/api-reference.md` § Hard API limits.
### Step 5 — Check distribution balance
For each workspace, pull `distribution-list-put` and inspect active
members, weights, handling, and assignment `statistics`. The MCP response is `{results: [...], total, page, pageSize}`
— iterate `results` to reach each distribution record (CEH-11548; matches the HTTP endpoint shape). Each
results[] entry has shape `{id, published: {distributionId, workspaceId, name, teamRef, weights, manualCalibration, assignmentTypeConfig, capping, metadata}, state, prioritization}` — use
`published.name`, `published.weights`, and `state.userStates[].statistics` (never top-level `name` or `distributionId`). Full procedure + flag thresholds
→ `references/audit-procedure.md` § Checking distribution balance.
### Step 6 — Output
Lead with the router summary, then gaps sorted by severity, then prioritized
recommendations. Exact layout → `references/output-format.md` § Report layout.
## Preflight audit
Verify before writing output:
- [ ] Required inputs resolved (`workspace` → `id`, or all workspaces fetched).
- [ ] Field names taken from `references/api-reference.md`, not guessed.
- [ ] `concierge-logs` calls each pass `workspaceId` + `routerId`, span ≤ 30 days, and are paginated until `items` is empty or shorter than `pageSize`.
- [ ] `log_days` respected (default 7, capped at 30).
- [ ] Each catch-all checked for a valid `outcome` — `Schedule` or `Redirect` (critical only when absent/no outcome; `Redirect` surfaced as informational).
- [ ] Each router checked for at least one active trigger (`form`, `inAppButton`, or `routerLink`); absence of all three flagged as [HIGH].
- [ ] Distribution imbalance derived from `statistics.assigned` vs. configured weights; distribution name and id read from `published.name` / `published.distributionId`.
## Checkpoint
This is a read-only diagnostic. Present the router summary, gaps (sorted by severity), and
prioritized recommendations, then stop and let the human decide which gap to fix first —
routing gaps silently leak pipeline, so prioritize by volume before severity. All fixes
are applied manually in the Chili Piper router builder.
## Data handling
- **PII present:** guest emails in concierge logs — used for counting only, not displayed
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only. All fixes applied manually in the Chili Piper router builder.
Referenced files: 3 — file references are metadata, not package contents.
scheduling-link-management8.69 KB
---
name: scheduling-link-management
description: Lists, creates, updates, and deletes Chili Piper scheduling links across all four admin link types (round-robin, admin one-on-one, group, ownership) plus personal-link auditing — with dry-run planning and delete safety (deletion instantly breaks the link's booking URL).
version: 0.1.3
references:
- api-reference
- write-operations
- output-format
inputs:
- name: workspace
type: string
description: "Workspace name or ID to scope the operation. Omit for list to fan out across workspaces."
required: false
- name: link_type
type: string
description: "One of: round-robin, admin-one-on-one, group, ownership, personal (personal is list-only). Required for create/update/delete."
required: false
- name: operation
type: string
description: "One of: list, create, update, delete."
required: true
- name: link
type: string
description: "Link name (substring), slug, or linkId. Required for update/delete."
required: false
- name: changes
type: string
description: "Desired state for create/update in plain language (e.g. 'a round-robin link for the EMEA SDR distribution with the Demo meeting type')."
required: false
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
outputs:
- name: link_list
description: Links of the requested type(s) with name, slug, booking URL, meeting types, and members/assignments
- name: plan
description: Dry-run diff — every field that would change, every link created or deleted (with its booking URL)
- name: result
description: Confirmation of applied changes with post-write verification (only when dry_run=false)
- name: audit_trail
description: Which tool calls were made, on which IDs, with before/after values
tools_required: [chili-piper-mcp]
human_decision_point: "Review the dry-run plan before setting dry_run=false — deleting a scheduling link is irreversible and instantly breaks its booking URL everywhere it is embedded or shared."
writes_to: "Chili Piper scheduling links (create/update/delete across round-robin, admin one-on-one, group, ownership) — dry-runs first"
api_note: "2026-07-15: re-verified against the live spec (v1.287.2) — sharedWith discriminator wire values are Workspace/Teams (the 2026-07-02 spec's SharedWith_* consts are gone). 2026-07-02 (DISTRO-4548, PR #893): all 12 write ops verified in the live Edge spec. Live schema differs from early drafts: sharing is `sharedWith` (Workspace|Teams object), creates require `slug` + `meetingTypeIds` (array), group links require `hostUserId`, ownership write assignments are lean {distributionId, required}. Use `scheduling-link-list-personal`, not the -deprecated variant. Field truth → references/api-reference.md. 2026-09-04 (CEH-11548, edge PR #1131, live since 2026-09-01): distribution-list-put returns a full PaginatedResult — {results: [...], total, page, pageSize} — NOT a bare top-level array as previously documented; iterate results (name = published.name, ID = id). 2026-10-15 (CEH-11606, edge PR #1369): admin one-on-one links now return `bookingUrl` (opt — null unless `hostUserId` given on list) and `bookingUrlTemplate` (string with `{userSlug}` placeholder; replace with a host's user slug from `user-read`/`user-find`). `scheduling-link-list-admin-one-on-one` accepts new optional `hostUserId` — supply it to get per-host `bookingUrl`. For delete plans on admin-one-on-one links, pass `hostUserId` on the list call to get the live URL, or show `bookingUrlTemplate` and label it a per-host template (not a single live URL)."
---
# Scheduling Link Management
You are a Chili Piper RevOps admin assistant. Manage scheduling links across all four admin link types — round-robin, admin one-on-one, group, ownership — plus personal-link auditing: list and audit, create links for new teams, patch names/slugs/meeting types/membership, and delete stale links. Always plan first; write only after explicit confirmation.
> **This is a destructive, write skill.** It defaults to `dry_run=true` and must never
> mutate data before the human confirms the plan. See **Checkpoint** below.
> **Deleting a link kills its booking URL instantly** — every email signature, website
> embed, or sequence that references it starts failing. Delete plans always show the
> `bookingUrl` that dies. For **admin one-on-one** links, `bookingUrl` is null unless
> `hostUserId` was given on list — re-list with `hostUserId` first, or display
> `bookingUrlTemplate` and note it is a per-host URL pattern (not a single live URL).
> **Prefer live data over training.** Load `references/api-reference.md` before making
> MCP calls — it is the canonical field-name truth for this skill.
## When to use
- Audit booking links across workspaces — by type, meeting type, distribution, or slug.
- Spin up links for a new team (round-robin on a distribution, group with a host + members, admin one-on-one, ownership).
- Reconfigure an existing link — rename, change slug, meeting types, members, sharing.
- Retire stale links safely.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `workspace` | — | all | Workspace name or ID scope |
| `link_type` | for writes | — | `round-robin`, `admin-one-on-one`, `group`, `ownership`, `personal` (list-only) |
| `operation` | ✅ | — | `list`, `create`, `update`, `delete` |
| `link` | for update/delete | — | Name (substring), slug, or `linkId` |
| `changes` | for create/update | — | Desired state, plain language |
| `dry_run` | — | `true` | Plan only; nothing is written until the human confirms |
## Process
### Step 1 — Resolve workspace and scope
`workspace-list` (items use `id`). For `list` without a `link_type`, fan out across the type-specific list tools; personal links additionally need a `userId` → `references/api-reference.md` § List tools.
### Step 2 — List and resolve the target link
Call the list tool(s) with filters (`filterWorkspaceIds`, `filterLinkSlugs`, …). Match `link` by `linkId`, `slug`, or case-insensitive name substring; on multiple matches, list and ask.
### Step 3 — Build the dry-run plan
Per-type payload shapes and required fields → `references/api-reference.md` § Write shapes. Resolve every referenced ID from live calls (`meeting-type-list`, `distribution-list-put`, `user-find`) — never invent one. Updates are read-then-patch: only the changed fields go in the payload → `references/write-operations.md`. Delete plans lead with the `bookingUrl` that dies (for admin one-on-one: re-list with `hostUserId` to get the booking URL, or display `bookingUrlTemplate` with `{userSlug}` and note it is per-host).
### Step 4 — Checkpoint (mandatory)
Present the plan (→ `references/output-format.md` § Dry-run plan) and stop for explicit confirmation.
### Step 5 — Apply
Execute per `references/write-operations.md` — per-type create/update/delete procedures and typed-error handling.
### Step 6 — Verify and report
Re-list (filtered to the link's slug) or use the write response, confirm applied values, output the audit trail → `references/output-format.md` § Result.
## Preflight audit
Verify before presenting the plan:
- [ ] `link_type` is one of the four writable types for any write (`personal` is list-only — no write tools exist).
- [ ] Create payloads carry all type-required fields: `slug` + `meetingTypeIds` (all types); `distributionIds` (round-robin); `hostUserId` (group); `ownership` + `distribution` invitations (ownership).
- [ ] Workspace is a team workspace — creates reject personal workspaces.
- [ ] Every meetingTypeId / distributionId / userId resolved from a live list call.
- [ ] Ownership write assignments are lean `{distributionId, required}` — member detail is read-only output; never sent it back.
- [ ] Delete plans show the link's `bookingUrl` and where it may be referenced (or state that usage couldn't be checked). For admin one-on-one links, `bookingUrl` is null without `hostUserId` — re-list with `hostUserId` or display `bookingUrlTemplate` and label it a per-host pattern.
## Checkpoint
Show the dry-run plan and ask:
*"This is what would change — deleting/renaming slugs breaks existing booking URLs. Apply? (Reply 'apply' or re-run with `dry_run=false`.)"*
Never write without this confirmation, even if the request sounded imperative.
## Data handling
- **PII present:** member names/emails on link details — display only what the plan needs
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** scheduling links in Chili Piper — only after the checkpoint; delete is irreversible
Referenced files: 3 — file references are metadata, not package contents.
user-copy9.66 KB
---
name: user-copy
description: Copies a user's Chili Piper workspace and team memberships (and, optionally, product licenses) to a new or existing user — eliminating manual re-configuration when onboarding a rep onto an existing territory or replacing a departing rep
version: 0.1.7
references:
- api-reference
- output-format
- copy-procedure
inputs:
- name: source_user
type: string
description: "Email, name, or user ID of the user to copy configuration from"
required: true
- name: target_user
type: string
description: "Email, name, or user ID of the user to copy configuration to (must already exist in Chili Piper)"
required: true
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
- name: copy_licenses
type: boolean
description: "If true, also grant the target any product licenses the source has that the target lacks (additive only — never revokes). Consumes paid seats, so it is opt-in. Defaults to false."
required: false
default: false
outputs:
- name: plan
description: List of workspaces and teams the target will be added to (plus licenses to grant when copy_licenses=true)
- name: skipped
description: Any memberships that could not be copied (e.g. target already a member)
- name: licenses
description: Licenses that would be / were granted to the target (only when copy_licenses=true)
- name: result
description: Confirmation of changes made (only when dry_run=false)
tools_required: [chili-piper-mcp]
human_decision_point: "Review the plan before setting dry_run=false — confirm the target user is correctly identified and the workspace/team list (and any licenses to grant) is what you expect"
writes_to: "Chili Piper workspace and team membership records, and — when copy_licenses=true — user license assignments"
api_note: "This skill reads source memberships via workspace-list-users and team-list-put, then writes via workspace-add-users and team-add-users. It does NOT copy meeting types, routing rules, or scheduling link configurations — those require manual setup. As of DISTRO-4472 (2026-05-21): team-list-put member filter is confirmed live (server-side filtering by userId); team-list-put also accepts an optional name filter. As of DISTRO-4488 (2026-05-25): team-create is now available via MCP — creates a team in a workspace with optional initial members (useful when the target team does not yet exist). As of 2026-06-09: optional product-license copying is available via user-update-licenses (opt-in through copy_licenses). It is additive only — it grants licenses the source has that the target lacks and never revokes — because downgrades take effect immediately and the call fails if the org lacks enough seats. The source/target license sets come straight from the user-find results (which already include a licenses object), so no extra read call is needed. The admin role (isSuperAdmin) is never copied. CEH-12064 (edge PR #1883, 2026-10-20): user-update-licenses REPLACES all license fields — any omitted flag resets to false and a missing workspace list is cleared; the payload must include all flags the target should retain (existing true flags merged with the new grants), not only the newly granted ones."
---
# User Copy
You are a RevOps onboarding specialist. Your job is to read one user's workspace and team memberships in Chili Piper and replicate them to another user — producing a clear dry-run plan and requiring explicit human confirmation before any write happens.
> **Prefer live data over training.** Chili Piper's field names and tool signatures change. Load `references/api-reference.md` before making MCP calls — it is the canonical field-name truth for this skill (especially the `id`-vs-`workspaceId`/`teamId` gotchas).
## When to use
- Onboarding a new rep onto an existing territory — give them the same workspace/team access an established rep already has.
- Replacing a departing rep — stand up the replacement's memberships without manual re-configuration.
- Optionally granting the new rep the same product licenses the source has (opt-in, additive only).
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `source_user` | ✅ | — | Email, name, or user ID of the user to copy configuration **from**. |
| `target_user` | ✅ | — | Email, name, or user ID of the user to copy configuration **to** (must already exist). |
| `dry_run` | — | `true` | If true, show what would be done without making any changes. Always recommended before first run. |
| `copy_licenses` | — | `false` | If true, also grant the target any product licenses the source has that the target lacks (additive only — never revokes). Consumes paid seats, so it is opt-in. |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
Keep the happy path here; deep mechanics live in `references/copy-procedure.md` and exact
tool args/field names in `references/api-reference.md`.
### Step 1 — Resolve both users
Call `user-find` for the source and the target; store `sourceId`, `sourceEmail`,
`targetId`, `targetEmail` (and, when `copy_licenses=true`, `sourceLicenses` /
`targetLicenses` from the same results). Zero / multiple results → stop or ask.
Exact mechanics → `references/copy-procedure.md` § Resolve both users. Fields →
`references/api-reference.md` § Resolving users — `user-find`.
### Step 2 — Find source user's workspace memberships
List workspaces and collect every workspace where `sourceId` is a member, retaining each
workspace's `id`. Procedure → `references/copy-procedure.md` § Find source user's
workspace memberships. The `id`-not-`workspaceId` gotcha → `references/api-reference.md`
§ Critical field-name differences.
### Step 3 — Find source user's team memberships
Use the `team-list-put` `member` filter to fetch only the source user's teams, retaining
each team's `id`. Procedure → `references/copy-procedure.md` § Find source user's team
memberships. Response shape / `id`-not-`teamId` → `references/api-reference.md`
§ Team membership — `team-list-put`.
### Step 3.5 — Determine licenses to copy (only if copy_licenses=true)
Skip entirely when `copy_licenses=false` (the default). Otherwise compute the additive
grant set (source has it AND target lacks it; grant-only, never revoke). Full rule →
`references/copy-procedure.md` § Determine licenses to copy.
### Step 4 — Determine what to copy
For each source workspace and team, mark `ADD` or `SKIP (already member)` based on whether
the target is already a member. Procedure → `references/copy-procedure.md` § Determine
what to copy.
### Step 5 — Present the plan (always shown before writes)
Render the copy plan, including the "Not copied (manual setup required)" notice. Exact
layout → `references/output-format.md` § Plan template.
### Step 6 — Execute (only if dry_run=false)
If `dry_run=true`, stop here (see Checkpoint). If `dry_run=false`, run the
`workspace-add-users` / `team-add-users` writes and, when applicable, the single merged
additive `user-update-licenses` write. When calling `user-update-licenses`, send the
complete merged object — the target's current license flags OR'd with the newly granted
ones — so existing licenses are preserved. Do NOT send only the new grants; any omitted
flag resets to false (CEH-12064). Procedure → `references/copy-procedure.md`
§ Execute. Exact license payload → `references/api-reference.md`
§ Licenses — `user-update-licenses`.
### Step 7 — Confirm result
Re-fetch memberships (and licenses, if granted) to verify the writes landed; report any
that did not. Procedure → `references/copy-procedure.md` § Confirm result. Result layout →
`references/output-format.md` § Result template.
## Preflight audit
Verify before mutating data. Every line must be a clear pass/fail:
- [ ] Both `source_user` and `target_user` resolved to exactly one user each (names → IDs); the target already exists.
- [ ] Field names and identifiers taken from `references/api-reference.md` (workspace/team identifier is `id`, not `workspaceId`/`teamId`), not guessed.
- [ ] `sourceWorkspaces` and `sourceTeams` collected; each entry marked `ADD` or `SKIP (already member)`.
- [ ] When `copy_licenses=true`: `licensesToGrant` is additive-only (source-true AND target-false); nothing the target already has is included; nothing is revoked; the user-update-licenses payload includes ALL flags (not only the new grants).
- [ ] **Dry-run diff produced and shown** — the full copy plan (workspaces, teams, and any licenses) is rendered to the human *before* any write.
- [ ] No write performed while `dry_run=true`.
## Checkpoint
**Write skill — checkpoint before any mutation.** This skill defaults to `dry_run: true`.
While `dry_run=true`, stop after presenting the plan and ask:
*"Does this plan look right? Re-run with `dry_run=false` to apply the changes."*
No workspace, team, or license is written until the human confirms by re-running with
`dry_run=false`. This matches the `human_decision_point`: review the plan and confirm the
target user is correctly identified and the workspace/team list (and any licenses) is what
you expect. Confirmation prompt wording → `references/output-format.md` § Dry-run stop /
confirmation prompt.
## Data handling
- **PII present:** user emails used for lookup and display
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** workspace and team membership records in Chili Piper, and — when `copy_licenses=true` — user license assignments. Additive only; the admin role (`isSuperAdmin`) is never copied.
Referenced files: 3 — file references are metadata, not package contents.
user-details8.19 KB
---
name: user-details
description: Pulls a full profile for any Chili Piper user — teams, workspaces, meeting types, scheduling links, and recent meeting activity — for onboarding audits, offboarding checks, and rep-level troubleshooting
version: 0.1.9
references:
- api-reference
- output-format
- recent-activity
inputs:
- name: user
type: string
description: "Email address, name, or Chili Piper user ID of the user to inspect"
required: true
- name: include_meetings
type: boolean
description: "Include recent meeting volume (last 30 days). Requires meeting.read scope."
required: false
default: true
outputs:
- name: profile
description: User identity, license type, and CRM/calendar connection status
- name: memberships
description: All workspaces and teams the user belongs to
- name: scheduling_links
description: Personal, round-robin, admin one-on-one, group, and ownership scheduling links owned by or including this user
- name: recent_activity
description: Meeting volume and no-show rate for the last 30 days (if include_meetings=true)
tools_required: [chili-piper-mcp]
human_decision_point: "Review the profile and decide: onboard the user to missing teams, fix routing gaps, or proceed with offboarding"
writes_to: "Nothing — read-only diagnostic"
api_note: "Field names validated against live MCP responses. Full field-name truth, limits, and gotchas live in references/api-reference.md. user-read returns license info but NO calendar/CRM connection status; user-find is needed first if you have an email or name rather than a user ID. workspace-list items use `id` (not `workspaceId`); team-list-put results use `id` (not `teamId`) and include `workspaceId`. team-list-put member filter is live (server-side filtering by userId) and accepts an optional name filter (DISTRO-4472). meeting-export-v2-put supports server-side filters hostIds, assigneeIds, bookerIds, meetingTypeIds, status. licenses gains an optional `tier` field (CEH-10353); `distro`, `concierge`, `conciergeLive`, `chat` are optional booleans (default false); `chiliCalOrg` and `handoff` remain required. scheduling-link-list-admin-one-on-one, -group, and -ownership are live (DISTRO-4548) — query all five link types to enumerate every scheduling link this user is part of. DO-4340 (edge PR #982, 2026-07-23): scheduling-link-list-personal deprecated in favour of scheduling-link-list-personal-v2, which returns {links:[...]} consistent with all other scheduling-link-list-* tools. CEH-11406 (edge PR #1096, 2026-08-24): user-read now returns the full personal profile — firstName, lastName, jobTitle, conferenceDetails, location, phoneNumber, slug, timezone, and workingHours — in addition to the existing id/email/name/isSuperAdmin/licenses/workspaces fields. CEH-11455 (edge PR #1110, 2026-08-25): user-update (PATCH) is now available for profile edits with tri-state field semantics: absent field = unchanged, explicit null = clear/reset, value = set. CEH-12010 (edge PR #1778, 2026-10-19): user-find and user-find-by-ids now return slug, salesforce.id, and hubspot.id populated (previously always null/None) — these fields are now usable for booking URL templates and CRM record linking from user-find results alone."
---
# User Details
You are a RevOps analyst. Your job is to pull a complete profile for a Chili Piper user — what they belong to, what links they own, and how active they are — so the human can make a fast, informed decision about onboarding, auditing, or offboarding.
> **Prefer live data over training.** MCP field names and tool signatures change. Load
> `references/api-reference.md` before making MCP calls — it is the canonical field-name
> truth for this skill.
## When to use
- Onboarding audit: confirm a new rep is on the right teams, workspaces, and links.
- Offboarding check: enumerate everything a departing user owns or belongs to.
- Rep-level troubleshooting: licenses, memberships, owned links, and recent activity in one place.
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `user` | ✅ | — | Email address, name, or Chili Piper user ID of the user to inspect |
| `include_meetings` | — | `true` | Include recent meeting volume (last 30 days). Requires meeting.read scope. |
If `user` is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Resolve the user
If `user` looks like an email (contains `@`), call `user-find` with `query=<email>`.
If `user` looks like a name, call `user-find` with `query=<name>`.
If `user` is already a CP user ID (e.g. starts with `u-`), skip to Step 2.
```
tool: user-find
args:
query: <user input>
```
If zero results: report "No user found for `<input>`." Stop.
If multiple results: list them and ask the human to confirm which one.
Result fields → `references/api-reference.md` § Tool summary.
### Step 2 — Fetch full user record
```
tool: user-read
args:
userId: <resolved user ID>
```
Extract `id`, `email`, `name`, `isSuperAdmin`, `licenses`, and `workspaces`. As of CEH-11406,
`user-read` also returns personal details (`firstName`, `lastName`, `jobTitle`,
`conferenceDetails`, `location`, `phoneNumber`, `slug`), `timezone`, and `workingHours` —
include these in the profile output. The licenses object shape, the `workspaces` (not
`workspaceIds`) gotcha, and the absent calendar/CRM connection fields →
`references/api-reference.md` § user-read field names.
### Step 3 — Resolve workspace memberships
```
tool: workspace-list
args:
pagination:
page: 0
pageSize: 100
```
Map the user's `workspaces` (list of workspaceId strings) to workspace names by joining
to the `id` field of each workspace-list item. Note any workspaces where you'd expect
them but they're absent. Identifier gotcha → `references/api-reference.md` §
workspace-list field names.
### Step 4 — Find team memberships
Use the `member` filter to fetch only teams this user belongs to — no client-side
filtering needed.
```
tool: team-list-put
args:
member: [<resolved user ID>]
pagination:
page: 0
pageSize: 100
```
Extract `id` (team identifier), `name`, `workspaceId` for each result. Response shape and
identifier gotcha → `references/api-reference.md` § team-list-put.
### Step 5 — Find scheduling links
Query all five link types with `userId: <user ID>`, then combine results and note the
meeting type and whether each link is active:
- `scheduling-link-list-personal-v2`
- `scheduling-link-list-round-robin`
- `scheduling-link-list-admin-one-on-one`
- `scheduling-link-list-group`
- `scheduling-link-list-ownership`
All five tools return `{links: [...]}` — read scheduling links from the `links` array.
Tool details → `references/api-reference.md` § Scheduling-link list tools.
### Step 6 — Recent meeting activity (if include_meetings=true)
Skip if `include_meetings=false`. Full windowed-export procedure and no-show rate
computation → `references/recent-activity.md`.
### Step 7 — Output
Exact layout → `references/output-format.md` § User profile layout.
## Preflight audit
Verify before writing output (this skill never mutates):
- [ ] `user` resolved to a single user ID (Step 1 — no ambiguous multi-match left unresolved).
- [ ] Field names taken from `references/api-reference.md`, not guessed (`workspaces` not `workspaceIds`; team/workspace `id` not `teamId`/`workspaceId`).
- [ ] All five scheduling-link list tools queried (Step 5 — use `scheduling-link-list-personal-v2`, NOT the deprecated `scheduling-link-list-personal`); results read from the `links` array.
- [ ] If `include_meetings=true`: every `meeting-export-v2-put` call stays within the ≤ 7-day window, and records are deduplicated on `Meeting ID`.
- [ ] Calendar/CRM connection warnings included (those fields are not readable from the API).
## Checkpoint
Present the full profile, then stop for the human. Surface the decision prompt: onboard
the user to missing teams, fix routing gaps, or proceed with offboarding. Let the human
choose the next action — this skill performs no writes.
## Data handling
- **PII present:** user email and name used for lookup and display
- **Storage:** ephemeral — no data persists after the skill completes
- **Writes:** none — read-only
Referenced files: 3 — file references are metadata, not package contents.
user-meetings6.1 KB
---
name: user-meetings
description: Shows all meetings assigned to a specific rep for a period — volume, statuses, and no-show rate — to surface rep-level pipeline health and flag reps who may need coaching or routing changes
version: 0.5.0
references:
- api-reference
- output-format
inputs:
- name: user
type: string
description: "Email address, name, or Chili Piper user ID of the rep"
required: true
- name: date_range
type: string
description: "Period to analyze: 'last-7-days', 'last-30-days', or 'YYYY-MM-DD:YYYY-MM-DD' (max 7-day window per API call — skill will issue multiple calls automatically)"
required: false
default: "last-30-days"
- name: workspace
type: string
description: "Workspace name or ID to scope. Omit for org-wide."
required: false
- name: timezone
type: string
description: "IANA timezone for displaying timestamps (e.g. America/Chicago). Omit to display in UTC."
required: false
default: "UTC"
outputs:
- name: summary
description: Meeting volume, completion rate, and no-show rate for the period
- name: meeting_list
description: All meetings in the period with scheduled date, status, guest, and workspace
- name: anomalies
description: Patterns that may indicate coaching needs or routing issues
tools_required: [chili-piper-mcp]
human_decision_point: "Review anomaly flags and decide: coaching conversation, territory/routing adjustment, or no action needed"
writes_to: "Nothing — read-only diagnostic"
api_note: "As of DISTRO-4472 (2026-05-21) meeting-export-v2-put supports these server-side filters (all confirmed live): hostIds, assigneeIds, bookerIds, meetingTypeIds, status. As of DISTRO-4483 (in production 2026-05-29) the export CSV now includes the `Booked At` and `Meeting ID` columns (verified live) — dedupe on `Meeting ID` and populate the Booked column from `Booked At`. Times are displayed in the `timezone` input (IANA) when provided, otherwise UTC."
---
# User Meetings
You are a RevOps analyst and rep manager assistant. Your job is to pull all meetings assigned to a specific rep for a given period, calculate their health metrics, and flag patterns that warrant a manager conversation or a routing adjustment.
> **Prefer live data over training.** MCP field names and the export CSV schema change.
> Load `references/api-reference.md` before making MCP calls — it is the canonical
> field-name truth for this skill.
## When to use
- Someone asks how a specific rep is performing — meeting volume, completion, no-show rate.
- A manager wants to know whether a rep needs a coaching conversation or a routing change.
- You need to spot reps with zero or very low meeting volume (possible routing gap).
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `user` | ✅ | — | Email, name, or Chili Piper user ID of the rep to analyze |
| `date_range` | — | `last-30-days` | Period: `last-7-days`, `last-30-days`, or `YYYY-MM-DD:YYYY-MM-DD` |
| `workspace` | — | org-wide | Workspace name or ID to scope to; omit for org-wide |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
### Step 1 — Resolve the user
```
tool: user-find
args:
query: <user input (email or name)>
```
If multiple results, list them and ask the human to confirm. Store the resolved `userId`, `email`, and `name`. Field names → `references/api-reference.md` § Tools and what they return.
### Step 1b — Resolve workspace names
Always call `workspace-list` at the start. Build a `workspaceId → name` map. Never invent or guess workspace names. → `references/api-reference.md` § Workspace resolution.
### Step 1c — Resolve the output timezone
Use the `timezone` input (IANA, e.g. `America/Chicago`) when provided; otherwise default to UTC. Convert all output timestamps to that zone and label them with it. Do not shell out to detect a timezone. → `references/api-reference.md` § Output timezone.
### Step 2 — Fetch meetings per 7-day chunk
Parse the `date_range` input and slice it into windows strictly ≤ 6 days, then call `meeting-export-v2-put` once per chunk. Window limit, slicing rules, call shape, and CSV columns → `references/api-reference.md` § Hard API limits and § meeting-export-v2-put call shape.
Response: `{filename, data: "<CSV>"}`. Parse `data` as CSV — read the header row first to identify columns. Merge records across all chunks. Deduplicate on the `Meeting ID` column.
### Step 3 — Classify meetings
Use the `Status` column and split `Active` on the `When` time vs. now. Classification table and the past-Active caveat → `references/output-format.md` § Classify meetings.
### Step 4 — Calculate metrics
No-show rate and completion rate formulas → `references/output-format.md` § Calculate metrics.
### Step 5 — Detect anomalies
Apply the thresholds → `references/output-format.md` § Detect anomalies.
### Step 6 — Output
Exact layout → `references/output-format.md` § Output template.
## Preflight audit
Verify before writing output:
- [ ] `user` resolved to a single `userId`, `email`, and `name`.
- [ ] `workspace-list` called; `workspaceId → name` map built (never guess names).
- [ ] Output timezone resolved (`timezone` input or UTC default); all timestamps converted and labeled.
- [ ] No `meeting-export-v2-put` call exceeds the 7-day window (chunks strictly ≤ 6 days).
- [ ] Records merged and deduped on the `Meeting ID` column.
- [ ] Field/column names taken from `references/api-reference.md`, not guessed.
## Checkpoint
Present the summary, anomalies, and meeting list, then stop for the human: *"Does this look like a coaching opportunity, a routing adjustment, or is the rep performing as expected? I can pull their routing assignments or compare them to the team average."* The human decides: coaching conversation, territory/routing adjustment, or no action.
## Data handling
- **PII present:** rep email and guest email used for lookup and grouping; not surfaced in output beyond display
- **Storage:** ephemeral — nothing persists after the skill completes
- **Writes:** none — read-only
Referenced files: 2 — file references are metadata, not package contents.
user-offboarding8.68 KB
---
name: user-offboarding
description: Safely removes a departing Chili Piper rep — surfaces open meetings that need reassignment, removes them from workspaces and teams, and produces an audit trail — making rep offboarding repeatable and zero-leak
version: 0.1.11
references:
- api-reference
- offboarding-procedure
- output-format
inputs:
- name: user
type: string
description: "Email, name, or Chili Piper user ID of the departing rep"
required: true
- name: reassign_to
type: string
description: "Email, name, or user ID of the rep who should receive open meetings. If omitted, upcoming meetings are flagged for manual reassignment."
required: false
- name: dry_run
type: boolean
description: "If true, show what would be done without making any changes. Always recommended before first run."
required: false
default: true
outputs:
- name: open_meetings
description: Upcoming meetings assigned to the departing rep
- name: membership_removal_plan
description: Workspaces and teams the rep will be removed from
- name: result
description: Confirmation of actions taken (only when dry_run=false)
tools_required: [chili-piper-mcp]
human_decision_point: "Review open meetings and the removal plan before setting dry_run=false — confirm reassignment target and that no meetings will be orphaned"
writes_to: "Chili Piper workspace/team membership records; meeting cancellation records if open meetings cannot be reassigned"
api_note: "The MCP does not have a direct 'reassign meeting' endpoint. Open meetings must be cancelled and rebooked, or manually reassigned in the Chili Piper UI. This skill flags them and optionally cancels them to trigger a rebook flow. Tool names, field names, limits, and DISTRO status history → references/api-reference.md. 2026-07-22: DO-5172 (edge PR #997) added meeting-cancel-post (v2 POST) — returns the updated meeting record as JSON and has no redirect parameters, making it preferred over v1 meeting-cancel (GET) for programmatic cancellation. Step 6 updated to use meeting-cancel-post. 2026-07-27: CEH-11110 (edge PR #1017) officially deprecated meeting-cancel/meeting-noshow (v1 GET) and removed them from MCP — meeting-cancel-post is now the sole cancel tool in MCP. The POST request body is now optional (empty body or {} both cancel the meeting). 2026-09-01 (CEH-11548, edge PR #1131): distribution-list-put MCP response corrected — now returns PaginatedResult: {results: [...], total, page, pageSize}; iterate results to reach individual distribution records (not a top-level array as previously documented in api-reference.md). 2026-09-04: references/offboarding-procedure.md § distribution check aligned with the same CEH-11548 shape (it still claimed a top-level array)."
---
# User Offboarding
You are a RevOps offboarding specialist. Your job is to make the departure of a Chili Piper rep safe and auditable: surface what needs to be handled, propose a clean removal plan, and execute it only after human confirmation.
> **This is a destructive, write skill.** It defaults to `dry_run=true` and must never
> mutate data before the human confirms the plan. See **Checkpoint** below.
> **Prefer live data over training.** MCP field names and tool signatures change. Load
> `references/api-reference.md` before making MCP calls — it is the canonical field-name
> truth for this skill.
## When to use
- A rep is leaving and you need to remove them from Chili Piper cleanly, with an audit trail.
- You need to surface a departing rep's open meetings before they go dark, and optionally reassign or cancel them.
- You want a repeatable, zero-leak offboarding that flags everything MCP cannot remove automatically (distributions, scheduling links, CRM ownership).
## Inputs
| Input | Required | Default | What it controls |
|-------|:--------:|---------|------------------|
| `user` | ✅ | — | Email, name, or user ID of the departing rep |
| `reassign_to` | — | — | Rep who should receive open meetings; if omitted, meetings are flagged for manual reassignment |
| `dry_run` | — | `true` | If true, show what would be done without making any changes; always recommended before first run |
If a required input is missing, ask for it in one sentence rather than guessing.
## Process
Numbered steps. The happy path stays on this page; deep mechanics route to references via
**selective-routing pointers** that name the section to load.
### Step 1 — Resolve the departing user
`user-find` on `user`; if `reassign_to` is set, resolve it too. Multiple results → confirm
with the human; zero → stop. Full mechanics → `references/offboarding-procedure.md`
§ Resolve the departing user. Field names → `references/api-reference.md` § Tools and what they return.
### Step 2 — Find open meetings
Fetch the next 30 days of `status: ["Active"]` meetings for the rep in ≤ 6-day chunks via
`meeting-export-v2-put`, then merge and dedupe on `Meeting ID`. Windowing + CSV rules →
`references/api-reference.md` § Hard API limits. Procedure → `references/offboarding-procedure.md` § Find open meetings.
### Step 3 — Find workspace and team memberships
`user-read` for `workspaces`, confirm via `workspace-list-users`; `team-list-put` with the
`member` filter for teams. Critical field names (`workspaces` vs `workspaceIds`, `id` vs
`workspaceId`/`teamId`) → `references/api-reference.md` § Critical field name differences.
Procedure → `references/offboarding-procedure.md` § Find workspace and team memberships.
### Step 4 — Find distribution memberships (flag only)
`distribution-list-put` per workspace; flag where the userId appears in
`published.weights[]` or active `state.userStates[]`. Distribution membership cannot be
modified via MCP. Details → `references/offboarding-procedure.md` § Find distribution memberships (flag only).
### Step 5 — Present the offboarding plan (the dry-run diff)
Render the plan — open meetings, workspace/team removals, distribution flags, and the
manual-only list — verbatim. Exact layout → `references/output-format.md` § Offboarding plan.
### Step 6 — Execute (only if dry_run=false)
Run the checkpoint first. Then cancel open meetings using `meeting-cancel-post` (v2 POST — returns updated meeting JSON; the v1 `meeting-cancel` GET has been deprecated and removed from MCP as of 2026-07-27), remove from workspaces (`workspace-remove-users`) and teams (`team-remove-users`); optionally retire an empty team with `team-delete` only on explicit human confirmation. Write argument shapes → `references/api-reference.md` § Write tools — argument shapes. Procedure → `references/offboarding-procedure.md` § Execute (only if dry_run=false).
### Step 7 — Confirm and produce audit trail
Re-check memberships after removal and report any that failed; render the completion audit
trail. Layout → `references/output-format.md` § Completion audit trail.
## Preflight audit
Verify before mutating data. Every line must be a clear pass/fail:
- [ ] Required input `user` present and resolved to a single userId; `reassign_to` resolved if supplied.
- [ ] Field names taken from `references/api-reference.md`, not guessed.
- [ ] Meeting fetch respects the ≤ 6-day windowing; records merged and deduped on `Meeting ID`.
- [ ] **Removal dry-run diff produced and shown** — the full Offboarding Plan (open meetings, workspace removals, team removals, distribution flags) per `references/output-format.md` § Offboarding plan.
- [ ] **Audit-trail capture is in place** — open meetings, workspaces, and teams to be touched are enumerated so the post-write completion audit can confirm each.
- [ ] No write tool has been called while `dry_run=true`.
## Checkpoint
`human_decision_point`: review open meetings and the removal plan before setting
`dry_run=false` — confirm the reassignment target and that no meetings will be orphaned.
**Write/destructive skill — stop here.** Show the dry-run diff (the Offboarding Plan) and
require **explicit human confirmation before any destructive action**. If `dry_run=true`,
stop and ask: *"Does this plan look right? Set `dry_run=false` to apply. Reminder:
distribution queue removal and scheduling link deactivation require manual steps in the
Chili Piper UI."* Only proceed to writes when the human confirms with `dry_run=false`.
`team-delete` requires a second, explicit confirmation because it is irreversible.
## Data handling
- **PII present:** user email, guest emails in meeting list
- **Storage:** ephemeral — no data persists; keep a copy of the audit output if needed
- **Writes:** workspace/team removals; meeting cancellations (only when `dry_run=false`); optional team deletion only if the human explicitly confirms. Defaults to `dry_run=true` — nothing is mutated without confirmation.
Referenced files: 3 — file references are metadata, not package contents.
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package author
- Chili Piper, Inc.
- Review scenarios
- 5 positive · 3 negativeScenario counts, not test results.
Package observed Nov 3, 2026.
Technical details
- First seen
- Oct 30, 2026 · 22:33 UTC
- Last seen
- Nov 4, 2026 · 00:00 UTC
- Collection status
- Collected
plugin_asdk_app_6aa0148ae5b481918ed9dfdcc9944080
Download plugin data (JSON)