How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/getcargohq/cargo-skills --skill cargo-segmentationBefore you start
- Installation does not include a model subscription, API allowance or permission to access your files.
- Repository stars and installation counts describe activity, not an independent quality or security test.
Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
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.
Seereferences/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 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 writeEvery command prints JSON to stdout; failures exit non-zero and print {"error": "...", "status": ..., "body": ...} to stderr. 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 referenceSegments 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, object, objectProperty, any, vector, sql, segment, occurrence, enrollment) 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 required at both levels (the filter and every group): a misspelled key fails validation and the API returns a 400 namingconjonction. Grep your JSON forconjunctionbefore every call. Every group needs at least one condition. A group with"conditions": []is rejected (Filter groups must contain at least one condition); match everything with"groups": []instead.
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; read `count`
cargo-ai segmentation segment fetch \
--model-uuid <uuid> \
--filter '{"conjonction":"and","groups":[{"conjonction":"and","conditions":[
{"kind":"number","columnSlug":"employee_count","operator":"greaterThan","value":100}]}]}' \
--fetching-limit 1 --sync false --enrich false
# 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 fetch returns the match total as count (use --fetching-limit, not --limit: --limit caps membership, so --limit 1 reports a count of 1). 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 | Signed URLs (urls[]) 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 refreshes the model before evaluating (--sync) and adds a _segments membership column (--enrich). Both default to on when omitted and cost time, so pass --sync false --enrich false 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" } ] }
# Only the deltas where something entered (or moved, or left)
cargo-ai segmentation change list --segment-uuid <segment-uuid> --has-records added --limit 20
# One delta's counts, by its uuid → { "change": {...} }
cargo-ai segmentation change get <change-uuid>
# Which records actually entered the audience in that delta?
cargo-ai segmentation change fetch --uuid <change-uuid> --kinds added --limit 50
# The whole delta as files, when it is too big to page → { "urls": [...] }
cargo-ai segmentation change download --uuid <change-uuid> --kinds added,removed--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. change download returns signed URLs rather than rows, and takes the same four kinds (unchanged from CLI 1.0.128, cargo#6369; before it the API refused that one).
change list --not-empty keeps only the deltas where a record was added, updated or removed, and --has-records takes any of the four kinds. Both need CLI 1.0.128 (cargo#6369): before it the API answered --not-empty with a 400 (Unrecognized key: "notEmpty") and refused --has-records unchanged, so on an older CLI use --has-records <kind> to skip empty deltas.
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 fires as records enter its audience. A play is created from a
--model-uuid, a--filter, and--change-kinds, and generates its 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-project/SKILL.md` when the audience should live in git.
Gotchas
- `conjonction`, never `conjunction` — the call is rejected with a 400.
- `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
segmentUuidis 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-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>"
