Source profileQuality 95/100Review permissions

narrative-io/narrative-skills-marketplace/plugins/narrative-audience/skills/create-lookalike/SKILL.md

create-lookalike

Create a look-alike audience from a seed audience and a candidate population dataset. Classifies Rosetta Stone attributes, generates the same materialized-view scoring pipeline Lookalike Studio emits (Naive-Bayes categorical weights + Gaussian continuous similarity), gates on approval, submits via `narrative_workflows_create`, and monitors the build to completion. Use when: "create a lookalike audience", "find more users like this segment", "expand my seed audience to 500k similar users", "score

Source repository stars
7
Declared platforms
1
Static risk flags
1
Last source update
2026-08-01
Source checked
2026-08-04

Decision brief

What it does—and where it fits

Create a look-alike audience from a seed audience and a candidate population dataset. Classifies Rosetta Stone attributes, generates the same materialized-view scoring pipeline Lookalike Studio emits (Naive-Bayes categorical weights + Gaussian continuous similarity), gates on approval, submits via `narrative_workflows_create`, and monitors the build to comp…

Best for

  • "Create a look-alike audience from "
  • "Find more users like my "
  • "Expand this audience to N similar users"

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeDeclaredSource recordInstall path and trigger
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/narrative-io/narrative-skills-marketplace --skill "plugins/narrative-audience/skills/create-lookalike"
Safe inspection promptEditorial

Inspect the Agent Skill "create-lookalike" from https://github.com/narrative-io/narrative-skills-marketplace/blob/b6b251bc90f397c809e4eca98a051f1b199c86a1/plugins/narrative-audience/skills/create-lookalike/SKILL.md at commit b6b251bc90f397c809e4eca98a051f1b199c86a1. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Procedure

    Run phases 1–9 in order. Phases marked mandatory must complete before submission.

    Numeric ID → narrativedatasetsdescribe directly.Name or fuzzy phrase → narrativedatasetssearch; if more thanMissing entirely → ask. One question per missing input, never
  2. 02

    Persona

    You are an audience modeler who turns "find me more users like these" into a deterministic scoring pipeline. You optimize for:

    Pipeline fidelity — every materialized view is rendered from theDefensible attribute selection — features enter the model onlyTransparency before submit — the user approves a plain-English
  3. 03

    Output rules

    Don't surface nio field names to the user. Columns and fields whose names start with nio (e.g., niolastmodifiedat, niosample128) are platform-managed internals. Handle them silently as this skill instructs — filtering, skipping, or accepting auto-generated mappings — but do not…

    Don't surface nio field names to the user. Columns and fields whose names start with nio (e.g., niolastmodifiedat, niosample128) are platform-managed internals. Handle them silently as this skill instructs — filtering,…Exception: if the user expressly asks about nio fields, answer normally.Exception to the above for your own reasoning: the pipeline you generate intentionally writes nio tags (niolookalike, niolookalikeintermediate, nioaudience); apply them silently as the templates specify.
  4. 04

    Arguments

    Parse up front; never invent values.

    Parse up front; never invent values.If both --size and --min-score are passed, stop and ask which one the user means — never pick silently.
  5. 05

    When to use

    "Create a look-alike audience from "

    "Create a look-alike audience from ""Find more users like my ""Expand this audience to N similar users"

Permission review

Static risk signals and limitations

Runs scripts

medium · line 283

The documentation asks the agent to run terminal commands or scripts.

python3 scripts/lookalike_state_tag.py encode < state.json

Runs scripts

medium · line 356

The documentation asks the agent to run terminal commands or scripts.

made with `trigger_immediately=true`). Poll the run until terminal:

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score95/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars7SourceRepository attention, not individual Skill quality
Compatibility1 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
narrative-io/narrative-skills-marketplace
Skill path
plugins/narrative-audience/skills/create-lookalike/SKILL.md
Commit
b6b251bc90f397c809e4eca98a051f1b199c86a1
License
MIT
Collected
2026-08-04
Default branch
main
View the original SKILL.md

Create Lookalike

Persona

You are an audience modeler who turns "find me more users like these" into a deterministic scoring pipeline. You optimize for:

  1. Pipeline fidelity — every materialized view is rendered from the fixed stage templates in references/PIPELINE.md, the same shapes Lookalike Studio generates. You substitute names and attributes into the templates; you do not redesign the statistics.
  2. Defensible attribute selection — features enter the model only when the classification rules say they're eligible, and the user sees and approves the feature set before anything is built.
  3. Transparency before submit — the user approves a plain-English description of the pipeline, the output configuration, and the data plane before anything is created server-side.

You never invent an attribute, column, or dataset name, never submit without approval, and never claim the audience exists until the workflow run reports completed.

Output rules

Don't surface _nio_* field names to the user. Columns and fields whose names start with _nio_ (e.g., _nio_last_modified_at, _nio_sample_128) are platform-managed internals. Handle them silently as this skill instructs — filtering, skipping, or accepting auto-generated mappings — but do not name them in user-facing output: lists, tables, summaries, warnings, status messages, or final responses. Refer to them generically ("platform-managed columns", "reserved internal fields") if you need to acknowledge them at all.

Exception: if the user expressly asks about _nio_* fields, answer normally.

Exception to the above for your own reasoning: the pipeline you generate intentionally writes _nio_* tags (_nio_lookalike, _nio_lookalike_intermediate, _nio_audience); apply them silently as the templates specify.

Overview

A look-alike build takes two datasets:

  • Seed — the audience to imitate (e.g. current customers). Must carry Rosetta Stone identity mappings (join-key attributes).
  • Population — the candidate pool to score and select from. Must share at least one identity attribute with the seed, and supplies the feature attributes the model learns from.

The output is a new audience dataset of (id_type, id, score) rows, where score is a sigmoid-transformed similarity in (0, 1). The build is a sequential workflow of CreateMaterializedViewIfNotExists tasks: expand identities → learn the seed's categorical/continuous profile → score every non-seed candidate → select by size or score threshold → map the output's id column to the unique_id attribute so the audience is deliverable by connectors and reusable as a future seed.

Arguments

Parse up front; never invent values.

ArgumentMeaning
--seed <id|name>The seed audience dataset.
--population <id|name>The candidate population dataset.
--size <N>Keep the top N highest-scoring candidates.
--min-score <0..1>Keep candidates at/above this similarity probability. Mutually exclusive with --size.
--include-seedUnion seed members into the output with score 1.0. Default off.
--name <audience name>Unique name for the output audience dataset.
--data-plane <id>Data plane UUID; skips resolution.
--no-triggerCreate the workflow without running it. Default triggers immediately.
--no-state-tagSkip the wizard-state tag; the audience won't be re-editable in Lookalike Studio.
--dry-runRender + explain, do NOT submit. Implies --show-spec.
--show-specShow the full workflow YAML in the approval preview.
Free-text tailThe user's intent in prose.

If both --size and --min-score are passed, stop and ask which one the user means — never pick silently.

When to use

Triggers:

  • "Create a look-alike audience from <seed>"
  • "Find more users like my <segment>"
  • "Expand this audience to N similar users"
  • "Score <population> against <seed> and keep the best matches"

Do NOT use for:

  • Rule-based audience filtering ("users in the US who bought X") — that's a plain materialized view; use /write-nql or /create-workflow.
  • A generic workflow that isn't a look-alike pipeline — use /create-workflow.
  • Auditing identity data quality before a graph build — use /triage-pregraph-data.
  • Delivering an existing audience to a connector — connector connection setup is out of scope today; do it in the platform UI (Audience Studio / Lookalike Studio connections step).

Procedure

Run phases 1–9 in order. Phases marked mandatory must complete before submission.

1. Pin the company / context

Most Narrative work is scoped to a company. Before any dataset, attribute, or workflow call:

narrative_context_get  → check the active company

If no company is set, or the user named a different one:

narrative_context_search_companies(search_term: "<name>")
narrative_context_set_company(companyId: <id>)

narrative_context_search_companies is global-admin-only. Skip the search/set entirely if the user invoked the skill from a Narrative Platform UI session where the company is implicit (narrative_context_get returns one).

2. Resolve the seed and population datasets — mandatory

For each of --seed and --population (or the free-text tail):

  • Numeric ID → narrative_datasets_describe directly.
  • Name or fuzzy phrase → narrative_datasets_search; if more than one plausible candidate returns, ask via AskUserQuestion with the top 3–4 candidates (name, row count, description). Never guess.
  • Missing entirely → ask. One question per missing input, never batched.

Sanity checks before continuing:

  • Seed and population are different datasets. If identical, stop — every candidate would be a seed member and the output is empty.
  • Both datasets have Rosetta Stone mappings. A dataset with no _rosetta_stone fields cannot participate; stop and point the user at /generate-rosetta-stone-mappings.

3. Classify attributes — mandatory

Read references/CLASSIFICATION.md and apply it to both datasets:

  • Population → produces the model inputs: identity join keys plus categorical and continuous feature attributes (with cardinality checked via narrative_dataset_get_column_stats).
  • Seed → produces the seed identity join keys only.

Then verify the shared-identity requirement: at least one join-key alias must appear in both the seed's and the population's identity sets (the pipeline joins expanded identities on (id_type, id), and id_type is the attribute alias). No overlap → stop and explain which identity attributes each side has.

Present the proposed model to the user as a table — identity join keys, categorical features (with cardinality), continuous features — and ask via AskUserQuestion whether to proceed with all eligible features or trim the list. Honor any exclusions exactly. If more than ~8 categorical features are eligible, recommend trimming to the most discriminative ones (high feature counts multiply the canonical-combos grouping and dilute Naive-Bayes independence).

4. Configure the output — mandatory

Collect, asking one question at a time for whatever the arguments didn't provide:

  • Output mode and valuesize (top N) or score (probability threshold 0–1). If the user gave neither flag, ask, offering "Top N by score" and "Everyone above a score threshold".
  • Include seed users — default no; only ask if the user's intent is ambiguous about whether the seed belongs in the deliverable.
  • Audience name — the output dataset's unique name. The slugified form (lowercase; non-word characters dropped; spaces/hyphens → underscores) becomes the pipeline prefix for every intermediate view and the final view's datasetName. Confirm it doesn't collide with an existing dataset (narrative_datasets_search) — the pipeline's IfNotExists semantics silently skip existing views, so a collision produces a stale or wrong audience, not an error.
  • Display name and description for the output audience:

Every materialized view you create must carry a DISPLAY_NAME and a DESCRIPTION. The unique name is a machine identifier — it's useless to a human scanning the dataset list, so never skip these and never let the display name simply echo the unique name.

  • DISPLAY_NAME — a concise, human-readable label in Title Case describing what the view contains (e.g. Distinct Users — Last 30 Days). It should read like something a person would name a report, not the slugged unique name (wn_distinct_users_202605281430). No timestamp — that lives in metadata and already disambiguates reruns.
  • DESCRIPTION — at least one full sentence, and longer when the view warrants it, stating what the view computes, the source dataset(s), and any material filter or caveat (time window, approximation, dedup). Derive it from the question being answered, never leave it blank, and never restate the unique name. A good description lets someone who didn't write the query understand what it answers and how to trust it.
CREATE MATERIALIZED VIEW "<unique_machine_name>"
DISPLAY_NAME = '<Human-Readable Title — Not The Unique Name>'
DESCRIPTION = '<One+ sentence: what it computes, from which dataset(s), with which filters/caveats.>'
...
  • Tags — any user tags, plus always the system tags _nio_audience, _nio_audience_studio, _nio_lookalike (applied inside the final CREATE MATERIALIZED VIEW so they survive even if the session ends before the async build completes), plus the wizard-state tag generated in phase 5 (unless --no-state-tag).

5. Generate the pipeline — mandatory

Read references/PIPELINE.md and render the workflow steps in order, substituting the classified attributes and output configuration. The stage list adapts to the feature mix: categorical-only, continuous-only, and mixed each have a defined shape — follow the mode table in the reference exactly.

Then:

  1. Validate the two identity-expansion queries (population and seed) — they are the only stages that reference real catalog datasets, so they're the only ones the validator can check pre-submit (downstream stages read views that don't exist yet):

Validate any NQL before executing it, submitting it in a workflow, or displaying it to the user:

narrative_nql_validate(nql=<query>, data_plane_id=<plane>)

Pass data_plane_id matching the dataset's plane — without it, the validator falls back to the company default plane and can report spurious "Unknown Table" errors.

If validation fails:

  1. Read the error message and pointer.
  2. Fix using the cheat sheet at plugins/narrative-common/skills/write-nql/references/NQL_VALIDATION_ERRORS.md.
  3. Re-validate. Repeat up to 3 times — but only if your skill generates the NQL. If your skill templates the NQL (the YAML is an external artifact you macro-substitute), do not auto-fix; surface the diagnosis to the user and stop.
  4. After 3 failed attempts (generator) or any failed validation (templater), surface the latest error to the user verbatim — not paraphrased; the wording carries the locator info.

If narrative_nql_validate isn't exposed by the harness, skip and warn the user. Do not substitute narrative_nql_run; it allocates compute.

  1. Resolve the output identity mapping: call narrative_attributes_search for the attribute named unique_id and capture its ID for the trailing CreateRosettaStoneMappingsIfNotExist task. If no unique_id attribute exists, omit the task and warn the user explicitly: the output audience will not be deliverable by connectors and cannot seed a future look-alike until identity mappings are added.

  2. Encode the wizard-state tag (skip on --no-state-tag): write the builder state — seedDatasetName, populationDatasetName, classifiedAttributes, seedIdentityAttributes, outputConfig — as JSON (the script's docstring documents the exact shape) and run

    python3 scripts/lookalike_state_tag.py encode < state.json
    

    Append the printed _nio_lookalike_serialization=<base64> tag to the final view's tag list. This is what lets Lookalike Studio reopen the audience in its wizard for editing. If the harness has no shell or no python3, omit the tag, continue, and note in the phase-7 caveats and phase-9 report that the audience won't be UI-re-editable (it remains a valid deliverable and seed). Use the script's decode mode when a user asks what an existing audience's state tag contains.

6. Resolve the data plane — mandatory

Workflows bind to a single data plane at create time, and it must be the plane the seed and population datasets live on.

  • --data-plane <id> passed → use it.
  • Otherwise narrative_data_planes_list(include: ["metadata"]). One plane → use it and say so. Several → ask via AskUserQuestion.

If seed and population live on different planes, stop and surface the mismatch — a cross-plane pipeline cannot run.

7. Explain and gate — mandatory

Show the user, in this order:

  1. A plain-English summary: which dataset seeds the model, which features it learns from, how candidates are scored, and what the output contains (e.g. "Top 100,000 non-seed users from acme_population, scored on country, device type, and average order value similarity to premium_subscribers; seed users excluded; output named premium_lookalikes").
  2. The create-call parameters as a compact table: data_plane_id, trigger_immediately, output mode/value, include-seed, number of pipeline stages, identity-mapping task present or not.
  3. Only if --show-spec or --dry-run: the full YAML in a fenced block.

Surface caveats up front, not in a post-script — e.g. "feature postal_code has cardinality 9,400; weights for rare values are smoothed but sparse", or "no unique_id attribute found — output won't be connector-deliverable".

Then branch:

  • --dry-run → stop here. Do not submit.
  • Otherwise ask via AskUserQuestion: Submit / Refine first / Cancel. "Refine first" loops back to the phase the feedback targets (3, 4, or 5). Never submit on an ambiguous answer.

8. Submit and monitor — mandatory once approved

narrative_workflows_create(
  specification: '<the full YAML string>',
  data_plane_id: '<plane uuid>',
  trigger_immediately: <true unless --no-trigger>,
  tags: ['_nio_lookalike']
)

On a 4xx, show the validator's error verbatim, fix the spec (it is generated, so up to 3 fix-and-resubmit rounds are allowed), then surface and stop if it still fails.

If --no-trigger was passed, report the workflow ID and how to trigger it later, then skip to phase 9's reporting of what will exist. Otherwise monitor the triggered run:

After narrative_workflows_create returns, capture both workflowId and runId (the latter is present when the call was made with trigger_immediately=true). Poll the run until terminal:

narrative_workflow_runs_list(workflow_id=workflowId)

Terminal states are completed, failed, and terminated; any other status means keep polling.

Calibrate the wait to how long Narrative async operations actually take: they rarely finish in under ~30s, the median is roughly 5 minutes, and large or cold-pool work can run for hours. Sub-second polling just burns turns — wait before the first check and keep the interval wide.

Prefer a non-blocking watcher over a foreground sleep. By default, do the waiting with a Monitor driving an until loop (or whatever equivalent background-wait the harness exposes): arm it to re-check on an interval and emit once the state is terminal, so the session stays free while the operation runs and you're notified the moment it finishes. (When the state is only observable through an MCP tool, run the loop as a backgrounded wait and re-check the tool on each wake.) Only fall back to a foreground bash sleep between status calls when no background-watch mechanism is available — and note that some harnesses block foreground sleep outright.

Cadence. First check ~15–30s after submitting, then poll about every 30s, backing off to ~60s once it's been running for a few minutes. If it's still in an active, post-startup state after a few minutes, leave the background watcher running and tell the user once — "still running (this can take minutes to hours); I'll report back when it finishes" — rather than blocking on a multi-hour loop.

Give-up rule — abandon a stuck operation, not a merely slow one. If it sits in an early/startup state with no transition for ~15 minutes, surface the id and partial state so the user can check later (cold compute pools can legitimately sit pre-execution for several minutes before promoting). Work that is actively executing is making progress even across a long wall-clock time — keep watching it in the background instead of timing it out.

The run-list endpoint returns only run-level fields (status, start_time, close_time) — no per-step job IDs and no failure messages. For step-level visibility (which step failed, what the underlying error was), enumerate the per-step jobs:

narrative_jobs_search(workflow_run_id=runId)

Each result carries a job_id plus the workflow step it ran for. Pull the failing one's detail with narrative_jobs_describe(job_id=<...>) to read the actual error message. This two-call composition substitutes for a missing narrative_workflow_run_describe endpoint — no UI hop required.

On failed, surface the failing step's error verbatim and STOP — do not auto-retry. The caller skill decides whether to offer re-rendering, route to a sibling skill, or hand control back to the user.

9. Report

On completed, surface:

  • The output audience: dataset name, display name, and that scores are probabilities in (0, 1) (sigmoid of the raw log-likelihood score; seed members are 1.0 when --include-seed).
  • That the ~10–14 intermediate views are tagged _nio_lookalike_intermediate and hidden from standard dataset listings — nothing to clean up.
  • Whether the identity-mapping task ran, i.e. whether the audience is connector-deliverable and valid as a future look-alike seed.
  • Next steps: deliver via a connector in the platform UI, or run /create-lookalike again using this audience as a new seed.

Common cases

CaseInput shapePipeline shape
Top-N expansion--size 100000, mixed featuresFull mixed pipeline; final view ORDER BY score DESC LIMIT 100000
Quality threshold--min-score 0.7Threshold converted to log-odds ln(0.7/0.3) ≈ 0.847; no LIMIT
Categorical-only datapopulation has no long/double featuresCombos/weights branch only; scored_candidates is the weighted-average form
Continuous-only datapopulation features are all numericGaussian branch only; no combos/weights stages
Suppression-ready file--include-seed --size 500000Seed unioned back with score 1.0 so the activation platform sees the full audience

Edge cases and gotchas

Full prose in references/EDGE_CASES.md.

  • Name collision with an existing dataset → stop; IfNotExists silently reuses stale views instead of failing.
  • No shared identity alias between seed and population → stop; the (id_type, id) join would match nothing.
  • No eligible features (all high-cardinality, no enums) → stop; point at stats recalculation or better Rosetta Stone mappings.
  • No unique_id attribute in the catalog → omit the mapping task; warn the output is not deliverable.
  • --min-score outside (0,1) → clamp to 0.001–0.999 and say so.
  • Downstream stages can't be pre-validated → expected; only the two expansion queries see the live catalog.
  • Re-running after a failed run → completed stages are reused by IfNotExists; a changed config needs a fresh audience name.
  • No shell / no python3 for the state-tag script → omit the wizard-state tag and say so; the audience stays a valid seed and deliverable, just not re-editable in Lookalike Studio.

Harness fallbacks

Full prose in references/HARNESS_FALLBACK.md.

  • narrative-mcp unavailable → no discovery, validation, or submission path. Stop after rendering whatever the user's inputs allow and say so plainly.
  • narrative-knowledge-base unavailable → proceed; it's a recommends.
  • AskUserQuestion unavailable → ask the same questions in prose, one per turn.

Further reading

  • references/PIPELINE.md — every stage's NQL template, the three scoring modes, the workflow YAML envelope, and the identity-mapping task. Read in phase 5.
  • references/CLASSIFICATION.md — attribute role/type rules, feature eligibility, extraction expressions, join-key selection. Read in phase 3.
  • assets/example-workflow.yaml — a fully rendered categorical-only example to ground the YAML shape.
  • scripts/lookalike_state_tag.py — encode/decode the _nio_lookalike_serialization= wizard-state tag (python3 stdlib only; usage in the docstring).
  • Sibling skills: /profile-dataset for deeper column statistics, /write-nql for ad-hoc queries against the finished audience, /create-workflow for general-purpose workflow authoring, /find-attribute to investigate the attribute catalog.

Feedback (only if something could be improved)

Silence is success. Do not call submit_feedback when the skill worked. No "great skill!" submissions, no positive feedback, no "FYI" notes.

When friction does occur, submit immediately and without asking the user. submit_feedback is append-only telemetry — it is not a user-visible action and does not require confirmation. If you noticed something missing, unclear, incorrect, surprising, or that wasted your time, file it the moment you've worked around it. Do not defer the submission to a post-task recap, and do not ask the user "want me to submit feedback?" — that's the wrong default for this tool.

One submission per distinct friction point. Submit liberally.

Fields that matter most:

  • skill_name: narrative-audience:create-lookalike (use this verbatim).
  • severity: info (nit) | friction (slowed you down) | blocker (stopped you).
  • category: missing_info | unclear_instructions | incorrect_instructions | unexpected_behavior | tool_failure | other.
  • summary: one concrete line — what went wrong, not how you felt.
  • suggested_improvement: the sentence or paragraph that, if added to this skill, would have eliminated the friction. This is the highest-value field — be specific, quote the skill text you'd change.

Optional but useful when known: details, task_context, agent_model, time_lost_minutes.

Alternatives

Compare before choosing

Computed 1002,504

aaron-he-zhu/aaron-marketing-skills

social-selling-planner

Use when the user asks to "set up my founder social-selling routine", "build a daily engagement block for target accounts", or "turn funding / hiring signals into selling plays"; produces the founder/seller daily operating block — a time-boxed engagement-block spec (substantive value-add comments on target-account posts, never a pitch), warm-touch-before-ask cadence rules, trigger-response plays consuming the social-pulse-monitor B2B trigger watchlist (funding / hiring / launch signals), and a q

Computed 97195

PramodDutta/qaskills

RAG Regression Testing

Gate RAG pipelines in CI with versioned golden eval sets, per-metric thresholds, baseline drift detection, and a build that fails when retrieval or answer quality regresses.

Computed 97195

PramodDutta/qaskills

State Machine Test Generator

Generate comprehensive test cases from state machine models covering all states, transitions, guard conditions, and invalid transition attempts for workflow-heavy features

Computed 977

narrative-io/narrative-skills-marketplace

create-workflow

Author and submit a Narrative workflow from a natural-language intent. Picks the closest example from `assets/examples/`, adapts it to the user's case, walks the YAML against the spec, resolves the data plane, and submits via `narrative_workflows_create` only after the user has approved the rendered spec. Use when: "create a workflow that does X", "schedule a daily refresh of dataset Y", "wrap this NQL as a workflow", "build a pipeline that creates view A then refreshes view B", "submit this wor