@getcargohq/cargo-segmentation
Router for the Cargo CLI skill bundle — load first for anything Cargo, and whenever a task spans two Cargo domains. Explains what each skill owns, declarative workspace-as-code (cargo-cdk) vs the imperative CLI, the UUID and slug flow between skills, async polling of runs and batches, end-to-end use cases, and the gotchas that fail silently (`conjonction` spelling, run vs batch, model-uuid vs segment-uuid). Triggers: \"set up Cargo\", \"what can Cargo do\", \"which Cargo skill\", \"bootstrap my workspace\", \"I have a Cargo account\", \"cargo-ai …\", or any `cargo-ai` command whose domain you are unsure of. Skip when: the task obviously belongs to one skill — load that skill directly.
| 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.0 |
| 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 | cargo-ai |
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.mdfor full JSON response structures. Seereferences/troubleshooting.mdfor 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 [email protected] # 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
| Term | What it is |
|---|---|
| Filter | A JSON object ({conjonction, groups[].conditions[]}) evaluated against one model's columns. Ephemeral on its own. |
| Segment | A 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. |
| Change | One 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 columns | The 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, notconjunction. 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 forconjunctionbefore 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
| Command | Returns | Use for |
|---|---|---|
segment fetch --model-uuid --filter |
Records inline as JSON, paginated (--fetching-limit, --fetching-offset) |
Inspecting a handful of rows, counting, previewing a filter before saving it |
segment download --model-uuid --filter |
A signed URL to the full dataset | Handing the whole audience to the user or another tool — see ../cargo-analytics/SKILL.md |
record fetch --model-uuid --ids <ids> |
Specific records by id | Re-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 ownGENERATED_PLAY_SEGMENT; see../cargo-orchestration/references/examples/plays.md. - Export it —
../cargo-analytics/SKILL.md(segment downloadneeds--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 —
defineSegmentin../cargo-cdk/SKILL.mdwhen the audience should live in git.
Gotchas
conjonction, neverconjunction— silent empty result, no error.segment downloadtakes--model-uuid, not--segment-uuid. The filter travels with the request; the segment UUID is not a valid input there.change fetchneeds--uuid(the change UUID) plus--kinds. Passing the segment UUID returns a 400.change listneeds--segment-uuid. Calling it bare returns a 400 complaining thatsegmentUuidis undefined.--helponchangeandrecordsubcommands 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: truesegments are owned by a play. Editing one changes what that play targets; removing one breaks it.--limiton a segment caps membership, it is not a display page size —--fetching-limitis 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>"
Loading...
Select a file to preview
Analyzing security...
Checking scan reports and verification data.
Bill of Materials
Everything this skill can do — files, network, commands, and more.