PluginBench
Skill
Pass
Audit score 90

cargo-segmentation

getcargohq/cargo-skills

Define and use named filters (segments) over Cargo models as audiences for batch runs, plays, and exports.

What is cargo-segmentation?

Segments are saved filters over a Cargo model that define which records you mean. Use them to create reusable audiences for batch operations, play triggers, exports, and change tracking. This skill handles segment CRUD, filtering, counting, and fetching records.

  • Create, read, update, and delete named segments with saved filters
  • Count records matching a filter without saving the segment
  • Fetch or download records matching a segment or inline filter
  • Track changes to a segment between syncs (added, updated, removed, unchanged)
  • Define tracking columns so value changes register as updates, not just adds/removes

How to install cargo-segmentation

npx skills add https://github.com/getcargohq/cargo-skills --skill cargo-segmentation
Prerequisites
  • @cargo-ai/cli installed globally or via npx
  • Signed in with `cargo-ai login --email`, `--oauth`, or `--token`
  • Access to a Cargo workspace with at least one model
Claude Code
Cursor
Windsurf
Cline

How to use cargo-segmentation

  1. 1.Run `cargo-ai storage model list` to find the modelUuid you want to segment
  2. 2.Run `cargo-ai storage column list --model-uuid <uuid>` to see available column slugs for filtering
  3. 3.Test your filter with `cargo-ai segmentation segment fetch --model-uuid <uuid> --filter '<json>' --limit 1` to count matches before committing
  4. 4.Create the segment with `cargo-ai segmentation segment create --name "<name>" --model-uuid <uuid> --filter '<json>'`
  5. 5.Reference the saved segment in batch runs, plays, or exports by its uuid or slug

Use cases

Good for
  • Build a segment of companies with >100 employees, then run a batch campaign against it
  • Filter contacts by criteria (e.g., 'everyone who has not been emailed') and save as a reusable list
  • Count how many records match a condition before proposing a paid operation
  • Export a segment's full dataset via signed URL for use in another tool
  • Monitor when new records enter a saved segment and trigger downstream actions
Who it's for
  • Sales and marketing operations teams managing audience definitions
  • Data analysts building reusable filters for recurring campaigns
  • Workflow builders creating segment-based automation triggers
  • Anyone needing to define and track changes in a named audience

cargo-segmentation FAQ

What's the difference between a filter and a segment?

A filter is ephemeral JSON evaluated on demand; a segment is a saved filter with a name, uuid, and slug that tracks record counts and changes over time. Use filters for one-off questions, segments for reusable audiences.

Why does my filter match nothing when I think it should match records?

Check for the typo `conjunction` instead of `conjonction` — the French spelling is intentional, and misspelling it fails silently without error.

When should I use segment fetch vs. segment download?

Use `segment fetch` to inspect a few rows or count records; use `segment download` to get a signed URL for the full dataset to hand to another tool or user.

What are tracking columns and why do I need them?

Tracking columns are the subset of fields whose changes count as an `updated` record. Without them, a record only registers as added or removed. Set them when you need to monitor value changes in a segment.

Can I edit a segment created by a play?

No — segments named `GENERATED_PLAY_SEGMENT` with `fromPlay: true` belong to the play and should never be edited or removed by hand.

Full instructions (SKILL.md)

Source of truth, from getcargohq/cargo-skills.


name: cargo-segmentation description: "Define and use segments — named, saved filters over a Cargo model that become the audience for a batch run, a play trigger, or an export. Triggers: "build a segment of", "filter my contacts where", "who matches this criteria", "save this as a list", "how many companies match", "the Closed-Won segment", "everyone who has not been emailed", "target only accounts that", "what is in this segment", "narrow this down to". Filter JSON uses conjonction (not conjunction) — misspelling it fails silently. Skip when: running something over the segment — use cargo-orchestration; exporting its rows — use cargo-analytics; ad-hoc SQL over the model — use cargo-storage." version: "1.0.1" compatibility: Requires @cargo-ai/cli (npm). Sign in or create an account with cargo-ai login --email (emailed code, no browser), --oauth, or an API token homepage: https://github.com/getcargohq/cargo-skills metadata: author: getcargo openclaw: requires: bins: - cargo-ai install: - kind: node package: "@cargo-ai/cli@latest" bins: - cargo-ai homepage: https://github.com/getcargohq/cargo-skills

Cargo CLI — Segmentation

Segments are the audience layer of a Cargo workspace: a named, saved filter over one model that answers "which records do I mean?" Everything downstream — a batch run, a play trigger, a CSV export, a change feed — takes a segment (or a segment-shaped filter) as its input.

See references/response-shapes.md for full JSON response structures. See references/troubleshooting.md for common errors and how to fix them. Filter condition kinds and operators live in ../cargo-orchestration/references/filter-syntax.md — the single source of truth for filter JSON.

Bootstrap

Already signed in (cargo-ai whoami returns a workspace)? Skip to the next section.

npm install -g @cargo-ai/cli            # no global install? prefix every command with `npx @cargo-ai/cli`
cargo-ai login --email you@company.com  # emailed code, no browser; creates the account on first use
                                        # alternatives: --oauth (browser) · --token <api-token> (CI)
cargo-ai whoami                         # confirm the active workspace before any write

Every command prints JSON to stdout; failures exit non-zero with {"errorMessage": "..."}. Anything that creates a run or a batch is async — pass --wait-until-finished or poll the matching get. When the full skill bundle is installed, ../cargo/references/prerequisites.md adds the CLI version pin, token scopes, and the admin-only surface.

Key concepts

TermWhat it is
FilterA JSON object ({conjonction, groups[].conditions[]}) evaluated against one model's columns. Ephemeral on its own.
SegmentA filter saved with a name, a modelUuid, and a slug. Has a uuid, a live recordsCount, and a history. This is what plays, batches, and exports reference.
ChangeOne computed delta of a segment between two syncs — how many records were added, updated, removed, unchanged. The basis of every "notify me when someone enters this audience" motion.
Tracking columnsThe subset of columns (--tracking-column-slugs) whose value changes count as an updated record. Without them a record only ever registers as added or removed.

Filter vs segment — pick deliberately. A one-off question ("how many companies have >100 employees?") wants segment fetch with an inline filter and no saved object. An audience you will run something against, schedule against, or track over time wants a real segment create — because only a saved segment produces changes.

Discover resources first

Always list before creating. A workspace usually already holds the segment you are about to duplicate.

cargo-ai segmentation segment list                    # all segments (uuid, name, slug, modelUuid, recordsCount)
cargo-ai storage model list                           # find the modelUuid a segment must target
cargo-ai storage column list --model-uuid <uuid>      # the column slugs your filter conditions reference

Segments created automatically by a play are named GENERATED_PLAY_SEGMENT and carry fromPlay: true — never edit or remove those by hand; they belong to the play that owns them.

Retrieve in the UI: segments live under the model at app.getcargo.io/workspaces/<WORKSPACE_UUID>/models/<MODEL_UUID>. Get <WORKSPACE_UUID> from cargo-ai whoami.

Quick reference

cargo-ai segmentation segment list
cargo-ai segmentation segment get <segment-uuid>
cargo-ai segmentation segment create --name "<name>" --model-uuid <uuid> --filter '<json>'
cargo-ai segmentation segment update --uuid <segment-uuid> --filter '<json>'
cargo-ai segmentation segment remove <segment-uuid>
cargo-ai segmentation segment fetch    --model-uuid <uuid> --filter '<json>' --limit 50
cargo-ai segmentation segment download --model-uuid <uuid> --filter '<json>'
cargo-ai segmentation change list  --segment-uuid <segment-uuid>
cargo-ai segmentation change fetch --uuid <change-uuid> --kinds added --limit 50
cargo-ai segmentation record fetch --model-uuid <uuid> --ids <id[,id…]>

Building a filter

The full condition catalogue — every kind (string, number, date, boolean, array, relation) and every operator — is in ../cargo-orchestration/references/filter-syntax.md. The shape:

{
  "conjonction": "and",
  "groups": [
    {
      "conjonction": "and",
      "conditions": [
        { "kind": "number", "columnSlug": "employee_count", "operator": "greaterThan", "value": 100 },
        { "kind": "string", "columnSlug": "email", "operator": "isNotEmpty" }
      ]
    }
  ]
}

conjonction, not conjunction. The French spelling is intentional and it is the single most expensive typo in the CLI: a misspelled key does not error — the filter silently matches nothing, and you conclude the data is empty. Grep your JSON for conjunction before every call.

Match-everything filter: {"conjonction":"and","groups":[]}.

Size the audience before you build it

Counting is free; running anything over an audience is not. Establish the size first, then decide.

# 1. How many records match? — inline filter, no saved object, 1 row back
cargo-ai segmentation segment fetch \
  --model-uuid <uuid> \
  --filter '{"conjonction":"and","groups":[{"conjonction":"and","conditions":[
      {"kind":"number","columnSlug":"employee_count","operator":"greaterThan","value":100}]}]}' \
  --limit 1

# 2. Happy with the shape? Save it as the real audience.
cargo-ai segmentation segment create \
  --name "Mid-market accounts" \
  --model-uuid <uuid> \
  --filter '<same json>' \
  --column-slugs "name,domain,employee_count" \
  --tracking-column-slugs "employee_count,funding_stage"

segment get <uuid> then reports recordsCount — the authoritative size. Cite that number, not your own estimate, before proposing a paid run over the segment.

Fetch vs download vs record fetch

CommandReturnsUse for
segment fetch --model-uuid --filterRecords inline as JSON, paginated (--fetching-limit, --fetching-offset)Inspecting a handful of rows, counting, previewing a filter before saving it
segment download --model-uuid --filterA signed URL to the full datasetHanding the whole audience to the user or another tool — see ../cargo-analytics/SKILL.md
record fetch --model-uuid --ids <ids>Specific records by idRe-reading rows a change feed just told you about

segment fetch --sync refreshes the underlying data sources before evaluating; --enrich returns joined/derived values. Both cost time, so leave them off for a size check.

Never page a large segment into the conversation. Use --limit 3 to see the shape, then download for the rest.

Changes — the delta feed

Every time a segment syncs, Cargo computes a change: how the membership moved. This is what turns a static list into a signal.

# What deltas exist for this segment?
cargo-ai segmentation change list --segment-uuid <segment-uuid>
# → { "changes": [ { "uuid", "totalRecordsCount", "addedRecordsCount",
#                    "updatedRecordsCount", "removedRecordsCount",
#                    "unchangedRecordsCount", "createdAt" } ] }

# Which records actually entered the audience in that delta?
cargo-ai segmentation change fetch --uuid <change-uuid> --kinds added --limit 50

--kinds is required on change fetch and takes added, updated, removed, or unchanged (comma-separated). Returned rows carry the _kind, _id, _title, and _time meta-columns alongside the model's own columns.

updatedRecordsCount is always 0 unless the segment was created with --tracking-column-slugs — the tracked columns define what "updated" means. Set them at creation time when the segment is meant to feed a monitoring motion.

A segment's most recent delta is also inlined on segment list / segment get as lastChange, so a "what moved?" question rarely needs a second call.

What consumes a segment

Segments are an input, not an outcome. Once one exists:

  • Run something over it — batch a connector action or workflow across every member: ../cargo-orchestration/SKILL.md. Batches enroll from a segment; sample 10–20 records and get explicit approval before enrolling the full audience.
  • Trigger a play on entry — a play whose trigger is a segment fires as records enter it. Play triggers use kind: "filter" and generate their own GENERATED_PLAY_SEGMENT; see ../cargo-orchestration/references/examples/plays.md.
  • Export it — ../cargo-analytics/SKILL.md (segment download needs --model-uuid, not --segment-uuid — a frequent 400).
  • Watch it — alert when the audience empties, stalls, or spikes: ../cargo-observability/SKILL.md.
  • Act on it as GTM — signal segments (job change, funding, tech intent) drive the recipes in ../cargo-gtm/SKILL.md.
  • Declare it as code — defineSegment in ../cargo-project/SKILL.md when the audience should live in git.

Gotchas

  • conjonction, never conjunction — silent empty result, no error.
  • segment download takes --model-uuid, not --segment-uuid. The filter travels with the request; the segment UUID is not a valid input there.
  • change fetch needs --uuid (the change UUID) plus --kinds. Passing the segment UUID returns a 400.
  • change list needs --segment-uuid. Calling it bare returns a 400 complaining that segmentUuid is undefined.
  • --help on change and record subcommands prints the parent help rather than the subcommand's flags (CLI ≥ 1.0.48). Use the Quick reference above; file a report if it still bites.
  • A segment belongs to exactly one model. Cross-model audiences are a relationship + filter on the joined column, not two segments.
  • fromPlay: true segments are owned by a play. Editing one changes what that play targets; removing one breaks it.
  • --limit on a segment caps membership, it is not a display page size — --fetching-limit is the page size.

When the CLI fails

Two failed attempts on the same command, or behavior that contradicts this skill, goes to the team:

cargo-ai workspaceManagement report create \
  --title "<one-line summary>" \
  --description "<commands run, errorMessage verbatim, expected vs actual, UUIDs>"