Userflow
Userflow Inc. v4.0.0
Connect your Userflow account to the official Userflow MCP to query product adoption data and build directly in ChatGPT. Ask about flows, segments, users, and analytics (completion rates, NPS, survey responses, and event data) to see how users move through your product and find where they get stuck—then have ChatGPT create the segment, flow, chart, or dashboard the answer points to. Every write comes back as a draft you review; nothing publishes without you, all without leaving ChatGPT.
Language: English · Automatically detected from descriptions.
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package author
- Userflow Inc.
Package observed Sep 30, 2026.
Files & skills
File archives
Skill instructions
userflow-adoption-agent-topics12.9 KB
---
name: userflow-adoption-agent-topics
description: Read what people actually asked a Userflow Adoption Agent over a time window (default last 30 days) and turn it into a shareable HTML report of plainly-named topics, split into what the agent couldn't answer, what got thumbs-down, and what came up most — every topic expandable to the real conversations behind it. Use this skill whenever a user with the Userflow MCP connected asks "what are people asking the agent", "what are the top topics in the Adoption Agent", "what is the assistant failing to answer", "where is the agent getting negative feedback", "cluster our agent conversations", "analyse Adoption Agent questions", "what are the knowledge gaps in our agent", "summarise AI assistant conversations", or wants any topic, theme, cluster, gap, or failure analysis of an Adoption Agent / AI Assistant / assistant flow. Also trigger when a picker widget from this skill sends a prompt like "Build the Adoption Agent topic report for ... over ...". Requires the Userflow MCP connector.
---
# Userflow Adoption Agent topic report
Turn an Adoption Agent's raw conversation log into a report a PM or support lead can act on: a set of clearly-named topics, sorted into the three questions people actually want answered — **what is the agent failing to answer, what is it getting yelled at for, and what does it get asked most** — with every topic opening up to the real conversations underneath.
The audience is anyone running an Adoption Agent, not just analysts. So topic names have to read like something a colleague would say out loud, and every number has to be traceable to conversations the reader can inspect.
## Requirements
The **Userflow MCP connector** must be connected. If it isn't, say so and stop — there is no useful fallback.
## The flow at a glance
1. **Pick the agent and window** — one picker widget; assistant flow names are heavily duplicated, so never resolve by name alone.
2. **Size the job** — one analytics call gives denominators and tells you how much to pull.
3. **Pull the conversations** — three paginated pulls (disliked, unanswered, general).
4. **Cluster it yourself** — from what users actually wrote. Do not inherit the API's topic model.
5. **Build the report** — one self-contained HTML artifact with expandable topics.
6. **Write insights** — a few paragraphs of prose after the artifact, never inside it.
Read `references/api-notes.md` before the first data call. It documents the field semantics and pagination traps that will otherwise silently corrupt the report — several of them look like working data until you check. Read `references/artifact-template.md` at step 5.
---
## Step 1 — Pick the agent and the window
Call `describe_session` for `env_id`. Default to Production; only ask if the account has several plausible environments and the user hasn't said.
Call `list_flows` with `types: "assistant"`. Expect a lot of them, mostly drafts — real accounts accumulate test copies. **Names repeat**: an account can hold three flows called "Userflow Adoption Agent" and four called "Userflow AI Assistant". Resolving by name would silently analyse an abandoned draft, so the picker exists to make the user choose a specific UUID.
Render a picker widget (Visualizer, `interactive` module): the assistant flows as selectable rows, published first, then by `edited_at` descending. Each row needs enough to disambiguate identically-named flows — state, publication count, last edited date, and the first 8 characters of the UUID. Add window chips (7 / 30 / 90 days / custom, default **30 days**) and a "Build topic report ↗" button whose `sendPrompt` carries the flow name, UUID, and window. Then end the turn.
Flows with `total_publications: 0` have almost certainly never taken traffic. Keep them selectable but visually de-emphasised, so someone who wants a draft can still pick one and get an honest empty report rather than being blocked.
## Step 2 — Size the job before pulling
Call `get_adoption_agent_analytics` with the flow UUID, `env_id`, the window, and `interval: "week"`. This is one cheap call that returns `conversation_stats` (total, liked, disliked, unanswered) and `message_stats` (total messages plus a weekly series with per-week likes and dislikes).
Use it for three things: the report's KPI row, the denominators that turn raw counts into rates, and a pull budget. Roughly, conversations ÷ 50 is the number of paginated calls a full read would take — decide from that whether you can read everything or need to sample, and tell the user which you did.
If the window has almost no traffic (say under 10 conversations), say so plainly and offer a wider window before building anything. Clustering five conversations produces five "topics" and no insight.
## Step 3 — Pull the conversations
Three pulls with `list_adoption_agent_conversations`, always passing `flow_id`, `env_id`, `start_date`, `end_date`, and `include_messages: true`:
1. `conversation_type: "disliked"` — always read all of these. There are usually very few (single or low double digits even across a busy month) and they carry the most valuable content in the dataset.
2. `conversation_type: "unanswered"` — read all, up to your budget.
3. **No `conversation_type`** — the general corpus, for the frequency ranking. This is the expensive one; paginate with `offset`.
`include_messages: true` caps `limit` at 50 regardless of what you ask for, so pagination is mandatory on anything but a quiet window. Dedupe across the three pulls by conversation `id` — a disliked conversation also appears in the general pull, and double-counting it inflates topic sizes.
If you can't read the whole corpus within budget, read the disliked and unanswered sets completely and sample the general pull, because the first two sections must be exhaustive to be trustworthy while the frequency ranking degrades gracefully. Then state the coverage in the report footer: "clustered from 480 of 630 conversations".
## Step 4 — Do your own clustering
**Cluster from the raw messages. Do not use the API's topic model as your grouping.** There is a `get_adoption_agent_top_topics` tool and it returns tempting pre-built sections, but its topic descriptions routinely describe different subject matter than the conversations filed under them, and it tends to dump most traffic into one catch-all topic that then ranks first in every category at once. A report built on it looks authoritative and says nothing. `references/api-notes.md` has the specifics.
Optionally call it once as a cross-check. If your clustering and its ranking disagree sharply, that divergence is worth one line in the insights — but your clustering is the one that ships.
**Cluster on `user_content`, not `assistant_content`.** Assistant replies are templated ("I'm sorry, but I couldn't find specific information in our knowledge base…"), so clustering on them produces groups that describe the agent's failure modes rather than the users' subject matter. What people asked is the signal.
### Naming topics so they're actually readable
This is the part that determines whether the report gets used. Name each topic as the user's intent, in the plainest words that fit — a short verb or noun phrase someone could say in a standup. Abstract nominalisations ("User Interaction and Data Filtering") are what the machine-generated version already does badly; the value you add is saying what people actually wanted.
| Instead of | Say |
|---|---|
| User Interaction and Data Filtering | Can't find Adoption Studio |
| Last Seen and Activity Fields | What "Last seen" actually means |
| Request to Complete Field | Builder field-fill requests |
| Event Tracking Configuration Queries | Setting up event tracking |
| Subscription Tier Feature Access | Hitting a paywall mid-task |
Give each topic a **one-sentence description** in the same register — what these people want and why they're stuck, not a restatement of the name. Aim for **6–12 topics**. Fewer than 6 and you've built the catch-all bucket you were trying to avoid; more than 12 and nobody reads it. Sweep genuine one-offs into a single "Other one-off questions" entry rather than padding the list — but never sweep a *disliked* conversation into it, since a single angry conversation can be the most important thing in the window.
### Frustration chains
A user escalating across turns ("where is the adoption studio?" → "Yes, tell me how to locate it" → "are you serious") is one topic entry, not seven. Count it once, but flag it — repeated escalation inside a single conversation is a stronger failure signal than seven unrelated unanswered questions, and the reader should see that.
### Internal and test traffic
Real accounts have their own team hammering the agent, and it distorts everything. Tell-tale signs: the same `user_content` verbatim dozens of times, agent-action messages rather than questions (`is_unanswered: null` with replies like "I have filled in the field"), and traffic concentrated in two or three recurring `user_id` values.
Keep these topics in the report, marked with a visible **Test** badge, and exclude them from the headline customer counts while still showing their own counts. The reason to show rather than drop them is that the reader needs to know why their message volume looks high, and mislabelling internal QA as customer demand is exactly the error the report exists to prevent. If a topic is ambiguous, leave it unbadged and mention the doubt in the insights.
## Step 5 — The three sections
Every section is a ranked stack of expandable topic cards. Read `references/artifact-template.md` for the HTML.
1. **Couldn't answer** — topics ranked by how many messages have `is_unanswered: true`. Note that this is the agent's own self-report of not finding a knowledge-base match, not a judgment of correctness; a confidently wrong answer counts as answered. Say this in the report, because readers will otherwise treat the unanswered rate as an accuracy score.
2. **Negative feedback** — topics containing messages with `rating: "dislike"`. Always surface the `feedback` free-text verbatim where it exists. It's the only place a user says in their own words what went wrong, and it lands harder than any count.
3. **Asked most often** — topics ranked by conversation count, with the test-badged ones visibly separated from customer traffic.
**A topic appearing in more than one section is expected and meaningful** — the thing people ask most is often the thing that fails most. Render it in each section it qualifies for, but keep one canonical name and description, and badge the repeat ("also #1 unanswered") so the reader understands they're seeing the same topic rather than two similar ones.
## Step 6 — Build the artifact
Create one self-contained HTML file in the current task's designated user-facing output directory and return a clickable link to it. Structure, styling, and the expand/collapse pattern are in `references/artifact-template.md`.
The one behaviour that matters most: **sort every conversation's messages by `inserted_at` before rendering**. The API returns them unordered, so an unsorted transcript reads as gibberish and destroys trust in the whole report.
## Step 7 — Insights, as prose, after the artifact
Two to four short paragraphs in the chat — not inside the HTML. Reach for the readings the counts don't make obvious:
- **Knowledge gaps vs product gaps.** "Can't find X" is a docs or discoverability problem; "X is only available on a higher plan" is a packaging problem hitting users mid-task. They have different owners, and separating them is the most useful thing this report does.
- **What the dislikes are really about.** Check whether the thumbs-down clusters on wrong answers or on the agent cheerfully offering to help and then failing — the second is a tone-and-capability mismatch and is fixable in the prompt.
- **Concentration.** If a large share of traffic comes from a handful of users, or one week spikes, name it and suggest what to check.
- **What to do next.** One or two concrete moves: articles to write, a paywall message to reword, a topic worth adding to the knowledge base.
Then offer the obvious follow-ups: a wider window, a different agent, or a drill into one topic.
## Known limitations — state these, don't paper over them
- `user_id` values are internal UUIDs. No current Userflow MCP tool resolves them to names or emails, so show shortened IDs and explain the gap if asked rather than guessing.
- Conversation-level and message-level counts disagree slightly (a conversation with two disliked messages counts once in `conversation_stats`, twice in `message_stats`). Pick one basis per number, label it, and don't reconcile them silently.
- "Unanswered" means the agent said it couldn't find an answer. Silent wrong answers are invisible to this report.
- Clustering is a judgment call. When a conversation could sit in two topics, put it where its opening question points and keep the verbatim text visible so a reader can disagree.
Referenced files: 3
userflow-announcement-creator9.13 KB
---
name: userflow-announcement-creator
description: Create an in-app announcement in Userflow through a guided, conversational flow — gather context (a short summary, OR a linked doc/ticket via a connected MCP or Cowork, OR pasted content), draft and refine the copy with the user, set the notification level (silent / badge / boosted → pop-out, modal, or notification), optionally target specific users, show a confirmation card, create the unpublished draft via the Userflow MCP, hand back the Builder link, and offer to publish. Use this whenever a user with the Userflow MCP connected wants to "create an announcement", "announce a feature / update / release / fix", "post an in-app announcement", "draft an announcement", "let users know about X in Userflow", or turn a release note / changelog entry / Jira ticket / Notion doc into a Userflow announcement. Requires the Userflow MCP connector.
---
# Userflow Announcement Creator
Guide the user from a rough idea (or a linked doc/ticket) to a finished, ready-to-publish
Userflow announcement. This is a **conversational, step-by-step** skill: move through the phases
below in order, and **pause for the user at each ✋ checkpoint** — never barrel ahead and create or
publish anything without an explicit yes.
The single most important habit: **create is not publish**. `create_flow` only saves an unpublished
draft and returns a Builder link. Nothing is live until the user confirms and you call
`set_flow_publication`. When in doubt, do less and ask.
## Before you start
1. Confirm the **Userflow MCP** is connected (its tools are available). If not, tell the user this
skill needs the Userflow connector and stop.
2. Resolve the **environment**. Call `describe_session` to list environments. If there's exactly
one, use it. If there are several (e.g. production vs. a test env), ask which one this
announcement is for, and pass that `env_id` on every subsequent Userflow call that accepts it.
Default to the user's usual working environment if they've made it clear in conversation.
Don't over-explain the plumbing — a brief "Which environment — production?" is enough.
---
## Phase 1 — Gather the context
Ask the user for the source material, offering three ways to provide it:
> "What's this announcement about? You can give me a short summary, share a link to a doc or ticket
> that has the context (Notion, Jira, a Google Doc, etc.), or just paste the content in."
**If they share a link**, fetch it with the matching connected tool — Notion for a Notion page,
the Atlassian tools for a Jira issue or Confluence page, Google Drive for a Doc, Intercom, etc., or
`web_fetch` for a public URL. In Cowork, read an attached/linked file directly. If you can't access
it (no connector, permissioned, returns nothing), say so plainly and ask them to paste the relevant
part instead — don't guess at the contents.
**If they give a summary or paste text**, work from that.
Pull out what an announcement needs: what changed, who it's for, why it matters, and any link or
action users should take. If something important is missing (e.g. there's no obvious user benefit),
ask one short follow-up rather than inventing it.
---
## Phase 2 — Draft and refine the copy
Write the announcement as a **title** plus a short **body**. Keep it clear, specific, and benefit-led
— lead with what the user gets, not internal jargon. If the `userflow-brand-copy` skill is
available, follow its voice rules; otherwise default to concise, friendly, plain language.
✋ **Show the draft and get a read on it.** Present the title and body in the chat (plain, readable —
not raw JSON) and ask:
> "Here's a first draft. Does this capture it? Want any changes to **tone**, **length**, or
> **messaging**?"
Iterate until the user is happy. Small, fast loops beat one giant rewrite. Only move on once they've
confirmed the copy is good.
> Note: image handling is intentionally out of scope for this skill. If the user asks for an image,
> tell them they can add it in the Builder after the draft is created, and continue.
---
## Phase 3 — Delivery settings
Only once the copy is finalized, gather the delivery details. Ask these as a short, natural
sequence — one topic at a time, not a wall of questions.
### 3a. Audience targeting
> "Should this go to **everyone**, or only a **specific set of users**?"
If they want to target, ask them to describe the audience in plain language ("paid plans only",
"companies on the EU region", "users who haven't completed onboarding"). Then translate it into a
`filter_condition` using the predicate DSL:
- Call `list_attribute_definitions` (and `list_event_definitions` / `list_segments` as needed) to
find the **real** attribute FQNs, event names, and segment IDs — never invent them.
- Build predicates per `references/mcp-reference.md` → *Targeting*.
- **Echo the interpreted audience back in plain English** and get a ✋ nod before treating it as
final. Data-type mismatches (string `"true"` vs boolean `true`) silently break targeting, so it's
worth confirming.
If they say everyone, leave `filter_condition` unset.
### 3b. Notification level (post type)
> "How prominent should it be — **Silent**, **Badge**, or **Boosted**? If boosted: **Pop-out**,
> **Modal**, or **Notification**?"
Map their answer to the `level` value (see the table in `references/mcp-reference.md`):
| User says | `level` |
|-----------|---------|
| Silent | `silent` |
| Badge (default) | `badge` |
| Boosted → Pop-out | `popout` |
| Boosted → Modal | `modal` |
| Boosted → Notification / Toast | `toast` |
Briefly explain any option the user seems unsure about (Badge = quiet unread counter; Boosted =
proactively pops up).
### 3c. Resource Center readiness (informational — never blocks)
Every announcement, **even Modal and Toast**, only actually displays if the account has a
**published Resource Center that contains an Announcements block**. Do a quick check with
`list_flows` (`types: "resource_center"`, `state: "published"`). If none is published, mention it as
a heads-up so the announcement doesn't quietly get zero views — but **do not block**; let the user
proceed if they want:
> "Heads-up: I don't see a published Resource Center with an Announcements block, which is what
> actually surfaces announcements to users. You can still create this now and sort that out
> separately — just flagging it."
Keep it to a single informational line. Don't nag or re-raise it.
---
## Phase 4 — Confirmation card
✋ Before creating anything, show a **confirmation card** summarizing the whole announcement, and ask
for a clear go-ahead.
Render it with the visualizer (`visualize:show_widget`) as a compact card if available — otherwise a
tidy formatted summary in chat is fine. Include:
- **Title** and a short **body preview**
- **Notification level** (in the user's words, e.g. "Boosted — Modal")
- **Audience** (plain-English, e.g. "Paid plans only" or "Everyone")
- **Environment**
- The Resource Center heads-up, if it applied
Then ask:
> "Ready for me to create this as a draft in Userflow?"
Wait for the yes.
---
## Phase 5 — Create the draft
On confirmation, create the announcement with `create_flow`:
- `name`: the announcement's internal name (usually the title)
- `type`: `"announcement"`
- `draft.announcement`: `{ title, content (rich2), level }`
- `filter_condition`: only if the user targeted an audience
- `env_id`: the resolved environment
See `references/mcp-reference.md` → *Creating the announcement* for the exact JSON shape and a
copy-ready template. The body must be a **rich2** document, not an HTML string.
`create_flow` returns a **Builder URL**. Give it to the user:
> "Done — here's your announcement draft: [link]. It's saved but not live yet."
---
## Phase 6 — Offer to publish
✋ Publishing is a live, user-facing action — always ask, never auto-publish.
> "Want me to publish it now, or would you rather review it in the Builder first?"
If they say publish, call `set_flow_publication` with `action: "publish"`. It uses a **two-step
confirm**: the first call (without `confirm: true`) returns a confirmation payload; call again with
`confirm: true` to apply. Pass the same `env_id`. See `references/mcp-reference.md` → *Publishing*.
If a Resource Center wasn't published (from Phase 3c), gently remind them once here that the
announcement may not display until that's set up.
If they'd rather review first, leave it as a draft and point them to the Builder link. Done.
---
## Guardrails
- **Never publish without an explicit yes.** Creating a draft is safe and reversible; publishing is
live. Keep them as two separate, confirmed steps.
- **Never invent** attribute FQNs, event names, segment IDs, or plan names — look them up.
- **Don't skip checkpoints.** The value of this skill is the pause-and-confirm rhythm; a great draft
published to the wrong audience is worse than a slightly slower flow.
- **Stay in scope.** Copy + level + audience + create + publish. Changelog/distribution and image
uploads are intentionally out of scope; if asked, note they can be handled in the Builder and move on.
- Keep the conversation light and human — you're a helpful teammate walking them through it, not a form.
Referenced files: 2
userflow-banner-creator7.87 KB
---
name: userflow-banner-creator
description: Create an in-app banner in Userflow through a guided, conversational flow — gather context from a short summary, pasted content, attached file, public page, or linked document/ticket in a connected app; draft and refine short banner copy; add an optional CTA; configure placement and behavior; optionally target users; show a confirmation card; create an unpublished draft through Userflow MCP; return the Builder link; and offer to publish. Use whenever a user with Userflow MCP connected asks to create or add an in-app banner, announce maintenance, a promotion, or an update in a page-top or page-bottom bar, or turn a note, ticket, or document into a Userflow banner. Requires the Userflow MCP connector.
---
# Userflow Banner Creator
Guide the user from a rough idea (or a linked doc/ticket) to a finished, ready-to-publish Userflow
**banner** — a bar embedded directly into their app's page. This is a **conversational, step-by-step**
skill: move through the phases in order and **pause at each ✋ checkpoint**. Never create or publish
without an explicit yes.
The core habit, same as any content-creation flow: **create is not publish**. `create_flow` saves an
unpublished draft and returns a Builder link; nothing is live until the user confirms and you call
`set_flow_publication`.
## How banners differ from announcements
Banners embed **directly into the page DOM**, so — unlike announcements — there is **no notification
level** (silent/badge/boosted) and **no Resource Center dependency**. The banner-specific choices are
**placement** (where it sits) and **behavior** (sticky / overlay / animate). Copy should be **short —
one line is ideal**.
## Before you start
1. Confirm the **Userflow MCP** is connected. If not, say so and stop.
2. Resolve the **environment** via `describe_session` (e.g. Production vs. Staging). One env → use it;
several → ask which. The banner *draft* is account-level, but you'll need the env for the
live-banner priority check and for publishing.
---
## Phase 1 — Gather the context
Ask for the source material, offering three ways:
> "What's the banner for? Give me a short summary, share a link to a doc or ticket with the context
> (Notion, Jira, a Google Doc, etc.), or paste the content in."
If they share a **link**, use the matching connected app for private content (for example Notion,
Atlassian for Jira/Confluence, or Google Drive), use browser or web access for a public page, and read
files attached to the current task directly. If the required app is unavailable or access fails, say
so and ask them to paste the relevant text. If they give a summary or pasted text, work from that.
Banners carry one short message and maybe one action — pull out the single thing users need to know
and any link/action they should take.
---
## Phase 2 — Draft and refine the copy
Write **short** banner copy — ideally one line. Lead with the point; cut everything else. If a
bundled Userflow brand-copy skill is available, follow its voice rules; otherwise use concise,
direct, friendly product copy and preserve any tone requirements the user provides.
✋ Show the draft (plain, readable — not JSON) and ask:
> "Here's the banner text. Good? Want changes to tone, length, or wording? And should it have a
> **button** — e.g. 'Learn more' linking somewhere, or a 'Dismiss' button?"
If they want a CTA, capture the button text and its action — most commonly **navigate** to a URL, but
also **start a flow**, **dismiss** the banner, track an event, or set an attribute. See
`references/mcp-reference.md` → *Buttons*. Iterate until the copy and button are right.
---
## Phase 3 — Placement and behavior
Banners always need a placement. **Always ask** (offer it as a dropdown of choices):
- **Top of page** → `embed_mode: "body_first"`
- **Bottom of page** → `embed_mode: "body_last"`
- **Anchor to a specific element** → hand off to the Builder (see below)
**Element-anchored placement is finished in the Builder, not here.** The MCP can't click to pick an
element on a live page, so if the user chooses element-anchored, create the draft with the copy and
settings you have and tell them to open the Builder link to position it against the element. Don't ask
for CSS selectors. Top/Bottom of page need no selector and work fully via MCP.
Then a couple of quick behavior questions (offer sensible defaults):
- **Sticky?** Stick to the top/bottom of the viewport while scrolling, or scroll away with the page
(`sticky`, default false).
- **Overlay or push?** Float over app content, or push the app's content down (`overlay`, default
false = push).
- Optional: animate on appear (`animate`, default true); allow users to dismiss with an X.
---
## Phase 4 — Audience targeting
> "Should this show to **everyone**, or only a **specific set of users**?"
If targeted, ask them to describe the audience in plain language, then build a `filter_condition` from
the predicate DSL — **resolve real attribute FQNs / event names first via `list_attribute_definitions`
/ `list_event_definitions`; never invent them** — and **echo the interpreted audience back in plain
English** for a ✋ nod. See `references/mcp-reference.md` → *Targeting*. If everyone, leave
`filter_condition` unset.
**Priority — only if other live banners exist.** Check `list_flows` (`types: "banner"`,
`state: "published"`, the chosen `env_id`). Only if that returns one or more, raise priority: at any
moment a user sees just one banner, and the highest-priority eligible one wins. Ask whether this banner
should take precedence over the existing one(s), set `priority` (1–5) accordingly, and note the final
ordering is visible in the Builder. If there are no other live banners, don't bring priority up at all.
---
## Phase 5 — Confirmation card
✋ Show a **readable confirmation card** (never raw predicate/draft JSON) and get a clear go-ahead.
Use an interactive confirmation card if that capability is available; otherwise use a clean text
table. Include:
- **Copy** and the **button** (label + what it does), if any
- **Placement** in plain words ("Top of page", or "Anchored — finish in Builder")
- **Behavior** — sticky / overlay / animate as on or off
- **Audience** — plain-English ("Everyone" or "Active EU companies")
- **Priority**, only if it came up
- **Environment**
Then: "Ready for me to create this banner as a draft?" — wait for the yes.
---
## Phase 6 — Create the draft
On confirmation, call `create_flow` with `type: "banner"` and the `draft.banner` payload (content as a
**rich2** document, buttons, `embed_mode`, `sticky`, `overlay`, `animate`, layout), plus
`filter_condition` if targeted and `priority` if it came up. See `references/mcp-reference.md` →
*Creating the banner* for the exact shape.
`create_flow` returns a **Builder URL**. Give it to the user:
> "Done — here's your banner draft: [link]. Saved, not live yet."
If placement was element-anchored, remind them to set the anchor position in the Builder before
publishing.
---
## Phase 7 — Offer to publish
✋ Never auto-publish.
> "Want me to publish it now, or review in the Builder first?"
If publish, call `set_flow_publication` (`action: "publish"`) — a **two-step confirm**: first call
without `confirm`, then again with `confirm: true`, passing the chosen `env_id`. See
`references/mcp-reference.md` → *Publishing*.
---
## Guardrails
- **Never publish without an explicit yes.** Create (draft) and publish (live) are separate confirmed
steps.
- **Never invent** attribute FQNs, event names, or values — look them up and echo the audience back.
- **Keep copy short.** A banner is one line, not a paragraph. Push back gently on wall-of-text copy.
- **Element-anchored → Builder.** Don't fabricate CSS selectors; hand off placement.
- **No raw JSON in the confirmation** — a readable card is what catches mistakes.
- Keep it conversational — a helpful teammate, not a form.
Referenced files: 2
userflow-flow-compare8.2 KB
---
name: userflow-flow-compare
description: Compare two Userflow flows of the same type side by side in an interactive dashboard — views, completions, completion rate, step-funnel drop-off, missing element errors, trends, and improvement insights. Use this skill whenever the user with the Userflow MCP connected asks to "compare flows", "compare these two flows/announcements/checklists", "which flow performs better", "flow A vs flow B", "benchmark my onboarding flows", or wants any head-to-head performance comparison of Userflow content. Also trigger when a picker widget from this skill sends a prompt like "Compare these two ... flows over ... Build the comparison dashboard". Requires the Userflow MCP connector.
---
# Userflow flow compare
Compare two flows of the same type over a chosen date range, producing an inline comparison dashboard with metrics, funnels, trends, and insights.
The interaction has two phases, usually across two turns:
1. **Picker phase** — fetch all flows, render an interactive picker (type → two searchable flow dropdowns → date range → Compare button).
2. **Dashboard phase** — triggered by the picker's resulting prompt (or by a user who names both
flows directly), pull analytics and render the comparison dashboard plus written insights.
If the user already named two flows and a range in their message, skip the picker and go straight to the dashboard phase (resolve names via `list_flows` with `flow_name` and verify both are the same type; if types differ, say so and re-render the picker pre-scoped so they can fix one or both).
## Setup (both phases)
1. Confirm the connected Userflow MCP exposes `list_flows`, `describe_session`, `query_flow_metrics`,
`query_usage_metrics`, and `get_flow_details`. If required analytics tools are unavailable, say so
and stop before promising a dashboard.
2. Call `describe_session` once to get `env_id`. Default to the Production environment; only ask the user if there are multiple non-obvious environments.
## Phase 1 — picker
1. Call `list_flows` with `list_all_flow_types: true`, `state: "published"`, `order_by: "edited_at"`, `order_dir: "desc"`. Keep `id`, `name`, `type`, and `first_published_at` for each flow (store `first_published_at` — you need it later for window-clipping warnings).
2. **Exclude** `tracker` (event trackers, no session funnel) and `assistant` (Adoption Agent has its own analytics) from the comparable set. Comparable types: `flow`, `checklist`, `announcement`, `launcher`, `banner`, `resource_center`.
3. Render a searchable interactive picker when that capability is available. Otherwise show a concise
text list grouped by type and ask the user to choose two flows plus a date range. Follow the picker
behavior in `references/dashboard-templates.md`:
- Flow type dropdown first, with per-type published counts. Changing type clears both selections.
- Two searchable dropdowns (text input + filtered list) scoped to the selected type — this makes a type mismatch impossible by design. A flow selected in one dropdown is hidden from the other.
- Date range chips: Last day, Last 1 week, Last 15 days, Last 1 month, Last quarter, Last 6 months, Last year. Default: Last 1 month.
- Keep the compare action disabled until both flows are chosen. The resulting prompt must include
both names, UUIDs, type, and selected range.
4. End the turn after rendering — the selection arrives as the next user message.
## Phase 2 — data pull
Map the range to `last_n_days`: day→1, 1 week→7, 15 days→15, 1 month→30, quarter→90, 6 months→180, year→365. Pick `interval`: `day` when ≤31 days, `week` when ≤180, `month` otherwise.
Make exactly these calls:
1. `query_flow_metrics` with `flows: [id1, id2]`, `env_id`, `last_n_days`, `include_time_series: true`, `interval`, and `include_steps: true` (steps only return for guide flows; harmless otherwise). **On a 408 timeout, retry once with identical parameters** — retries routinely succeed. If the retry also fails, tell the user the analytics endpoint is slow right now and offer a narrower range.
2. For funnel-bearing types only (`flow`, `checklist` — skip for announcements/banners/launchers/resource centers): `query_usage_metrics` with `event_name: "tooltip_target_missing"`, `group_by: ["event/flow_id"]`, same `last_n_days`, `limit: 100`. A flow absent from the grouped results has **zero** missing element errors — report 0, don't call again. Note this metric is flow-level, not step-level.
3. **Do not call `get_flow_analytics` or `get_flow_summary`.** Both are timeout-prone (observed 300s timeouts) and add nothing: worst drop-off is computable directly from the step funnel.
## Phase 2 — dashboard
Create **one self-contained HTML dashboard** in the current task's designated user-facing output
directory and return a clickable link. Choose the layout by flow type and follow the portable
dashboard contract in `references/dashboard-templates.md`:
**Guide flows / checklists** — legend, metric cards (views vs, unique viewers vs, completion rate vs, missing element errors vs), step funnel for each flow that has views (horizontal bars, per-step counts, step-over-step drop % in red when ≥50%, worst-drop bar highlighted red), daily/weekly views line chart for both flows, and optional follow-up controls (view sessions, try a different range).
**Announcements** — legend, metric cards (views vs, reactions vs, comments vs, engagement per 100 views vs — computed as (reactions+comments)/views×100, 1 decimal), views trend chart, and optional follow-up controls. No funnel, no completion rate, no missing-element card.
Chart conventions: Cove series colors (#2a78d6 for flow 1, #eb6834 for flow 2, dashed line for flow 2 so color isn't the only cue), custom HTML legend above the chart, `role="img"` + `aria-label` on canvases, sr-only summary heading first, round every displayed number. Trim leading all-zero periods from long trend charts and say so in the chart label.
## Insights (written prose after the artifact, never inside it)
Always give 2–4 insights. Derive them from these patterns, validated in dry runs:
- **Worst drop-off step**: report both the largest absolute view loss and the largest percentage drop between consecutive steps — they're often different steps and imply different fixes.
- **Goal placement artifact**: if completion rate is 0% but mid-funnel retention is strong, check whether the goal step sits after the real point of value; suggest moving the goal or strengthening the transition into the goal step, rather than assuming the whole flow fails.
- **Dormant flow**: a published flow with zero views isn't an error — look at its first step name and start conditions for chaining clues (e.g., a flow whose first step is "Navigate back to main" likely depends on another flow completing). Say what would revive it.
- **Flatline to zero**: a healthy series that drops to exactly zero and stays there mid-window signals an unpublish, expiry, or feed removal — not organic decay. Offer a `get_flow_details` follow-up button to check publication history.
- **Window clipping**: compare the chosen window against each flow's `first_published_at`. If the window starts after a flow's launch, warn that the launch spike is excluded and the comparison may mislead (a "no launch spike" conclusion from a clipped window is an artifact). Suggest a range that covers both launches.
- **Reach vs resonance**: for announcements, contrast total views against engagement per 100 views — broad targeting often wins reach while losing rate; say which goal (awareness vs activation) each pattern serves.
- **Element health**: zero `tooltip_target_missing` errors means drop-off is behavioral, not technical breakage — say so explicitly, it changes what the user should fix.
## Edge cases
- Both flows zero views: render the dashboard anyway (all zeros), lead insights with the dormancy analysis, and suggest a longer range.
- User provides a Userflow URL instead of a name: extract the UUID from the path and match against `list_flows` output.
- User's two flows are different types: name the mismatch plainly, then re-render the picker with both selections cleared so they can change one or both.
- More than ~250 flows in the account: cap each dropdown's visible list at 30 matches and rely on search.
Referenced files: 2
userflow-flow-segment-compare7.15 KB
---
name: userflow-flow-segment-compare
description: Compare how a single piece of Userflow content performs across several audience segments, rendered as a dashboard — a key-metrics comparison table plus trend charts. Works for ANY Userflow flow type (guide flows, announcements, banners, checklists, launchers, resource centers, embeds), not just flows and announcements. Content is chosen from a searchable dropdown; the "segments" are whatever the user wants to compare — existing account segments, ad-hoc filters built just for this analysis, or a mix — and ad-hoc ones are never saved to the account. Use whenever a user with the Userflow MCP connected wants to "compare a flow/announcement/banner across segments", "how does [content] perform for [group A] vs [group B]", "break down [content] by audience/user type", or any per-audience performance breakdown of one piece of content. Different from userflow-flow-compare (two flows head-to-head) — here it's ONE piece of content across MANY audiences. Requires the Userflow MCP connector.
---
# Userflow Content × Segment Compare
Take **one** piece of Userflow content — any flow type — and show how it performs across **several
audiences**, ending in a dashboard: a **comparison table** of key metrics and **trend charts** of
those metrics, one line per segment. Conversational and step-by-step — **pause at each ✋ checkpoint**.
Hold onto three things:
- **Any content type.** Guide flows, announcements, banners, checklists, launchers, resource centers,
assistants, trackers, embeds — all are "flows" with a `type` in Userflow. The metrics adapt to the
type (see `references/mcp-metrics.md`).
- **"Segment" is loose.** A real account segment, or an ad-hoc filter the user describes just for this
comparison. **Never create ad-hoc segments on the account** — they're query-time predicates only.
- **Read-only.** This skill only reads analytics; it writes nothing to Userflow.
## Before you start
1. Confirm the **Userflow MCP** is connected. If not, say so and stop.
2. Resolve the **environment** via `describe_session` (default to **Production** for analytics unless
told otherwise); pass its `env_id` on every analytics call.
---
## Phase 1 — Pick the content (searchable dropdown)
Don't make the user type an exact name. Fetch the content and let them **pick from a searchable
dropdown**.
1. Call `list_flows` broadly — `list_all_flow_types: true`, `state: "published"` (published content is
what has analytics), ordered by `edited_at` desc. Each item carries `name`, `type`, and `id`.
2. Render a **searchable dropdown picker** as an interactive widget (same pattern as the
`userflow-flow-compare` picker): a search box plus a filterable list of items, each showing the
**name** and a **type badge** (Flow / Announcement / Banner / Checklist / …). On selection, the
widget sends a prompt back to continue (e.g. "Analyze '<name>' [<id>] across segments"). If an
interactive widget can't render, fall back to a concise text list grouped by type for the user to
pick from.
3. **Capture the content type** from the chosen item — it decides the metric set. Confirm the resolved
name + type back to the user.
---
## Phase 2 — Which segments to compare?
Now ask what audiences to compare (aim for 2–5 for a readable dashboard). For **each** one, it's
either:
- **An existing account segment** — call `list_segments` (`subject_type: "user"`) and let the user
pick (a searchable/multi-select picker works well here too, or a simple list). Reference it as a
`{ "type": "segment", "segment_id": "<uuid>" }` predicate.
- **An ad-hoc filter** — the user describes it in plain language; you translate it into
attribute/event predicates. **Resolve real FQNs / event names first** (`list_attribute_definitions`,
`list_event_definitions`) — never invent them.
A mix of existing + ad-hoc is fine. Collect them all before moving on.
**One real constraint:** these analytics predicates are **user-scoped**, so existing segments you
reference must be **user** segments. A company-level idea (e.g. "EU companies") is still fine — express
it as a user predicate on a company attribute (`group/region = eu`); just don't pass a *company*
segment id. See `references/mcp-metrics.md` → *Scoping*.
---
## Phase 3 — Review the segments (before pulling any data)
✋ Show the assembled comparison set as a **readable card** (not JSON):
- The **content** being analyzed (name + type)
- Each **segment**: its label, and either "existing segment" or the ad-hoc conditions in plain English
(Field · Operator · Value)
- The **time window** and **interval** (propose a default: **last 90 days, weekly**; offer day/week/
month and a different range)
Ask: "Compare these against **[content]** over **[window]**? I can add, drop, or edit any segment."
Remind them ad-hoc segments won't be saved to the account. Iterate until they're happy.
---
## Phase 4 — Pull the metrics
For **each** segment, call `query_flow_metrics` on the single content id, scoped by that segment's
predicates, with the time series on:
```
query_flow_metrics(
flows: ["<content-id>"],
predicates: [ <that segment's predicates> ],
include_time_series: true,
interval: "<day|week|month>",
last_n_days: <n>, // or start_date/end_date
env_id: "<env>"
)
```
It returns the segment's `metrics` and a `time_data` array for trends, and works across content types.
**Read the metric keys actually returned and adapt** — completion-type content (guide flows,
checklists) leads with a completion rate; seen/engagement-type content (announcements, banners,
launchers, embeds, resource centers) leads with views and its primary engagement metric. See
`references/mcp-metrics.md` for the per-type guidance and zero-data handling. Collect one result per
segment.
---
## Phase 5 — Build the dashboard
Produce a **self-contained HTML dashboard** (a file artifact). Follow
`references/dashboard-spec.md` for the portable visual and interaction contract. At minimum:
1. **Header** — content name, type, time window, and the segments compared.
2. **Comparison table** — one row per segment, columns = the key metrics for this content type (chosen
from what `query_flow_metrics` returned). Make the best/worst per column easy to spot.
3. **Trend charts** — for each key metric, one multi-series line chart with **one line per segment**
over the shared time buckets.
Flag any low-sample or zero-data segment so a flat line isn't misread. Save it in the current task's
designated user-facing output directory, return a clickable link, then offer to iterate (add/drop a
segment, change window or metrics).
---
## Guardrails
- **Never create segments on the account.** Ad-hoc filters are query-time predicates only — say so
when reviewing them.
- **Never invent** attribute FQNs / event names / values — look them up and echo audiences back.
- **Match metrics to content type** — adapt to the returned metric keys; don't show completion rate for
a banner or reactions for a guide flow.
- **Don't mislead on thin data.** Flag low-sample or zero-data segments.
- **Read-only** — never publishes or writes anything.
- Keep it light; the dashboard is the deliverable, not a lecture.
Referenced files: 3
userflow-nps-summariser7.53 KB
--- name: userflow-nps-summariser description: Summarise the positive and negative comments from a Userflow NPS survey over a chosen time frame, with expandable user lists showing each respondent's comment and score. Use this skill whenever the user with the Userflow MCP connected asks to "summarise NPS", "summarise NPS feedback/comments", "what are people saying in our NPS", "NPS comment summary", "group NPS feedback", or anything about reading, digesting, or theming NPS survey responses. Also trigger when a widget from this skill sends a prompt like "Summarise NPS feedback for ... over ...". Requires the Userflow MCP connector. --- # Userflow NPS summariser Summarise what respondents wrote in an NPS survey — positive and negative comment themes with expandable per-user lists (comment + score). The output is deliberately comment-only: no NPS score card, no promoter/passive/detractor split, no trend chart. Interaction, usually across three turns: 1. **Link** — ask for the NPS flow's Userflow link, extract the flow ID, verify it's genuinely an NPS survey. 2. **Time frame** — render an interactive time-range picker when available, with a text fallback. 3. **Summary** — pull raw responses, join and classify, create a portable comment-summary report, and add written insights. If the user's first message already contains a link (or flow name) and a time frame, collapse the phases: verify, then go straight to the summary. ## Setup 1. Confirm the connected Userflow MCP exposes `list_flows`, `describe_session`, `list_flow_survey_questions`, and `list_survey_responses`. If required tools are unavailable, say so and stop before promising a report. 2. Call `describe_session` once for `env_id`. Default to Production; ask only if multiple non-obvious environments exist. ## Phase 1 — link and verification Userflow has **no `nps` flow type** — the `types` filter silently ignores the value and returns everything. NPS surveys are regular flows containing an NPS question block, and flow names lie in both directions (a flow named "Trial Prompt: NPS Survey" may contain zero questions; a survey may lack an NPS block). So never trust names; always verify. 1. Ask the user to paste the flow's link from the Userflow app (e.g. `https://app.userflow.com/app/<slug>/flows/<uuid>/builder`). Extract the UUID from the path. If they give a name instead, resolve it via `list_flows` with `flow_name` and confirm the match. 2. Call `list_flow_survey_questions` with the flow ID. Verify a question with `type: "nps"` exists. Capture: - the NPS question's `cvid` and `name` - every text-type question (`text`, `multiline_text`) — these are the comment sources; note their names (they reveal the flow's branching, e.g. separate "Passive feedback" and "Detractor feedback" questions) - whether any feedback question exists for promoters — many flows don't have one, which matters for the summary 3. If no `nps` question is found, tell the user plainly what the flow actually contains (its question types, or that it has none) and ask for a different link. Do not proceed on a name match alone. ## Phase 2 — time frame Render an interactive picker when available: show the verified flow name, choices for Last 1 week / 15 days / 1 month / quarter / 6 months / year (default: quarter), and a Summarise action whose resulting prompt includes the flow name, UUID, and chosen range. If interactive controls are unavailable, present the same ranges in text and ask the user to choose one. End the turn. ## Phase 3 — data pull and joining Map the range to a start date. **Both survey tools require full ISO 8601 datetimes** — bare dates like `2026-04-21` are rejected. Use `2026-04-21T00:00:00Z` / `2026-07-20T23:59:59Z` forms. 1. Call `list_survey_responses` with `flow_id`, `env_id`, `start_date`, `end_date`, `limit: 500`. Do **not** call `get_nps_breakdown` — the score summary is out of scope by design. 2. The result is one row per question per session. Join rows by `session_id`: - the row whose `question_cvid` matches the NPS question gives the score (`number_answer`, arrives as a string — parse it) - any text-question row in the same session gives the comment (`text_answer`) - empty-string text answers mean the user skipped the box — treat as no comment 3. If 500 rows come back, warn that the export may be truncated and offer a narrower range. ## Phase 3 — classification and summary Classify each **non-empty comment** by its sentiment, not by the score bucket. An 8-scorer complaining about pricing belongs in Negative; a 7-scorer praising the product belongs in Positive. Genuinely mixed comments go where their dominant substance points, with the full comment visible so the tension shows. Keep each row's score badge so readers can see sentiment and score diverge. Create one self-contained HTML report in the current task's designated user-facing output directory and return a clickable link: 1. sr-only summary heading with comment counts and the main themes. 2. Context line: flow name · range · "N comments from M responses". 3. Two `<details open>` accordions — **Positive** (`#348452` heading) and **Negative** (`#e34948` heading). Each contains: - a short thematic summary paragraph grouping comments into named themes with counts (e.g. "Pricing & AI limits (3): …") — bold theme labels, plain prose - the user list: rows of score badge (colored by score: ≥9 green `#348452`, 7–8 amber `#d97917`, ≤6 red `#e34948`), shortened user ID in monospace (first 8 chars + ellipsis), date, and the comment lightly paraphrased for length but preserving specifics 4. Optional follow-up controls for drafting a promoter feedback question or rerunning a longer range. Follow the portable report contract in `references/widget-templates.md`. Then write 2–3 insights as prose after the report (never inside it), drawing on: - **Theme clustering**: name the dominant complaint clusters and which is a product problem vs a commercial one — they imply different owners and fixes. - **The promoter blind spot**: if the flow has no promoter feedback question, say the positive column will stay near-empty by design and suggest adding a question — 40%+ of respondents may be scoring 9–10 with no way to say why. - **Timing clusters**: if several negative comments land in a short window, suggest checking what shipped or changed then. - **Specific, actionable bug reports** buried in comments (e.g. save behavior, preview rendering) deserve explicit mention — they're free QA. ## Known limitations (state honestly, don't work around) - `list_survey_responses` returns internal user UUIDs only. No current Userflow MCP tool resolves internal UUIDs to names or emails (`check_user_activity` and `list_users` search external IDs/names/emails only; `get_user_events` confirms existence but returns no identity). Display shortened IDs and, if the user asks who someone is, explain the limitation rather than guessing. - Comment classification is a judgment call on sentiment; when a comment is truly ambiguous, place it in Negative (complaints are costlier to miss) and keep the verbatim substance visible. ## Edge cases - Zero comments in the window: still render the report with both sections empty, state the response count, and lead insights with the flow's feedback-question structure (that's usually why). - All comments one polarity: render both sections anyway — an empty Positive section paired with the promoter-blind-spot insight is itself the finding. - Flow published but with responses predating the window: suggest a wider range in the insights when comment volume is thin (under ~5).
Referenced files: 2
userflow-segment-creator7.04 KB
---
name: userflow-segment-creator
description: Create a condition (filter-based) segment in Userflow through a guided, conversational flow — pick user vs. company, describe the audience in plain language, translate it into real attribute/event predicates (looked up, never invented), show the conditions in a simple inline card for confirmation, name it, and create it via the Userflow MCP. Use this whenever a user with the Userflow MCP connected wants to "create a segment", "build an audience", "make a user/company segment", "segment users who…", "define a group of users/companies by conditions", or filter their audience by attributes or behavior. Requires the Userflow MCP connector. Note — the MCP only creates condition segments; manual/list (CSV-uploaded) segments are not supported and must be imported from the Userflow dashboard.
---
# Userflow Segment Creator
Guide the user from a plain-language audience description to a live **condition segment** in Userflow.
This is a **conversational, step-by-step** skill: move through the phases in order and **pause at each
✋ checkpoint**. Never create the segment until the user has seen the conditions and said yes.
## Scope (read first)
The Userflow MCP's `create_or_update_segment` creates **condition (filter) segments only** — segments
defined by attribute/event rules that evaluate membership automatically. It **cannot** create
**manual/list segments** (a fixed set of users uploaded from a file); there is no MCP tool to import
members or set attributes. If the user wants a manual/CSV-based segment, say so plainly and point them
to the Userflow dashboard's CSV import (or the REST Identify API) — then offer to help with a condition
segment instead. Don't try to fake it with a giant list of OR'd equals; that hits the nesting budget
and isn't what they want.
## Before you start
Confirm the **Userflow MCP** is connected (its tools are available). If not, tell the user this skill
needs the Userflow connector and stop. Segments are account-level, so no environment needs to be
chosen to create one (an optional match-count preview later is per-environment — handle that then).
---
## Phase 1 — User or company segment?
Ask up front, because it decides which attributes are even valid:
> "Is this a **user** segment or a **company** segment?"
This sets `subject_type` (`"user"` or `"company"`) and constrains predicates — see
`references/mcp-reference.md` → *Subject-type scoping*. In short: a **company** segment can only use
company attributes (`group/…`); a **user** segment can use user attributes, company attributes, and
company-membership attributes.
---
## Phase 2 — Describe the conditions
Ask the user to describe the audience in plain language:
> "Describe who should be in it — e.g. 'companies on an active subscription in the EU', or 'users who
> haven't completed onboarding and were last seen over 30 days ago'."
Then translate it into predicates. **Resolve real identifiers first — never invent them:**
- `list_attribute_definitions` (scope matching the subject type) → exact attribute FQNs and their
`data_type`. Company attributes use the `group/` prefix.
- `list_event_definitions` → valid `event_name` values, if the description involves behavior.
- Build the predicate array per `references/mcp-reference.md` → *Building the conditions*.
Two things that silently break segments, so get them right:
- **Data types.** String `"true"` ≠ boolean `true`; a number stored as text won't match a numeric
comparison. Match the attribute's real `data_type`.
- **No nested segment references.** `create_or_update_segment` rejects `type: "segment"` predicates
anywhere in the tree. If the user says "everyone in segment X plus …", you can't nest X — expand the
intent into attribute/event rules, or tell them that part can't be combined this way.
If the description is ambiguous ("active" = subscribed, or recently seen?), ask one short clarifying
question rather than guessing.
---
## Phase 3 — Show the conditions and confirm
✋ Render the conditions as a **simple, human-readable card** so the user can eyeball them before
anything is created. Use an interactive card if that capability is available; otherwise use a clean
text table. The card should show:
- **Subject type** (User segment / Company segment)
- A **plain-English restatement** ("Companies with an active subscription AND region = EU")
- The **conditions in readable form** — one row per rule as **Field · Operator · Value**, using the
attribute's friendly **display name** (e.g. "Subscription State", "Page Viewed"), a plain operator
("is", "is not", "fewer than", "more than", "in the last 30 days"), and the actual value — grouped
by AND / OR. For event rules, spell out the count, window, and actor in words (e.g. "fewer than 10
times, across all team members, in the last 30 days").
**Do not show raw predicate JSON to the user.** The JSON is what you send to the tool, not what the
user reviews — a table of Field / Operator / Value is far easier to sanity-check and is what catches
wrong data types or values. Keep the JSON to yourself.
Then ask:
> "Does this match who you have in mind? I can adjust any rule."
Iterate until they're happy. Small edits are cheap — re-render the card each time.
**Optional match preview.** Offering a rough count helps them trust the filter. If they want it, run a
read-only `list_users` (or `list_companies`) with the same predicates in their chosen environment
(default Production) and report the approximate number of matches. Keep it optional and non-blocking —
skip it if they'd rather just proceed.
---
## Phase 4 — Name it
Once the conditions are confirmed:
> "What should I name this segment?"
Suggest a descriptive default from the conditions if they're unsure (e.g. "Active EU companies").
---
## Phase 5 — Confirm and create
✋ One final check before writing:
> "Ready for me to create the **[User/Company] segment '[name]'** with these conditions?"
On yes, call `create_or_update_segment` with `subject_type`, `name`, and `predicates` (omit
`segment_id` to create new). See `references/mcp-reference.md` → *Creating the segment*.
Report back the created segment (name + id) and that it's now live in their segment list, evaluating
membership automatically. Because it's condition-based, membership updates on its own as users/companies
change — no manual upkeep.
---
## Guardrails
- **Never invent** attribute FQNs, event names, or values — look them up, and echo the audience back in
plain English before creating.
- **Respect subject-type scoping** — don't put user-scoped attributes on a company segment.
- **No nested segment predicates** — attribute / event / not_event / clauses only.
- **Condition segments only** — if they need a manual/list segment, point them to the dashboard importer
rather than forcing it.
- **Don't skip the confirmation card.** A segment with a subtly wrong data type matches the wrong people
(or no one); the eyeball step is the whole point.
- Keep it conversational — you're walking a teammate through it, not making them fill in a form.
Referenced files: 2
Technical details
- First seen
- Sep 30, 2026 · 22:02 UTC
- Last seen
- Oct 1, 2026 · 12:00 UTC
- Collection status
- Collected
plugin_asdk_app_6a42b1a21e3c8191a436847ae17e527f
Download listing JSON