Cargo CLI
getcargo v1.23.0
Publisher description
From the marketplace listing
Agent skills for the Cargo CLI in Codex. Turn Codex into a GTM engineering workstation: build lead lists, find and verify emails, run waterfall enrichment, score leads, sync to CRM, monitor buying signals, and manage the workspace as code with cargo-ai.
Language: English · Automatically detected from descriptions.
Files & skills
File archives
Skill instructions
cargo56.5 KB
---
name: cargo
description: "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."
version: "1.23.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
---
```
██████ ████ █████ ██████ ██████
██ ░ ██ ██░ ██ ██ ██ ░ ██ ██░
██ ██████░ █████ ░ ██ ███ ██ ██░
██ ██ ██░ ██ ██ ██ ██░ ██ ██░
██████ ██ ██░ ██ ██ ██████░ ██████░
░░░░░░ ░░ ░░ ░░ ░░ ░░░░░░ ░░░░░░
```
# Cargo CLI — Skills Overview
This repository contains 18 skills at the repo root: this **router** (`cargo`), one **onboarding skill** (`cargo-quickstart`), one **outcome skill** (`cargo-gtm`), and fifteen **capability skills**.
- **`cargo-quickstart`** — guided first-run demo. Fresh workspace → real deliverable (the accounts matching the user's persona, sized for free and sampled for a quarter of a credit) in under two minutes, ending by saving the demo as a recurring play. Load for new users, demo/tour requests, or empty workspaces.
- **`cargo-gtm`** — application library. The front door for any GTM task ("build a TAM list", "find 5 fintech CTOs", "monitor job changes"). Routes via internal recipes (`../cargo-gtm/recipes/*.md`) and provider playbooks (`../cargo-gtm/provider-playbooks/*.md`).
- **Capability skills** — standard library. One per CLI domain (orchestration, storage, segmentation, connection, AI, content, context, analytics, billing, observability, hosting, cdk, workspace management), plus `cargo-diagnostics` (cross-domain forensics over runs, batches, and credit spend) and `cargo-mcp` (the hosted MCP server, the one surface that is not the CLI). Loaded by `cargo-gtm`, or directly when you need a specific CLI domain.
- **`cargo-cdk`** — the declarative one. Where the other capability skills wrap **imperative** one-off `cargo-ai <domain>` calls, `cargo-cdk` defines the whole workspace as code (`define*` builders + `cargo-ai cdk deploy`) and reconciles it. It spans every resource type — see "Declarative vs imperative" below to route between it and the imperative skills.
`cargo-gtm` delegates to capability skills; capability skills never reference `cargo-gtm` (one-way dependency).
**Glossary:** See [`references/glossary.md`](references/glossary.md) for term-by-term definitions (UUIDs, slugs, `conjonction`, run/batch/play/tool, signal/persona/ICP, etc.).
**Interaction conventions:** See [`references/interaction.md`](references/interaction.md) for the pack-wide defaults on when to stop and ask (plan gate before building, recommended-default choices) and how to present results (narrate, summarize — never dump raw JSON).
## Installation
```bash
npm install -g @cargo-ai/cli
# Recommended: emailed code, no browser at any point.
# Creates the account and a workspace on first use — there is no separate sign-up step.
cargo-ai login --email you@company.com # sends the code, then exits
cargo-ai login --email you@company.com --code 123456
# Alternatives
cargo-ai login --oauth # browser sign-in (OAuth device flow)
cargo-ai login --token <your-api-token> # existing workspace-scoped API token (CI)
# Optional: pick the workspace at login instead of being prompted
cargo-ai login --email you@company.com --workspace-name "Acme GTM"
# Verify
cargo-ai whoami
```
**A new account starts with 100 free credits and needs no card**, so an agent can sign a user up and produce a real deliverable in the same turn — there is no purchase gate between install and first value. Useful anchors for what that buys: ~5,000 leads sourced (`salesNavigator.searchLeads`, 0.02/record), ~1,000 profile+verified-email enriches (`aiArk.enrichPerson`, 0.1), ~1,000 email verifications (`waterfall.verifyEmail`, 0.1), or ~50 fully enriched contacts (`waterfall.enrichContact`, 2). The [quickstart demo](../cargo-quickstart/SKILL.md) spends about **0.25**. Say the free balance out loud before the first paid call on a new account.
`--email` is the one to reach for in an **agent or sandbox shell**: it never opens a browser, and where there is no terminal to prompt at, the first call sends the code and exits so you re-run with `--code`. To keep the code out of shell history, pass it on stdin: `echo 123456 | cargo-ai login --email you@company.com --code -`. Signing in with an address that already has an account resolves to its existing workspace rather than creating one, so this is safe to re-run.
`--oauth` runs the same OAuth 2.0 Device Authorization Flow it always did, and still needs a human at the verification URL. Use `--token` for CI, with a workspace-scoped token from **Settings > API**; token values are shown only once, so store one immediately in a secrets manager.
Without a global install, prefix every command with `npx @cargo-ai/cli` instead of `cargo-ai`.
These skills also install as a native **agent plugin** for Claude Code, Codex, and Cursor (one repo, three targets) — plugin users get the same skills plus the approval hook and session-lifecycle hooks bundled, with no separate installer. See the repo `README.md` for per-target install steps, and use **one** channel: plugin *or* `skills add`, never both (duplicates every skill).
All commands output JSON to stdout. Failed commands exit non-zero and return `{"errorMessage": "..."}`. For the full setup conventions that every capability skill links to (token scopes, async polling, admin-only commands), see [`references/prerequisites.md`](references/prerequisites.md).
## Every Cargo session has three jobs
> **Automated on Claude Code.** Jobs 1 and 3 (refresh + session register/finalize) run on their own when either the **Cargo plugin** is installed (its bundled `SessionStart`/`Stop`/`SessionEnd` hooks handle them) or the hooks from the Cargo bootstrap installer — documented under *Staying current → Claude Code* in the repo [`README.md`](../README.md) — are present. The `Stop` hook also checkpoints the session row each turn, so a session that never reaches `SessionEnd` still shows recent context instead of a bare placeholder. Do these by hand only when neither is installed (or on agents without lifecycle hooks). Job 2 (reporting) is always your responsibility — it can't be automated, and neither can the two **asks** at the end of Job 3 (share the session, star the repo): a hook can print, but it can't take a Y/N.
>
> **Never run that installer on the user's behalf without asking.** Its documented form pipes a network-fetched script into a shell, so it is the user's call, made by the user, in their own terminal — point them at the README rather than reaching for the command yourself. If they want to inspect it first, the README also gives the download-once-then-run form; tell them to prefer it, because fetching twice (read, then pipe) proves nothing about what the second request serves.
### 1. At session start — refresh and register
Before any other Cargo command, refresh the CLI and skills, then register the session in workspace management:
```bash
# Refresh — idempotent, ~10s. Skills first, then the CLI at the version the
# bundle pins. The pin file `cli-version` sits in the same directory as this
# SKILL.md — read it from wherever you loaded this skill (on Claude Code with
# `skills add` that is ~/.claude/skills/cargo/; plugin installs handle this
# automatically via their SessionStart hook). Fall back to latest.
npx -y skills add getcargohq/cargo-skills
npm install -g "@cargo-ai/cli@$(cat <path-to-this-skill-dir>/cli-version 2>/dev/null || echo latest)"
# Register the session (placeholders OK — overwritten at session end)
cargo-ai workspaceManagement session upsert \
--session-id <session-id> \
--title "Agent session <session-id>" \
--summary "Session in progress."
```
Skip the refresh only if the user explicitly pinned a version — and skip the `skills add` entirely if the skills came from a **plugin** (the plugin owns them; a parallel `skills add` duplicates every skill). Skip the `session upsert` only if the user opted out or no session id is available.
**Why the pin:** `cargo/cli-version` is bumped in lockstep with these skills (a PR from the CLI release pipeline), so the CLI you install is the one this bundle was written against — no docs/CLI drift mid-session. If the pin file is missing or unreadable, `latest` is the safe fallback. To move the pin, merge the pending version-bump PR on `getcargohq/cargo-skills` (or edit `cargo/cli-version`) — the next session refresh converges automatically.
The pin is also what keeps this refresh from being a blind auto-update: the version installed is a reviewed constant committed to this repo, not whatever `latest` resolved to this morning, and moving it is a human merge. Two things follow for you as the agent. The refresh installs a **global npm package** and rewrites the skills bundle on disk — surface that the first time you run it in a session rather than doing it silently, and skip it entirely if the user has pinned a version or asks you not to. And treat the pin as read-only: bump `cargo/cli-version` only when the user explicitly asks, never to work around a failing command.
### 2. Mid-session — re-refresh, or escalate when stuck
**Re-refresh** the CLI and skills mid-session when:
- A documented CLI flag or response shape doesn't match what you observe (a fix may have shipped since session start).
- The user explicitly asks ("bump cargo", "make sure I'm on latest").
**Send a workspace management report** when the CLI is failing in a way the skill references and `--help` cannot resolve, the user or agent is repeatedly retrying the same command without progress, the syntax for a flag / JSON payload is unclear, or a needed capability seems missing:
```bash
cargo-ai workspaceManagement report create \
--title "<one-line summary of the problem>" \
--description "<exact command(s) tried, errorMessage, expected vs actual, UUIDs involved>"
```
Trigger conditions (any one is enough):
- A command failed ≥ 2 times in a row on the same task and the cause is not obvious.
- The CLI is being misused and the correct usage is not discoverable from the skills, examples, or `--help`.
- A documented behavior contradicts what you observe.
- A feature appears to be missing entirely.
This is the official feedback channel — every report is reviewed by the Cargo team and used to improve the CLI and these skills. It carries **wins as well as failures**: a session-share (below) files through the same command. **Do not give up silently — file a report.** See `../cargo-workspace-management/SKILL.md` (Reports section) and `../cargo-workspace-management/references/examples/reports.md` for templates.
### 3. At session end — finalize the session row, then ask to share
Produce a short title (5–8 words) and a 1–2 sentence summary of what the session actually worked on, then overwrite the placeholder row and stamp `finished_at`:
```bash
cargo-ai workspaceManagement session upsert \
--session-id <claude-session-id> \
--title "<5-8 word title>" \
--summary "<1-2 sentence summary of what was accomplished or attempted>" \
--finished
```
`--title` and `--summary` are required (NOT NULL). `--finished` stamps `finished_at = now`; pass `--finished-at <iso>` for an explicit timestamp.
**Then ask once, at the natural end of the session:**
> "Send this session's activity to the Cargo team so they can improve the experience? (Y/N)"
On yes, file a session-share report (consented session traces are the fastest product-learning loop the team has):
```bash
cargo-ai workspaceManagement report create \
--title "Session share: <5-8 word session title>" \
--description "<what the user tried to accomplish, the commands/recipes used, what worked, where friction appeared, credits spent — no secrets or record-level data>"
```
On no, don't ask again this session. Skip the ask entirely for trivial sessions (a single lookup, no paid actions). See `../cargo-workspace-management/references/examples/reports.md` for the session-share template.
#### Then, if the session went well — offer to star the repo
A star is the **user's** endorsement, not yours. Never run the command unprompted; ask, and act only on an explicit yes. Silently starring from a skill file is astroturfing with someone else's GitHub account.
Ask only when all of these hold:
- The session produced a real deliverable (same bar as the session-share ask — skip trivial sessions).
- Nothing is still failing or unresolved. Asking after a broken session reads as tone-deaf.
- The marker file `~/.config/cargo-ai/.star-asked` does not exist — this is a **once per machine** ask, not once per session.
```bash
# gate
test -f ~/.config/cargo-ai/.star-asked || echo "ask"
```
> "Glad that worked. Want me to star `getcargohq/cargo-skills` for you? (Y/N)"
On yes (`gh` must be authenticated with the `repo` or `public_repo` scope — note there is no `gh repo star` subcommand):
```bash
gh api -X PUT /user/starred/getcargohq/cargo-skills # 204 No Content = starred
```
Touch the marker on **either** answer, so a no is never re-asked and a yes is never double-asked:
```bash
mkdir -p ~/.config/cargo-ai && touch ~/.config/cargo-ai/.star-asked
```
If `gh` is missing or unauthenticated, don't fix it and don't offer a workaround — say the repo is at `https://github.com/getcargohq/cargo-skills` and move on. This is the lowest-stakes item in the session; it never becomes a task.
---
## Skills at a glance
### Declarative (CDK) vs imperative (CLI) — pick the mode first
Two ways to create/manage the same Cargo resources. Decide which the task wants
before picking a domain:
- **Declarative → [`cargo-cdk`](../cargo-cdk/SKILL.md).** The user is managing
resources **as an artifact**: "set up / bootstrap a whole workspace as code",
"make this reproducible / version-controlled / in git", "deploy these
connectors + models + agents together", or anything that should be re-runnable
and diffable across environments. Define it in `define*` files and
`cargo-ai cdk deploy`.
- **Imperative → the matching capability skill below.** The user is doing a
**one-off operation** or **exploring**: "create one connector", "add a column",
"list connectors", "run this workflow", "query storage", "read a memory". A read,
ad-hoc query, or single mutation that needn't live in code.
When unsure: should the result be committed and re-deployable? Yes → CDK. A quick
action or a read → the capability skill.
### Onboarding skill
Load for a brand-new user or an empty workspace.
| Skill | Load when you need to… |
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| [`cargo-quickstart`](../cargo-quickstart/SKILL.md) | Run the guided first-run demo: one persona question → a free pool count and 25 matching accounts, in under two minutes → cost receipt → save as a recurring play. Routes to `cargo-gtm` afterwards. |
### Outcome skill
Load when the user states a real-world goal.
| Skill | Load when you need to… |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| [`cargo-gtm`](../cargo-gtm/SKILL.md) ([recap](#cargo-gtm)) | Any GTM task — sourcing, enrichment, verification, scoring, sequencing, CRM sync, signal monitoring (job changes, funding, tech-stack/hiring intent). Routes via recipes (`recipes/`), guides (`guides/`), and provider playbooks (`provider-playbooks/`). |
### Capability skills
Load for a specific CLI domain. The first link in each row jumps to the actual SKILL.md; the parenthetical jumps to the recap on this page.
| Skill | Load when you need to… |
| ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| [`cargo-orchestration`](../cargo-orchestration/SKILL.md) ([recap](#cargo-orchestration)) | Execute actions, run workflows, trigger batches, chat with agents, query orchestration with SQL (ClickHouse) |
| [`cargo-analytics`](../cargo-analytics/SKILL.md) ([recap](#cargo-analytics)) | Download run results, export segment data, monitor error rates and metrics |
| [`cargo-billing`](../cargo-billing/SKILL.md) ([recap](#cargo-billing)) | Check credit usage, view subscription details, track costs per workflow or connector |
| [`cargo-diagnostics`](../cargo-diagnostics/SKILL.md) ([recap](#cargo-diagnostics)) | Diagnose after the fact: trace why one run misbehaved, sweep a batch/play for errors grouped by root cause, profile where a play's credits go |
| [`cargo-observability`](../cargo-observability/SKILL.md) ([recap](#cargo-observability)) | Create and manage **alerts** — scheduled threshold checks on spans/runs/records, a model's health, or a SQL query — that fire actions (connector/tool/agent runs) on breach. Proactive counterpart to diagnostics |
| [`cargo-storage`](../cargo-storage/SKILL.md) ([recap](#cargo-storage)) | Inspect or modify data models, columns, datasets, and relationships; query workspace storage with SQL |
| [`cargo-segmentation`](../cargo-segmentation/SKILL.md) ([recap](#cargo-segmentation)) | Build and manage segments — the saved filters that name the audience for a batch, a play trigger, or an export — and read their change (delta) feed |
| [`cargo-connection`](../cargo-connection/SKILL.md) ([recap](#cargo-connection)) | Manage connector authentication, discover available integrations and their actions |
| [`cargo-ai`](../cargo-ai/SKILL.md) ([recap](#cargo-ai)) | Create and configure agents, configure releases, attach knowledge for RAG, manage MCP servers and memories |
| [`cargo-content`](../cargo-content/SKILL.md) ([recap](#cargo-content)) | Upload and organize knowledge files, build native/connector-backed knowledge libraries for RAG (the `content` domain) |
| [`cargo-context`](../cargo-context/SKILL.md) ([recap](#cargo-context)) | Browse/read/write/edit the workspace's git-backed GTM context repo, run commands in its runtime sandbox, inspect the knowledge graph |
| [`cargo-hosting`](../cargo-hosting/SKILL.md) ([recap](#cargo-hosting)) | Scaffold, deploy, and promote hosted apps (Vite SPAs on `*.cargo.app`) and edge workers (serverless HTTP handlers), and manage their deployments |
| [`cargo-cdk`](../cargo-cdk/SKILL.md) ([recap](#cargo-cdk)) | **Declarative — spans every resource type.** Define a whole workspace in code (`define*` builders) and deploy it with `cargo-ai cdk` (init → types → plan → deploy). Use for workspace-as-code / reproducible / version-controlled setups; see "Declarative vs imperative" above. |
| [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md) ([recap](#cargo-workspace-management)) | Invite users, create API tokens, organize folders, manage roles, report CLI issues to management |
| [`cargo-mcp`](../cargo-mcp/SKILL.md) ([recap](#cargo-mcp)) | Drive Cargo from the hosted MCP server at `https://mcp.getcargo.io/mcp` with no CLI install — connect a client, discover and price an action, execute one record or a batch, poll it, read models; and route between the MCP tools and the CLI |
> **Agent knowledge for RAG:** **files** + **libraries** live in the `content` domain → [`cargo-content`](../cargo-content/SKILL.md); how they attach to an agent → [`cargo-ai`](../cargo-ai/SKILL.md). (Files/libraries moved out of the old `ai file …` path in CLI ≥ 1.0.19.)
### These skills vs an MCP server
**Three distinct things wear the name MCP here.** They share no answers, so
establish which one is meant before replying:
| | What it is | Skill |
|---|---|---|
| **Hosted server** | Cargo's own endpoint at `https://mcp.getcargo.io/mcp`. Thirteen platform tools (discover, price, execute, poll, read models), plus whatever this workspace published. The way to drive Cargo with no CLI installed. | [`cargo-mcp`](../cargo-mcp/SKILL.md) |
| **Workspace server** | A curated set *this workspace* publishes (`ai mcp-server create --actions … --resources …`), served to any stdio client by `cargo-ai mcp`. | [`cargo-ai`](../cargo-ai/SKILL.md) |
| **Agent MCP client** | Somebody else's MCP server attached *to* a Cargo agent (`release update-draft --mcp-clients`). | [`cargo-ai`](../cargo-ai/SKILL.md) |
The first is new and is what "does Cargo have an MCP server?" now means. It
authenticates by OAuth discovered from its own `401` challenge, or by a
workspace-scoped bearer token:
```bash
claude mcp add --transport http cargo https://mcp.getcargo.io/mcp
```
The second is the curation path, and remains the right answer when a workspace
wants to expose one approved tool rather than the whole platform:
```bash
claude mcp add cargo -- cargo-ai mcp # the platform MCP
claude mcp add cargo -- cargo-ai mcp --server <uuid> # a curated server instead
```
With no `--server`, the bridge uses `CARGO_MCP_SERVER_UUID` when set, otherwise the platform `/mcp`. (Older CLIs instead fell back to "the workspace's only MCP server" and failed outright when there wasn't exactly one.)
Route between the CLI and either MCP surface by shape of the request:
| | **These skills (CLI)** | **An MCP server** |
|---|---|---|
| What it is | The whole CLI surface, every domain | The platform runtime tools, plus whatever the workspace chose to expose |
| Best for | Anything that builds something reusable: workflows, plays, schema changes, CDK deploys, diagnostics, exports, warehouse SQL | In-conversation execution: look this record up, enrich this list, run this one approved tool |
| Cost control | Full pilot → approval → receipt discipline ([`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md)) | Per-call; `search_actions` returns each action's credit cost before you run it |
| Reproducible | Yes — commands, plays, and CDK files are artifacts | No — a tool call leaves no artifact behind |
Rule of thumb: **anything the user will want to re-run or version belongs in the CLI.** Never fan an MCP tool out record-by-record over a list — that is what `execute_action_batch` (and `orchestration action execute-batch` on the CLI) exists for, and it is cheaper and observable. Conversely, when the workspace has already curated a tool for a job, calling it beats hand-assembling the same thing from raw actions.
### CLI domains without a dedicated skill yet
The CLI exposes several domains that no capability skill wraps yet. Reach for them directly (`cargo-ai <domain> --help`) when a task needs them, and file a `workspaceManagement report` if the surface is unclear:
| CLI domain | Covers |
| --- | --- |
| `expression` | Recipes and expression evaluation (`eval`, `recipe`) — generate/evaluate the template expressions used in node graphs. |
| `system-of-record` | System-of-record, client, and log operations. |
| `revenue-organization` | Allocations, capacities, members, territories (revenue/territory planning). |
| `user-management` | Current-user operations with no workspace context. |
---
## How the skills relate
```
┌─────────────────────────────────────┐
│ cargo-gtm │
│ Outcome / front door for GTM │
│ Recipes, guides, provider-playbks │
└─────────────────┬───────────────────┘
│ delegates to ↓ (one-way)
┌──────────────────────┴──────────────────────┐
│ │
┌──────────────────────────────────────────────────────────────┐
│ cargo-workspace-management │
│ Authentication, users, tokens, folders │
└──────────────────────────────────────────────────────────────┘
┌─────────────────┐ ┌────────────────────┐ ┌─────────────────┐
│ cargo-storage │ │ cargo-connection │ │ cargo-ai │
│ Models, columns,│ │ Connectors, │ │ Agents, docs, │
│ datasets │ │ integration actions│ │ MCP, memory │
└────────┬────────┘ └─────────┬──────────┘ └────────┬────────┘
(cargo-content feeds
files/libraries to agents)
│ │ (UUIDs flow down) │
└──────────────────────┼───────────────────────┘
▼
┌───────────────────────────────────────┐
│ cargo-orchestration │
│ Runs, batches, plays, tools, SoR │
└───────────────┬───────────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
┌────────────────────────┐ ┌───────────────────────────┐
│ cargo-analytics │ │ cargo-billing │
│ Results, metrics, │ │ Credit usage, costs │
│ exports │ │ │
└────────────────────────┘ └───────────────────────────┘
┌───────────────────────────────────────┐
│ cargo-context │
│ Git-backed GTM markdown knowledge: │
│ personas, plays, proof, signals… │
└───────────────────────────────────────┘
(orthogonal: not part of the workflow flow)
┌───────────────────────────────────────┐
│ cargo-cdk │
│ Declarative authoring layer: define │
│ connectors/models/plays/agents/… as │
│ code, deploy with `cargo-ai cdk`. │
└───────────────────────────────────────┘
(cross-cutting: PRODUCES the same resources the imperative
skills manage — an alternative mode, not a workflow stage)
┌───────────────────────────────────────┐
│ cargo-observability │
│ Scheduled threshold alerts over the │
│ telemetry above (spans/runs/records), │
│ a model's health, or a SQL query — │
│ fire actions as runs on breach. │
└───────────────────────────────────────┘
(watches orchestration/storage; fires orchestration
actions — proactive counterpart to cargo-diagnostics)
```
**Dependency rules in practice:**
- `cargo-gtm` delegates to capability skills via relative paths (`../cargo-orchestration/...`). Capability skills never reference `cargo-gtm`.
- `cargo-workspace-management` provides auth context for every skill — set it up first.
- `cargo-storage`, `cargo-connection`, and `cargo-ai` are peer skills that supply UUIDs to `cargo-orchestration`. They don't depend on each other.
- `cargo-content` owns workspace **files** and **libraries** (the `content` domain). It produces file/library UUIDs that `cargo-ai` consumes as agent release `resources` (RAG). Uploaded content files also surface read-only under `.files/` in the `cargo-context` runtime sandbox.
- `cargo-cdk` is **cross-cutting**: it's a declarative *authoring mode* that produces the very connectors/models/plays/agents/etc. the imperative capability skills manage one at a time. Route to it when the task is "manage the workspace as code" (reproducible, in git, multi-resource); route to the imperative domain skills for one-off ops, reads, and ad-hoc queries. See "Declarative vs imperative" under Skills at a glance.
- `cargo-context` is **orthogonal** to the workflow-execution flow. It touches the git-backed GTM knowledge base (markdown/MDX), not storage or workflow runs. Use it for capturing/editing the workspace's prose context — personas, plays, proof, objections, signals — and for inspecting the typed knowledge graph.
- For SQL queries against storage, use `cargo-ai storage query execute "<sql>"` (tables as `<datasetSlug>.<modelSlug>`). Load `cargo-storage` to discover dataset and model slugs, and to fetch the DDL when you need column types or the SQL dialect.
- For SQL queries against orchestration runtime tables (`runs`, `batches`, `spans`, `records`) — error rates, per-node failures, time-series — use `cargo-ai orchestration query execute "<sql>"`. Workspace scoping is automatic; tables are referenced without a schema prefix.
- Before building a workflow node graph, load `cargo-connection` to get `connectorUuid` and `actionSlug`. If any node calls a **credits-based provider action**, also load `cargo-gtm` and read that provider's playbook (`../cargo-gtm/provider-playbooks/<slug>.md`) — including its **Recurring use** section whenever the workflow is a scheduled tool or play, since a bad config or wrong cadence re-bills on every run. This applies even when the task arrived through `cargo-orchestration` or `cargo-cdk` directly, without a GTM framing.
- Before executing a workflow that uses an agent node, load `cargo-ai` to get `agentUuid`.
- After runs complete, load `cargo-analytics` to download results or measure performance. **For action output retrieval, prefer `cargo-ai orchestration run download-outputs` over `run download` — the former returns a signed-URL CSV/JSON of just the output node's data.**
- Load `cargo-billing` to understand credit consumption for any of the above.
- When a run failed, a run "succeeded but looks wrong", a batch has errors, or a play costs too much, load `cargo-diagnostics` — it sequences the `run get` / orchestration-SQL / billing surfaces into forensic runbooks (trace one run, sweep a batch, profile credit spend).
- To be told about a problem *before* you go looking — an error-rate spike, a cost ceiling, a slow node, a stalled sync, a workflow that stopped running — load `cargo-observability`. It creates **alerts**: scheduled threshold checks over the same telemetry (`spans`/`runs`/`records`), a model's health, or a SQL query, that fire actions on breach. Diagnostics is reactive (explain what happened); observability is proactive (watch for it). Alerts can also be declared as code via CDK's `defineAlert`.
---
## Per-skill critical rules
The non-obvious rules for each skill — the things that fail silently or cost money if you guess. Each skill's own SKILL.md carries the full surface; these are the ones worth knowing *before* you pick.
### cargo-gtm
**Recipes shipped:**
| Recipe | Use when… |
|---|---|
| `recipes/source-planning.md` | Decide the source before spending: probe candidates, cost per hit. |
| `recipes/prospecting.md` | End-to-end find → enrich → verify → sync (P1/P2/P3 variants). |
| `recipes/build-tam.md` | Build a Total Addressable Market list at scale (100–10,000 companies). |
| `recipes/linkedin-url-lookup.md` | Resolve LinkedIn URL from name + company with strict validation. |
| `recipes/portfolio-prospecting.md` | Investor / accelerator → portfolio companies → contacts. |
| `recipes/job-change-monitoring.md` | `waterfall.detectJobChange` (cargo-unique) on a contact segment. |
| `recipes/funding-watch.md` | Track companies that recently raised funding. |
| `recipes/tech-intent.md` | Find companies by tech-stack or hiring-intent signals. |
| `recipes/icp-discovery.md` | Diff Closed-Won vs Closed-Lost segments, surface ICP signals. |
| `recipes/custom-datapoints.md` | Design which custom attributes + live signals to collect, gated on a real source and cost. |
| `recipes/outreach-activation.md` | Turn a signal segment into send-ready outreach (enrich → verify → personalize → sequencer handoff). |
| `recipes/ads-audience-activation.md` | Push a segment to Google Ads Customer Match / LinkedIn Matched Audiences. |
| `recipes/review-and-iterate.md` | Human review loop for judgment output; corrections become permanent rules. |
| `recipes/re-engagement.md` | Wake up stale contacts only when a fresh signal fires (job change, funding, tech intent). |
| `recipes/lost-deal-revival.md` | Revive Closed-Lost CRM deals by branching on `lost_reason` (champion left, budget, timing). |
| `recipes/account-expansion.md` | Multi-thread customer accounts — net-new buyers, deduped against the Contacts model. |
**Priority provider stack** (recipes lead with these): salesNavigator (sourcing), cargo native (firmographics + signals), aiArk (LinkedIn-anchored enrich + cheapest search), waterfall (multi-source enrichment + email verify + job-change), FullEnrich (premium contact lookup), apolloio (1-credit niche-coverage enrich), theirStack (tech-stack + hiring intent), peopleDataLabs (heavyweight backfill). **Already have LinkedIn URLs?** Don't source — go straight to `aiArk.enrichPerson` (0.1, profile **+ verified email**, bills 0 on no-email), or `linkedin` (`enrichProfile`/`enrichCompany` 0.25) when you don't need the email; these are the cheapest URL-anchored enriches and easy to miss because the stack above is sourcing-first.
**Critical rules:**
- **Acceptable use gates every step that touches a person** (`../cargo-gtm/references/acceptable-use.md`): B2B professional identities from licensed providers only, three free blocking checks before any outreach step (*basis*, *suppression*, *relevance*), and a refusal list — undifferentiated fan-out, consumer targeting, lists with no stated origin, contacting a suppressed record, filter or identity evasion, auto-dialing, batch-blasting LinkedIn engagement actions. The pack never sends: outreach stops at send-ready variables for the user's own sequencer.
- All recipes use credits-based actions (`cargo-ai connection integration list` → 145 credits-based actions across 120 integrations).
- Action shape: `{"kind":"connector","integrationSlug":"<slug>","actionSlug":"<slug>"}` — no `config` on a top-level action, and **`connectorUuid` is never nested inside one**; it sits at the top level of a node.
- Output retrieval: `cargo-ai orchestration run download-outputs --output-node-slug <slug>` (NOT `run download`).
- peopleDataLabs filter shape: `searchX` uses cargo's `{conjonction, groups, conditions}` shape; `queryX` takes a PDL **SQL string** — never Elasticsearch.
### cargo-orchestration
**Critical rules:**
- See the decision flowchart at the top of `../cargo-orchestration/SKILL.md` for when to use `action execute` vs `run create` vs `batch create`.
- **Never enroll a full batch on the first attempt.** `batch create` / `action execute-batch` fan out across every record in the source. Sample **10–20 records**, report observed cost + hit-rate, then ask the user to approve the full enrollment — quoting the **record count** and the **credit estimate**. Mechanics: `../cargo-orchestration/SKILL.md` → "Create a batch"; spend rules: `../cargo-gtm/references/cost-discipline.md` §1.
- **Search for the action; never browse the catalog for it.** `cargo-ai orchestration action list <keywords> [--kind connector|native|tool|agent] [--integration-slug <slug>] [--limit 20]` covers the integration catalog, Cargo native actions, workspace tools, and agents in one free call, and returns a ready-to-paste `action` object (`connectorUuid` resolved) plus the action's **credit costs**. Its sibling `cargo-ai connection action search <keywords>` is connector-only but adds `--credits-only` and `--category`, the two filters `action list` lacks. Both beat paging `connection integration list`; reach for `integration get <slug>` only once you have picked the action and need its full input schema.
- **Omit `config` on `action execute` / `action execute-batch`** — inputs go in `--data` / `--records`. That is the shape `action list` returns, so its result pastes straight in. **`action get-output-schema` is the exception and still requires it** (`400` at `action.config` without `"config": {}`), as do workflow **nodes**, alert `--actions`, play `healthAlertActions`, and agent / MCP-server `--actions`. Inputs misplaced in `config` are now dropped rather than rejected — the action runs with no input and the error never mentions `config`.
- **`action execute` is the default for running an operation; `node execute` is debug-only.** Use `node execute` only to test a single node of a workflow you're authoring — it requires `--workflow-uuid`, `--release-uuid`, `--node`, `--computed-config` and `--context` (all five). Anything else — enrich a record, call a connector action, invoke a tool or agent — goes through `action execute` / `action execute-batch`.
- **Prefer built-in actions + expressions when building a node graph.** Avoid `python`, `script` (JS), and raw HTTP nodes unless necessary: use `variables` for transforms, the native `agent` node for LLM calls, the integration's dedicated connector action for APIs, and `branch`/`filter`/`switch` for routing. See `../cargo-orchestration/references/node-selection.md`.
- **Show a node graph, don't describe it.** Before deploying a draft, and whenever the user asks what a workflow or play does: `cargo-ai orchestration node diagram --workflow-uuid <uuid> --raw` (free, runs nothing, CLI ≥ 1.0.54; `references/node-diagram.md`). Routing, fallback edges, and which nodes bill are what's being approved. Let the command draw it rather than transcribing — node **slugs repeat within a release**, so a hand-drawn diagram keyed on slug merges nodes that aren't the same.
- Filter JSON uses `conjonction` (not `conjunction`) — breaks silently if misspelled.
- Query orchestration runtime tables (ClickHouse) with `cargo-ai orchestration query execute "<sql>"` against `runs`, `batches`, `spans`, `records` (no schema prefix; workspace scoping is automatic).
- For SQL against workspace storage (Companies, Contacts, …), use `cargo-ai storage query execute "<sql>"` — documented in `cargo-storage`.
- All operations are async — poll or pass `--wait-until-finished`. See [Async polling](#async-polling).
### cargo-analytics
**Critical rules:**
- `segment download` requires `--model-uuid`, not `--segment-uuid`.
- For batch result download, get the `output-node-slug` from `release get <release-uuid>` → `nodes[].slug`.
- For billing and credit usage, use `cargo-billing` instead.
- Analytics answers "what happened" (metrics, counts, exports). When the question is **why** — a failing run, a batch full of errors, surprising cost — hand off to `cargo-diagnostics`; its sweep runbook picks up exactly where analytics' error counts leave off.
### cargo-billing
**Critical rules:**
- Requires a token with **admin access**.
- Invoice amounts are in cents — divide by 100 for dollars.
- `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount` from `subscription get` = remaining credits.
### cargo-diagnostics
**Critical rules:**
- Start with the **sweep** when you don't know which run to look at; it ends with exemplar UUIDs for the **trace**.
- `runContext` is the source of truth for what a node produced; an execution's `title` is a truncated summary — never evidence.
- Credit attribution (`billing …`) needs an **admin** token; the SQL and `run get` steps don't.
- Any fix that re-runs paid nodes goes through the pilot gate in `../cargo-gtm/references/cost-discipline.md`.
- Diagnostics explains; it doesn't export. For bulk retrieval after the diagnosis (`run download-outputs`, `batch download`, `segment download`) go back to `cargo-analytics`.
- Present conclusions first, evidence as compact tables — per `references/interaction.md` (in the `cargo` router skill).
### cargo-observability
**Critical rules:**
- **`preview` before `create`.** `alert preview --scope … --threshold … [--window-minutes 60]` evaluates now without firing — the only way to size a threshold against reality and to catch an invalid scope/threshold pairing (`outcome: "notComputed"`) before it becomes a schedule that errors every tick.
- **Scope and threshold are a matched pair.** Telemetry metrics (`errorRate`, `duration`+aggregation, `credits`+aggregation, `count`) need `spans`/`runs`/`records`; `query` needs a query scope; `recordsCount`/`recordsShare`/`freshness`/`syncDuration` need `model`. Full matrix + units in `references/scopes-and-thresholds.md`.
- **Empty window vs real zero.** Most metrics report an idle window as `empty` (healthy, no fire). Only `count` and `recordsCount` return a real `0` — pair with `lte 0` for a **dead-man's switch** (alert when a workflow *stops*, a model *empties*).
- **Firing is at-most-once and costs credits.** Actions fire as runs (`runUuids` on the event); a sustained breach re-fires once per tick it's still true, never on the same rows twice. If an action calls a paid provider, apply `../cargo-gtm/references/cost-discipline.md` — a scheduled alert re-bills on every breach.
- **`--enabled` is strict** (`true`/`false` only); model-scope `filter` uses the segmentation shape spelled **`conjonction`**.
- Permissions are `observability:read` / `observability:write` (not admin-only). The declarative equivalent is CDK's `defineAlert` — see `cargo-cdk`.
### cargo-storage
**Critical rules:**
- Query via `cargo-ai storage query execute "<sql>"` (or `storage query download --query "<sql>"` for full exports) using `<datasetSlug>.<modelSlug>` table names (e.g. `default.companies`). `model get-ddl` is optional — useful for column types and SQL dialect.
- For SQL against orchestration runtime tables (`runs`/`batches`/`spans`/`records`), use `cargo-ai orchestration query execute "<sql>"` — documented in `cargo-orchestration`.
- For advanced record queries (filtering, sorting, pagination), use `segmentation segment fetch` — documented in `cargo-segmentation`.
- `storage relationship set` **replaces** the dataset's whole relationship set — anything absent from the payload is deleted. `list` first, send the full array back.
### cargo-segmentation
**Critical rules:**
- Filter JSON uses `conjonction` (not `conjunction`). A misspelling is **not** an error — the filter silently matches nothing.
- **Size before you spend.** `segment fetch --limit 1` counts an inline filter for free; a saved segment's `recordsCount` is the authoritative size. Quote it before proposing any paid run over the audience.
- `segment download` takes `--model-uuid` **plus the filter**, never `--segment-uuid`.
- `change list` needs `--segment-uuid`; `change fetch` needs the **change** UUID plus `--kinds` (`added`/`updated`/`removed`/`unchanged`).
- `updatedRecordsCount` stays `0` unless the segment was created with `--tracking-column-slugs` — those columns define what "updated" means.
- Segments named `GENERATED_PLAY_SEGMENT` (`fromPlay: true`) are owned by a play. Never edit or remove them by hand.
### cargo-connection
**Key concepts:**
- **Integration** = external service type (HubSpot, Clearbit, Salesforce, …)
- **Connector** = authenticated instance of an integration (referenced by `connectorUuid` in nodes)
### cargo-ai
**Critical rules:**
- Knowledge for RAG attaches to an agent via the release's `resources`: **files** + **libraries** come from [`cargo-content`](#cargo-content). Wire them in with `release update-draft --resources …` then `release deploy-draft`.
- **`cargo-ai mcp` with no `--server` now bridges the first-party platform MCP** (`mcp.getcargo.io/mcp`), not "the workspace's only MCP server". `ai mcp-server` still builds a curated server; pass its uuid with `--server`. See "These skills vs Cargo's MCP surfaces" above.
- **CLI ≥ 1.0.19:** files and libraries moved out of the `ai` domain into the top-level **`content`** domain (now the `cargo-content` skill). The old `cargo-ai ai file …` commands no longer exist.
> For _using_ agents (sending messages, multi-turn chat, polling), use `cargo-orchestration`.
See `../cargo-ai/SKILL.md` for model and temperature guidance by use case.
### cargo-content
**Critical rules:**
- New top-level **`content`** domain in CLI ≥ 1.0.19 — `cargo-ai content file …` / `cargo-ai content library …`. The old `cargo-ai ai file …` path is gone (`unknown command` → you're on the old path; bump the CLI).
- A file or library is inert until attached to an agent's deployed release `resources` — that wiring lives in [`cargo-ai`](#cargo-ai).
- Uploaded content files are also readable (read-only) under `.files/` in the `cargo-context` runtime sandbox.
- For batch-run **input** files (CSVs that drive a batch), use `cargo-ai workspaceManagement file upload` (a different surface) — see `cargo-workspace-management`.
### cargo-context
**Key concepts:**
- **Context repository** = the GitHub repo backing the workspace's context. Canonical example: [`getcargohq/cargo-workspaces`](https://github.com/getcargohq/cargo-workspaces). Files use `kebab-case.md` names, YAML frontmatter with required `title` + `description`, and `domain/slug` cross-refs (no `.md`).
- **Runtime sandbox** = a checked-out, executable copy of the context repo. `runtime write` and `runtime edit` push to the default branch; `runtime execute` does **not** push.
- **Knowledge graph** = the typed graph over every md/mdx file, with frontmatter and outbound cross-refs per node. Built via `cargo-ai context graph get`.
**Critical rules:**
- `runtime write` / `runtime edit` commit and push. `runtime execute` is ephemeral — use it for `grep`/`ls`/inspection, never for persistent changes.
- `runtime edit --old-string` must match the file content **exactly once**. Read first, copy whitespace verbatim.
- Set `title` + `description` frontmatter on every `.md`/`.mdx` file — a **strong convention, not enforced**: missing/malformed frontmatter is still committed, it just indexes poorly (graph falls back to filename + first paragraph, and reads `summary`, not `description`).
- Graph **edges** form only from frontmatter `references:`, markdown links, or wikilinks — a bare path in prose creates no edge. Cite source files in `references:`.
- For domains, conventions, and per-domain templates, see `../cargo-context/references/conventions.md`.
**Lifecycle:**
- For bootstrapping a fresh workspace's context from a domain (ICP, personas, proof, signals — idempotent, skips already-seeded domains), see [`../cargo-context/references/examples/bootstrap-from-domain.md`](../cargo-context/references/examples/bootstrap-from-domain.md).
- For the full bootstrap + ongoing call-driven refresh playbook (Phase 1 + Phase 2 + cadence), see [`../cargo-context/references/examples/lifecycle.md`](../cargo-context/references/examples/lifecycle.md).
### cargo-hosting
**Lifecycle:** `init` (local scaffold) → `create` (slot + globally-unique slug) → `deployment create` (build+upload) → `deployment promote` (go live).
**Critical rules:**
- `--slug` is the live subdomain — **globally unique within the hosting domain**.
- **Deploying ≠ going live.** `deployment create` builds; the URL only moves on `deployment promote`. `deployment get-promoted` shows what's live.
- `--source` is the **package root**, not `dist/` — the build (`npm ci && vite build` for apps, bundling for workers) runs server-side.
- Builds are async — poll `deployment get` until terminal before promoting.
- `--app-uuid` / `--worker-uuid` are mutually exclusive on deployment commands; `remove` cascades to deployments.
- Folders come from [`cargo-workspace-management`](#cargo-workspace-management); `--folder-uuid null` moves to root.
### cargo-cdk
entire Cargo workspace in TypeScript (`defineConnector`/`defineModel`/`defineAgent`/
`definePlay`/`defineTool`/`defineMcpServer`/`defineContext`/`defineSegment`/
`defineFolder`/`defineFile`/`defineWorker`/`defineApp`/`defineAlert`) and reconcile
it to live infra with `cargo-ai cdk`. Spans **every** resource type, so it overlaps
every imperative capability skill — route with "Declarative vs imperative" above.
**Lifecycle:** `cdk init` (scaffold from a template) → `cdk types` (type config
against the workspace) → author `define*` files → `cdk plan` (offline diff) →
`cdk deploy` (create/update, write state) → `cdk destroy`. Plus `refresh` (drift),
`import` (adopt existing), `rollback`.
**Critical rules:**
- **Commit `cargo.state.json`** — it links code to created resources and is the
*only* handle on deployed plays/agents (no slug); losing it orphans them.
- **Wire by handle, not `.uuid`** — pass a `define*` handle or `xxRef("uuid")`.
- **Secrets** go through `secret("ENV_VAR")` — resolved at deploy, never written to
state or the content hash. Export the env var first.
- **`--yes`** is required for non-interactive `deploy`/`destroy` (CI).
- **Run `cargo-ai cdk types`** after workspace integrations change so config
type-checks; typing is a bonus, deploy works without it.
- **`definePlay`/`defineTool` graphs with credits-based connector actions:** read
the provider's playbook in `../cargo-gtm/provider-playbooks/` (esp. its
**Recurring use** section) before `cdk deploy` — a deployed play re-bills its
nodes on every scheduled run.
**Recipes shipped:** `recipes/scaffold-a-workspace.md`, `add-connector-and-model.md`,
`build-an-agent.md`, `migrate-existing-workspace.md`, `deploy-from-ci.md`.
**Cookbooks:** ~20 pre-written GTM outcomes (TAM building,
inbound flow, contact sourcing, account scoring, AI SDR, …) live in
[`getcargohq/gtm-skills`](https://github.com/getcargohq/gtm-skills) beside its one-off
skills. The menu is local:
[`../cargo-cdk/references/cookbooks.md`](../cargo-cdk/references/cookbooks.md).
Check it before authoring a common GTM outcome from scratch.
**The routing question is one-off versus standing.** "Build our TAM" is `cargo-gtm`
when the user wants a list today, and `tam-building` when they want a pipeline that
keeps producing it. The words are the same; listen for whether the result is meant to
keep arriving. Each cookbook is a self-contained worked example the installing agent
copies into the project and adapts, not a template to fill in:
`npx skills add getcargohq/gtm-skills/<name>`. See the section in
`../cargo-cdk/SKILL.md` for the caveats and the `--force` warning.
### cargo-workspace-management
**Critical rules:**
- Most commands require a token with **admin access**.
- `workspaceManagement token create` requires `--name` (the legacy `--from-user` flag was removed). Pick a name that makes the token's purpose obvious in `token list` later.
- Token values are only shown **once** at creation — store immediately in a secrets manager (GitHub Secrets, AWS Secrets Manager, etc.).
- **Always send a `workspaceManagement report create`** when the CLI errors, is being used incorrectly, or you (user or agent) are struggling to make progress on a CLI task — see the section at the top of this file and `../cargo-workspace-management/references/examples/reports.md`.
### cargo-mcp
**Critical rules:**
- **`whoami` first, every session.** The token binds the session to exactly one workspace with no override. A wrong-workspace session returns real records belonging to someone else, which reads as success.
- **Never loop `execute_action` over a list** — `execute_action_batch` is cheaper, observable, and returns one object plus an output CSV.
- `search_actions` returns each action's `credits[].cost`, so quote the price before running it, and sample 10–20 records before a full fan-out.
- `query_models` is not SQL: it lists records with a limit and offset, and will not aggregate or join. Route those to `cargo-storage`.
- The tool list varies by workspace — the endpoint serves the platform tools plus whatever that workspace published with `defineMcpServer`.
## Async polling
All operations are asynchronous. Pass `--wait-until-finished` to block, or poll:
| Result type | Poll command | Interval | Terminal when |
| ------------- | ----------------------------------------- | -------- | ---------------------------------------------- |
| Run | `cargo-ai orchestration run get <uuid>` | 2s | `status` is `success`, `error`, or `cancelled` |
| Batch | `cargo-ai orchestration batch get <uuid>` | 5s | `status` is `success`, `error`, or `cancelled` |
| Agent message | `cargo-ai ai message get <uuid>` | 2s | `status` is `success` or `error` |
`action execute` returns a run; `action execute-batch` returns a batch — same polling applies.
See `../cargo-orchestration/references/polling.md` for retry strategies, error handling, and large-batch guidance.
---
## UUID flow between skills
See [`references/uuid-flow.md`](references/uuid-flow.md) — producer/consumer table for every UUID and slug that crosses skill boundaries (`workflowUuid`, `modelUuid`, `connectorUuid`, `actionSlug`, …), the standard discovery sequence to run before any workflow, and the `app.getcargo.io` URL patterns for resolving UUIDs in the UI.
---
## End-to-end use cases
See [`references/use-cases.md`](references/use-cases.md) — 8 worked recipes (single-record enrich, batch + CRM sync, AI lead scoring, custom workflow from scratch, error monitoring, fresh-workspace bootstrap, segment export with filter+sort, GTM context audit) showing which skills to load and the command sequence for each.
---
## Common gotchas
See [`references/gotchas.md`](references/gotchas.md) — silent-failure footguns and frequently confused command pairs (`conjonction` spelling, `run create` vs `batch create`, `--model-uuid` vs `--segment-uuid`, storage query table naming, token-shown-once, invoice cents, third-party connector rate limits, `context runtime execute` vs `write`/`edit`, …).
Referenced files: 8
cargo-ai17.6 KB
---
name: cargo-ai
description: "Build and configure AI agents inside Cargo — create an agent, choose its model and temperature, write its prompt, attach knowledge for retrieval (RAG), connect MCP tool servers, manage memories, and deploy releases. Triggers: \"create an agent\", \"make an agent that\", \"give the agent our docs\", \"attach this knowledge base\", \"attach this library to the agent\", \"add resources to the agent release\", \"connect an MCP server\", \"expose our tools as an MCP server\", \"use Cargo from Claude Desktop or ChatGPT\", \"change the agent model\", \"what does the agent remember\", \"deploy the agent\", \"the agent is answering wrong\". Skip when: uploading the knowledge files themselves — use cargo-content; sending the agent a message or running it over records — use cargo-orchestration."
version: "2.3.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
---
# Cargo CLI — AI
Agent resource management: creating and configuring agents, attaching knowledge for retrieval-augmented generation (RAG), connecting MCP servers, and managing agent memories.
> For *using* agents (sending messages, multi-turn chat, polling), use `cargo-orchestration`.
> For uploading knowledge **files** and building knowledge **libraries** (the `content` domain), use [`cargo-content`](../cargo-content/SKILL.md). This skill covers how that knowledge attaches to an agent.
> For workspace administration — folders (used to organize agents and files), users, API tokens, roles, and submitting reports when the CLI fails — use [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md).
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/agents.md` for agent CRUD and configuration examples.
> See `references/examples/mcp-servers.md` for MCP server creation and management examples.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover resources first
```bash
cargo-ai ai agent list # all agents (uuid, name, description)
cargo-ai ai template list # all AI agent templates (slug, name)
cargo-ai ai mcp-server list # all MCP servers (uuid, name)
cargo-ai ai memory list --scope agent --agent-uuid <uuid> # agent memories
# Knowledge files & libraries live in the content domain — see cargo-content:
# cargo-ai content file list / cargo-ai content library list
```
**Retrieve in the UI:** agents live at `app.getcargo.io/workspaces/<WORKSPACE_UUID>/agents/<AGENT_UUID>`. Get `<WORKSPACE_UUID>` from `cargo-ai whoami` under `workspace.uuid`.
## Quick reference
```bash
cargo-ai ai agent list
cargo-ai ai agent get <agent-uuid>
cargo-ai ai agent create --name <name> --icon-color blue --icon-face 🤖
cargo-ai ai agent update --uuid <agent-uuid> --name <name>
cargo-ai ai agent remove <agent-uuid>
cargo-ai ai release list --agent-uuid <uuid>
cargo-ai ai release get <release-uuid>
cargo-ai ai release get-draft --agent-uuid <uuid>
cargo-ai ai release update-draft --agent-uuid <uuid> --language-model-slug gpt-4o
cargo-ai ai release deploy-draft --agent-uuid <uuid>
cargo-ai ai template list
cargo-ai ai template get <slug>
cargo-ai ai mcp-server list
cargo-ai ai mcp-server create --name "Internal Tools"
cargo-ai ai mcp-server update --uuid <mcp-server-uuid> --name "Updated Name"
cargo-ai ai mcp-server remove <mcp-server-uuid>
cargo-ai ai mcp-client connect --name "My MCP" --url https://mcp.example.com/sse
cargo-ai mcp # serve the platform MCP over stdio
cargo-ai mcp --server <mcp-server-uuid> # serve a curated workspace MCP server instead
cargo-ai ai memory list --scope agent --agent-uuid <uuid>
cargo-ai ai memory update --mem0-id <id> --scope agent --agent-uuid <uuid> --content "Updated memory"
cargo-ai ai memory remove --mem0-id <id> --scope agent --agent-uuid <uuid>
```
## Agents
Agents are AI resources with configured instructions, a language model, actions, and optional resources.
**Before creating an agent from scratch, check existing templates — they capture proven patterns for common use cases (lead research, classification, email drafting) and give you a ready-made system prompt, model, and temperature to start from:**
```bash
cargo-ai ai template list # browse available patterns
cargo-ai ai template get <slug> # inspect system prompt, model, and actions
```
```bash
# List all agents
cargo-ai ai agent list
# Get a single agent (includes deployed release details)
cargo-ai ai agent get <agent-uuid>
# Create an agent
cargo-ai ai agent create \
--name "Lead Researcher" \
--icon-color blue --icon-face 🤖 \
--description "Researches leads and enriches data"
# Update an agent
cargo-ai ai agent update --uuid <agent-uuid> \
--name "Senior Lead Researcher" \
--description "Updated description"
# Move to a folder (find folder UUIDs via cargo-workspace-management)
cargo-ai ai agent update --uuid <agent-uuid> --folder-uuid <folder-uuid>
# Remove an agent
cargo-ai ai agent remove <agent-uuid>
```
**Agent icon:** `--icon-color` must be one of: `grey`, `green`, `purple`, `yellow`, `blue`, `red`. `--icon-face` is an emoji string.
**Folders:** Folder creation, listing, and management lives in [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md) (`cargo-ai workspaceManagement folder list/create/...`). Use that skill to discover or create the `<folder-uuid>` you pass to `--folder-uuid` here.
## Releases
Releases are versioned snapshots of an agent's configuration (system prompt, actions, resources, model, temperature). Agents execute against their deployed release.
```bash
# List releases for an agent
cargo-ai ai release list --agent-uuid <uuid>
# Get a specific release
cargo-ai ai release get <release-uuid>
# Get the current draft release (editable)
cargo-ai ai release get-draft --agent-uuid <uuid>
# Update the draft release
cargo-ai ai release update-draft --agent-uuid <uuid> \
--system-prompt "You are a lead research assistant..." \
--language-model-slug gpt-4o \
--temperature 0.3 \
--max-steps 10
# Deploy the draft release (makes it live)
cargo-ai ai release deploy-draft --agent-uuid <uuid> \
--integration-slug openai \
--language-model-slug gpt-4o \
--actions '[]' \
--mcp-clients '[]' \
--resources '[]' \
--capabilities '[]' \
--suggested-actions '[]' \
--description "Added research actions"
```
### Structured output & heartbeat — not yet exposed as CLI flags
The release API payload (both `draft/update` and `draft/deploy`) accepts two fields that **`release update-draft` / `release deploy-draft` do not surface as flags** (verified against the CLI source — there is no `--output` / `--output-schema` or `--heartbeat`):
| Field | Shape | Purpose |
|---|---|---|
| `output` | `{"type":"text"}` **or** `{"type":"jsonSchema","jsonSchema": <standard JSON Schema object>}` | Force the agent to return structured output matching a JSON Schema. |
| `heartbeat` | `{"intervalMinutes": number, "maxMessages": number, "prompt": string \| null}` | Periodically re-wake the chat (`intervalMinutes`) until it reaches `maxMessages`; `prompt` is the wake message (null = generic "continue"). |
The generic `--options` flag does **not** carry these — the API's `options` only holds `{connectorUuidsByIntegrationSlug, modelUuidsByIntegrationSlug}`. Until the flags ship, set these with a direct API call against the same endpoints the CLI uses:
```bash
# Structured (JSON Schema) output on the draft release
curl -sS -X PUT "$CARGO_API_BASE/v1/ai/releases/draft/update" \
-H "Authorization: Bearer $CARGO_TOKEN" -H "Content-Type: application/json" \
-d '{"agentUuid":"<uuid>","output":{"type":"jsonSchema","jsonSchema":{"type":"object","properties":{"score":{"type":"number"}},"required":["score"]}}}'
# Deploy carries the same fields — POST .../v1/ai/releases/draft/deploy
```
Send these payloads alongside the other fields you're updating (the endpoint replaces the draft config). **File a `workspaceManagement report`** (see [`../cargo-workspace-management/SKILL.md`](../cargo-workspace-management/SKILL.md)) to request first-class `--output` / `--heartbeat` flags — this is the documented feedback channel for CLI/UI parity gaps.
**Agent configuration workflow:**
1. **Browse templates for inspiration**: `cargo-ai ai template list` — find a template close to your use case, then `cargo-ai ai template get <slug>` to see its system prompt, model, and temperature
2. Create the agent: `cargo-ai ai agent create --name "..." --icon-color blue --icon-face 🤖`
3. Get the draft release: `cargo-ai ai release get-draft --agent-uuid <uuid>`
4. Update the draft with configured actions, resources, prompt, model: `cargo-ai ai release update-draft --agent-uuid <uuid> ...`
5. Deploy: `cargo-ai ai release deploy-draft --agent-uuid <uuid> ...`
## Templates
Templates are pre-built agent configurations that capture proven patterns for common use cases. **Always check templates before designing an agent from scratch** — they give you a ready-made system prompt, recommended language model, temperature, and tool configuration that you can adopt as-is or adapt.
```bash
# List available agent templates
cargo-ai ai template list
# Get a template by slug — inspect its system prompt, model, and settings
cargo-ai ai template get <slug>
```
Templates include a system prompt, actions, resources, and recommended model settings. Use them as a starting point and customize via `release update-draft`. See `references/examples/templates.md` for the full guide including an end-to-end example of creating an agent from a template.
## Model and temperature guidance
| Use case | Recommended model | Temperature |
|---|---|---|
| Classification, extraction, scoring | `gpt-4o-mini` or `claude-3-5-haiku` | `0.0` – `0.2` |
| Research, summarization, analysis | `gpt-4o` or `claude-3-5-sonnet` | `0.2` – `0.5` |
| Copywriting, personalization | `gpt-4o` or `claude-3-5-sonnet` | `0.5` – `0.8` |
| Brainstorming, creative ideation | `gpt-4o` or `claude-opus` | `0.7` – `1.0` |
Low temperature (`0.0`–`0.2`) = deterministic, consistent outputs. High temperature (`0.7`+) = creative, varied outputs. For production workflows processing thousands of records, prefer low temperature.
## Knowledge for RAG (files & libraries)
Knowledge that grounds agent responses (retrieval-augmented generation, RAG) comes from the **`content`** domain — see [`cargo-content`](../cargo-content/SKILL.md):
- **Files** — uploaded binaries (PDFs, CSVs, text).
- **Libraries** — collections that group files, either `native` (workspace-managed) or `connector`-backed (synced from an external source via an unstructured-data extractor).
> Files and libraries moved out of `ai` into the top-level **`content`** domain in CLI ≥ 1.0.19 (`cargo-ai content file …` / `cargo-ai content library …`). The old `ai file …` commands are gone. Everything content-related now lives in [`cargo-content`](../cargo-content/SKILL.md).
### Attaching knowledge to an agent
A file or library is inert until attached to an agent via the draft release's `resources` array and deployed. Upload files / build libraries in [`cargo-content`](../cargo-content/SKILL.md), then wire them in here with `release update-draft --resources …` followed by `release deploy-draft`. See [`../cargo-content/references/examples/files.md`](../cargo-content/references/examples/files.md) for the full upload → attach → deploy sequence.
## MCP — two directions, don't mix them up
MCP (Model Context Protocol) runs both ways in Cargo, and the two surfaces are unrelated:
| | **Publish** — `ai mcp-server` | **Consume** — `ai mcp-client` |
|---|---|---|
| What it is | A server **your workspace exposes**: the tools, agents, and data you choose to make callable | A connection **to someone else's** MCP server |
| Who calls it | Any MCP client — Claude Code, Claude Desktop, Cursor, ChatGPT | Your Cargo agents, during a chat or a workflow run |
| Wired via | `cargo-ai mcp --server <uuid>` (stdio bridge, below) | `release update-draft --mcp-clients …` |
**Before building one, check whether the platform MCP already covers it.** Cargo now serves a first-party MCP at `https://mcp.getcargo.io/mcp` — every workspace member, nothing to deploy — with a small fixed toolset for operating the workspace (`whoami`, `get_usage`, `search_actions`, `get_action_schema`, `autocomplete_action`, `execute_action`, `execute_action_batch`, `get_run`, `get_batch`, `list_runs`, `list_models`, `describe_model`, `query_models`). Hosted clients (ChatGPT connectors, Claude.ai, Cursor over HTTP) point at that URL and sign in with OAuth; the consent screen picks the workspace when the user belongs to several. `ai mcp-server` is for the other job: a **curated, named** subset — this tool, that agent, this filtered model — for a client that should see exactly that and nothing else.
### Publishing a workspace MCP server
```bash
cargo-ai ai mcp-server list
cargo-ai ai mcp-server create --name "CRM tools" \
--actions '[{"slug":"<tool-uuid>","kind":"tool","name":null,"description":null,"isBulkAllowed":false,"config":{}}]' \
--resources '[{"kind":"model","slug":"<slug>","name":"Accounts","description":null,"integrationSlug":"hubspot","modelUuid":null,"filter":null,"selectedColumnSlugs":null,"limit":null,"prompt":null,"isReadOnly":true}]'
cargo-ai ai mcp-server update --uuid <mcp-server-uuid> --name "Updated name"
cargo-ai ai mcp-server remove <mcp-server-uuid>
```
- **Actions** take `kind: "tool"` **or** `kind: "agent"` — an agent can be exposed as a callable MCP tool, not just a tool. `waitUntilFinished` controls whether the call blocks on the run.
- **Resources** take `kind: "model"` (a filtered, column-selected view of a model — keep `isReadOnly: true` unless the client is meant to write) or `kind: "file"` (workspace files by UUID, see [`../cargo-content/SKILL.md`](../cargo-content/SKILL.md)).
- `update` replaces `--actions` / `--resources` wholesale rather than merging — read the current server with `mcp-server list` and pass the full array back.
### Serving it to a coding agent — `cargo-ai mcp`
Either server reaches any stdio MCP client through the CLI, using the credentials already on the machine. **No token is copied into client config.**
```bash
claude mcp add cargo -- cargo-ai mcp # the platform MCP (no setup)
cargo-ai ai mcp-server list # find a curated server's UUID
claude mcp add cargo -- cargo-ai mcp --server <uuid> # that curated server instead
# Cursor, Windsurf, and other stdio clients: same command as the server entry
```
With no `--server`, the bridge uses `CARGO_MCP_SERVER_UUID` when set, otherwise the platform `/mcp`. **This changed:** older CLIs resolved "the workspace's only MCP server" and failed with `InvalidUsage` when the workspace had none or several — a bare `cargo-ai mcp` now always has something to serve. stdout carries the MCP protocol and all logs go to stderr, so never print anything to stdout around it.
**When to reach for this instead of the skills:** the skills give an agent the whole CLI; an MCP surface gives it a bounded set with no shell. Use the bridge for in-conversation lookups and one-off actions, and the CLI for batches, workflows, schema changes, and anything with a cost gate. Full routing rule: [`../cargo/SKILL.md`](../cargo/SKILL.md) → "These skills vs Cargo's MCP surfaces".
### Consuming an external MCP server
```bash
cargo-ai ai mcp-client connect --name "My MCP" --url https://mcp.example.com/sse
cargo-ai ai mcp-client connect --name "My MCP" --url https://mcp.example.com/sse \
--disabled-tool-slugs "dangerous_tool,other_tool"
```
`--authentication` takes `{"issuedAt": "...", "accessToken": "..."}` or `"null"`. Connected clients are attached to an agent through its release: `release update-draft --mcp-clients …`, then `release deploy-draft`.
## Memories
Memories are pieces of information an agent stores from conversations for future reference. They can be scoped to a workspace, user, or specific agent.
```bash
# List agent memories
cargo-ai ai memory list --scope agent --agent-uuid <uuid>
# List workspace-wide memories
cargo-ai ai memory list --scope workspace
# List user-scoped memories
cargo-ai ai memory list --scope user
# Update a memory
cargo-ai ai memory update \
--mem0-id <id> \
--scope agent --agent-uuid <uuid> \
--content "Updated memory content"
# Remove a memory
cargo-ai ai memory remove \
--mem0-id <id> \
--scope agent --agent-uuid <uuid>
```
## Help
Every command supports `--help`:
```bash
cargo-ai ai agent create --help
cargo-ai ai release update-draft --help
cargo-ai ai mcp-server create --help
cargo-ai ai memory list --help
```
Referenced files: 6
cargo-analytics14.2 KB
---
name: cargo-analytics
description: "Get data out of Cargo and measure what ran — download a run output, export a segment or model to CSV or JSON, and pull run and batch success and error counts. Triggers: \"download the results\", \"export this to CSV\", \"give me the file\", \"how many succeeded\", \"what is my error rate\", \"send me the enriched list\", \"get the output of that run\", \"how many records did it write\". Skip when: asking why something failed or where credits went — use cargo-diagnostics; asking about credits, plans, or invoices — use cargo-billing."
version: "1.5.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
---
# Cargo CLI — Analytics
Measurement and export: monitoring run metrics, downloading run and batch results, and exporting segment data.
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/run-analytics.md` for run metrics and error monitoring.
> See `references/examples/exports.md` for data export and download examples.
> For billing, usage metrics, and subscription: use the `cargo-billing` skill.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Scope — measure and export, not explain
This skill answers **"what happened"** and **"give me the data"**: metrics, counts, downloads, exports. The moment the question becomes **"why"** — why did this run fail, why is the output wrong or empty, which root cause explains these errors, why is this play so expensive — switch to the `cargo-diagnostics` skill; its runbooks sequence the raw surfaces into a diagnosis.
| The question sounds like… | Load |
| --- | --- |
| "What's the error rate?" / "How many runs failed this week?" / "Export the results / segment" | **this skill** |
| "Why did this run fail?" / "Run succeeded but the output looks wrong" | `cargo-diagnostics` → `references/run-trace.md` |
| "Why does this batch have errors? Which node keeps failing, and is it one cause or many?" | `cargo-diagnostics` → `references/batch-error-sweep.md` |
| "Why is this play so expensive? Where do the credits go?" | `cargo-diagnostics` → `references/play-optimize-credits.md` |
The two skills chain naturally: analytics **detects** (error rate spiked, batch reports failures), diagnostics **explains** (18 of 20 failures share one root cause), then analytics **retrieves** the clean results once the cause is fixed and the runs re-executed.
## Discover resources first
Most analytics commands require UUIDs. Discover them before querying.
```bash
cargo-ai orchestration play list # all plays (name, workflowUuid)
cargo-ai orchestration tool list # all tools (name, workflowUuid)
cargo-ai orchestration workflow list # all workflows (uuid only — no name)
cargo-ai ai agent list # all agents (uuid, name)
cargo-ai connection connector list # all connectors (uuid, name, integrationSlug)
cargo-ai storage model list # all models (uuid, name, slug)
```
## Quick reference
```bash
cargo-ai orchestration run get-metrics --workflow-uuid <uuid>
cargo-ai orchestration run download --workflow-uuid <uuid> --is-finished
cargo-ai orchestration run count --workflow-uuid <uuid> --statuses error
cargo-ai orchestration query execute "SELECT status, count() FROM runs GROUP BY status"
cargo-ai segmentation segment download --model-uuid <uuid> --filter '{"conjonction":"and","groups":[]}'
```
**Picking the right command:**
- `run get-metrics` / `run count` — workflow-scoped, predefined aggregations. Best when you already have a `workflowUuid`.
- `orchestration query execute` — ad-hoc SQL across the entire workspace (`runs`, `batches`, `spans`, `records`). Best for cross-workflow analytics, per-node breakdowns, and time-series.
- `run download` / `run download-outputs` — per-record output retrieval.
- `segment download` / `storage query execute` — storage data (Companies, Contacts, …).
## Workflow run metrics
Aggregated metrics for workflow runs (success/error rates, credits per node).
```bash
# Metrics for a workflow
cargo-ai orchestration run get-metrics --workflow-uuid <uuid>
# Scoped to a release, batch, or date range
cargo-ai orchestration run get-metrics --workflow-uuid <uuid> --release-uuid <uuid>
cargo-ai orchestration run get-metrics --workflow-uuid <uuid> --batch-uuid <uuid>
cargo-ai orchestration run get-metrics --workflow-uuid <uuid> \
--created-after <start-date> --created-before <end-date>
```
## Run count
Count runs matching specific criteria — useful for monitoring.
```bash
cargo-ai orchestration run count --workflow-uuid <uuid> --statuses error
cargo-ai orchestration run count --workflow-uuid <uuid> --is-finished \
--created-after <start-date> --created-before <end-date>
cargo-ai orchestration run count --workflow-uuid <uuid> --batch-uuid <uuid>
```
Supports: `--statuses`, `--batch-uuid`, `--release-uuid`, `--is-finished`, `--created-after`, `--created-before`, `--record-id`, `--record-title`.
For cross-workflow analytics or shapes that `run count` doesn't expose (per-node failure breakdowns, p95 durations, error rate over time), use `orchestration query execute` — see the [Ad-hoc execution analytics](#ad-hoc-execution-analytics-orchestration-query) section.
## Ad-hoc execution analytics (`orchestration query`)
Run SQL against orchestration runtime tables — `runs`, `batches`, `spans`, `records` — for analytics that the canned metrics commands don't cover. Tables are referenced without a schema prefix; workspace scoping is automatic. See `cargo-orchestration/references/examples/queries.md` for schemas and limits.
```bash
# Error rate across the workspace in the last day
cargo-ai orchestration query execute \
"SELECT countIf(status='error') / count() AS error_rate FROM runs WHERE created_at > now() - INTERVAL 1 DAY"
# Failed runs per workflow this week
cargo-ai orchestration query execute \
"SELECT workflow_uuid, count() AS errors FROM runs WHERE status='error' AND created_at > now() - INTERVAL 7 DAY GROUP BY workflow_uuid ORDER BY errors DESC"
# Per-node failure counts (last 24h)
cargo-ai orchestration query execute \
"SELECT node_slug, count() AS failures FROM spans WHERE execution_status='error' AND execution_started_at > now() - INTERVAL 1 DAY GROUP BY node_slug ORDER BY failures DESC"
# Credit spend by workflow this month
cargo-ai orchestration query execute \
"SELECT workflow_uuid, sum(credits_used_count) AS credits FROM batches WHERE created_at >= toStartOfMonth(now()) GROUP BY workflow_uuid ORDER BY credits DESC"
```
Read-only and capped: 30s execution time, 10 000 result rows, 10 000 000 rows scanned. Narrow with a `created_at`/`execution_started_at` predicate to stay under the row-scan cap.
## Downloading run results
Two distinct commands — pick the right one for the job.
### `run download` — one row per run, one column per node (gzipped CSV)
Returns `{"url": "..."}` — a signed URL to a **gzipped CSV**. Each row is a run: `_uuid`, `_workspace_uuid`, `_workflow_uuid`, `_record_id`, `_record_title`, `_created_at`, `_finished_at`, `_status`, `_error_message`, followed by **one column per node slug**.
**Each node column holds that execution's `title` — a truncated human-readable summary, not the node's output.** There is no `runContext` and no `executions[]` in this file. Treat it as a status board across many runs (which node errored, on which record), never as evidence of what a node produced — the same rule `cargo-diagnostics` applies to `title` everywhere else.
```bash
# Every run of a workflow
cargo-ai orchestration run download --workflow-uuid <uuid>
# Date range
cargo-ai orchestration run download --workflow-uuid <uuid> \
--created-after <start-date> --created-before <end-date>
# Specific statuses (run statuses: idle, pending, running, success, error,
# cancelling, cancelled, skipped — NOT "finished"/"failed")
cargo-ai orchestration run download --workflow-uuid <uuid> --statuses success,error
# Every run that reached a terminal state. `--is-finished` is `finished_at IS
# NOT NULL`, which is wider than success+error: cancelled and skipped runs
# stamp finishedAt too, so don't substitute one for the other.
cargo-ai orchestration run download --workflow-uuid <uuid> --is-finished
# From a specific batch
cargo-ai orchestration run download --workflow-uuid <uuid> --batch-uuid <uuid>
```
### `run download-outputs` — per-run input + output (CSV/JSON via signed URL)
**This is the canonical way to get action results out of the platform.** Maps to API `POST /v1/orchestration/runs/download-outputs`. Returns `{"url": "..."}` — a signed URL to a CSV (default) or JSON file. One row per run: the same `_`-prefixed run metadata, plus `input` (the first node's resolved config) and `output` (the chosen node's context, defaulting to the **last executed node** when `--output-node-slug` is omitted).
```bash
# --workflow-uuid is the only required flag
cargo-ai orchestration run download-outputs \
--workflow-uuid <uuid> \
--format json \
--limit 20
# Pin the output node explicitly, and filter by batch
cargo-ai orchestration run download-outputs \
--workflow-uuid <uuid> \
--output-node-slug <slug> \
--batch-uuid <uuid>
```
To find the `output-node-slug`: `cargo-ai orchestration release get <release-uuid>` → look at `nodes[].slug`. The terminal output node is typically named `output` or `end`. Without `--limit`, the file covers **every** matching run of the workflow, so pass one when you only need a sample.
### Getting the full `runContext` for several runs
You can't, in one call. The full per-node context is a **per-run S3 object**, and `orchestration run get <run-uuid>` is the only command that hydrates it — one run at a time. The two exports above are projections: `download` gives you node *titles* across many runs, `download-outputs` gives you first-node input + one node's output across many runs. For everything in between, loop `run get` over the UUIDs from the discovery ladder in [`../cargo-diagnostics/references/run-trace.md`](../cargo-diagnostics/references/run-trace.md) § 0.
Orchestration SQL is not an alternative here: `runs` and `spans` carry status, timing, and credits, but no node input/output columns.
## Downloading batch results
```bash
cargo-ai orchestration batch download --uuid <batch-uuid> --output-node-slug <node-slug>
```
To find the `output-node-slug`: run `cargo-ai orchestration release get <release-uuid>` (get the release UUID from the batch) and look at `nodes[].slug`.
## Handling partial batch failures
A batch with `status: "success"` can still contain individual run failures. Always inspect the batch for errors before treating results as complete.
**Step 1 — Check the batch summary:**
```bash
cargo-ai orchestration batch get <batch-uuid>
# → .runsCount = total records submitted
# → .executedRunsCount = records that reached a terminal state (success or error)
# → .failedRunsCount = records that errored
```
**Step 2 — Count and download the failed runs:**
```bash
cargo-ai orchestration run count \
--workflow-uuid <uuid> \
--batch-uuid <batch-uuid> \
--statuses error
cargo-ai orchestration run download \
--workflow-uuid <uuid> \
--batch-uuid <batch-uuid> \
--statuses error
```
**Step 3 — Diagnose.** Working out *why* they failed — grouping failures by root cause, picking exemplar runs, reading `runContext` — is the `cargo-diagnostics` skill's job: load `../cargo-diagnostics/references/batch-error-sweep.md` and feed it the batch UUID.
**Step 4 — Re-run only the failed records:**
After the diagnosis and fixing the underlying issue (connector credentials, bad input data, rate limits):
```bash
# Extract record IDs from the failed run download, then:
cargo-ai orchestration batch create \
--workflow-uuid <uuid> \
--data '{"kind":"recordIds","recordIds":["id1","id2","id3"]}'
```
**Filtering by node output slug:**
To download only a specific node's output from a batch (e.g. just the enrichment node, not the full run):
```bash
# 1. Get the release UUID from the batch
cargo-ai orchestration batch get <batch-uuid>
# → .releaseUuid
# 2. Find the node slug
cargo-ai orchestration release get <release-uuid>
# → nodes[].slug
# 3. Download that node's output
cargo-ai orchestration batch download \
--uuid <batch-uuid> \
--output-node-slug <node-slug>
```
## Segment data export
Filter JSON uses `conjonction` (not `conjunction`) — this is intentional. See the `cargo-orchestration` skill's `references/filter-syntax.md` for the full filter syntax.
```bash
# Full export (all records)
cargo-ai segmentation segment download \
--model-uuid <uuid> \
--filter '{"conjonction":"and","groups":[]}'
# With sorting and limit
cargo-ai segmentation segment download \
--model-uuid <uuid> \
--filter '{"conjonction":"and","groups":[]}' \
--sort '[{"columnSlug":"created_at","kind":"desc"}]' \
--limit 1000
```
**IMPORTANT:** `segment download` requires `--model-uuid`, not `--segment-uuid`. Get the `modelUuid` from `segment list`.
For live paginated queries with enrichment, use `segmentation segment fetch` from the `cargo-orchestration` skill.
## Help
Every command supports `--help`:
```bash
cargo-ai billing usage get-metrics --help
cargo-ai orchestration run download --help
cargo-ai segmentation segment download --help
```
Referenced files: 5
cargo-billing11.1 KB
---
name: cargo-billing
description: "Understand what Cargo is costing — remaining credits, usage broken down by workflow, connector, or agent, subscription state, and invoice history. Triggers: \"how many credits do I have left\", \"what did that cost\", \"why is my bill so high\", \"am I about to run out\", \"will this fit in our budget\", \"show me my invoices\", \"how much have I spent this month\", \"what plan am I on\", \"what do I get for free\", \"how many free credits\", \"can I afford this run\", \"add a card\", \"update my payment method\", \"why was my card declined\". Needs a token with admin access. Skip when: attributing spend to specific nodes or cutting a play cost — use cargo-diagnostics."
version: "1.1.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
---
# Cargo CLI — Billing
Billing and credit management: pulling usage metrics, checking subscription status, viewing invoices, and managing credits.
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/usage-metrics.md` for usage metric and subscription examples.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`. **Admin-only:** every command in this skill requires a token with admin access on the workspace. Non-admin tokens return `{"errorMessage":"forbidden"}`. When the full skill bundle is installed, [`../cargo/references/prerequisites.md`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover resources first
Usage metrics can be filtered and grouped by resource UUID. Discover them before querying.
```bash
cargo-ai orchestration play list # all plays (name, workflowUuid)
cargo-ai orchestration tool list # all tools (name, workflowUuid)
cargo-ai ai agent list # all agents (uuid, name)
cargo-ai connection connector list # all connectors (uuid, name, integrationSlug)
cargo-ai storage model list # all models (uuid, name, slug)
```
## Quick reference
```bash
cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD>
cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD> --group-by workflow_uuid
cargo-ai billing subscription get
cargo-ai billing subscription get-invoices
cargo-ai billing subscription update-payment-method --card-number <number> --card-exp <MM/YYYY> --card-cvc <cvc>
cargo-ai billing subscription create-portal-session
```
## Estimating cost before running a batch
Before triggering a large batch, estimate credit consumption to avoid unexpected charges.
**Step 1 — Check current credit balance:**
```bash
cargo-ai billing subscription get
# → subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount = remaining credits
```
**Step 2 — Estimate cost from a sample run:**
Run the workflow on a single record first and measure credits consumed:
```bash
# Run on one record
cargo-ai orchestration run create --workflow-uuid <uuid> --data '{...}'
# → poll to completion
# Check credits used for that run
cargo-ai billing usage get-metrics \
--from <today> --to <today> \
--workflow-uuid <uuid>
# → .totalUsage = credits consumed today for this workflow
```
**Step 3 — Project batch cost:**
```
estimated_cost = credits_per_record × number_of_records
```
Compare against `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount` before proceeding.
**Step 4 — Monitor during the batch:**
```bash
# Check running costs mid-batch
cargo-ai billing usage get-metrics \
--from <start-date> --to <today> \
--workflow-uuid <uuid>
```
**Cost levers:**
| Action | Effect |
|---|---|
| Use a cheaper model (e.g. `gpt-4o-mini` vs `gpt-4o`) | Significant reduction for AI nodes |
| Add `filter` nodes early in the graph | Skip ineligible records before expensive connector calls |
| Set `fallbackOnFailure: false` | Stop the run early on failures instead of continuing to downstream nodes |
| Reduce `maxSteps` on agent nodes | Limit how many tool calls an agent can make per record |
> To find out **which** node or provider dominates a play's spend before picking a lever, follow the attribution runbook in [`../cargo-diagnostics/references/play-optimize-credits.md`](../cargo-diagnostics/references/play-optimize-credits.md).
## Usage metrics
Pull credit and usage data for any time range, optionally filtered and grouped.
```bash
# Basic usage for a period
cargo-ai billing usage get-metrics --from <start-date> --to <end-date>
# Group by dimension
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by workflow_uuid
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by connector_uuid
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by integration_slug
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by model_uuid
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by agent_uuid
# Filter by specific resource
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --workflow-uuid <uuid>
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --agent-uuid <uuid>
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --connector-uuid <uuid>
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --integration-slug <slug>
# Specify unit
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit credits
```
`--group-by` values: `workflow_uuid`, `connector_uuid`, `model_uuid`, `integration_slug`, `agent_uuid`.
Available filters: `--workflow-uuid`, `--model-uuid`, `--connector-uuid`, `--integration-slug`, `--slug`, `--agent-uuid`. Combine with `--group-by` and `--unit`.
## Subscription and credits
```bash
cargo-ai billing subscription get # current plan, credits used/available, period dates
cargo-ai billing subscription get-invoices # invoice history (amounts in cents)
cargo-ai billing subscription get-credit-card # card on file
cargo-ai billing subscription update-payment-method # add or replace the card (see below)
cargo-ai billing subscription create-portal-session # Stripe portal URL for self-service billing
```
Remaining credits = `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount` from `subscription get`.
**Note:** Invoice amounts are returned in cents. Divide by 100 for the dollar value.
### The free tier
A new account starts with **100 free credits and no card on file**. When `subscription get` shows a fresh or near-fresh balance, answer cost questions against that budget rather than as an abstract number — "you've used 12 of your 100 free credits" is the useful answer to "how am I doing?", and it is also the honest one when the user is deciding whether to keep going.
What 100 credits buys, as ballpark anchors (per-action costs in [`../cargo-gtm/references/credits-cost-table.md`](../cargo-gtm/references/credits-cost-table.md)):
| Work | Cost | 100 credits ≈ |
|---|---|---|
| Source leads — `salesNavigator.searchLeads` | 0.02/record | ~5,000 leads |
| Enrich from a LinkedIn URL + verified email — `aiArk.enrichPerson` | 0.1 | ~1,000 people |
| Verify an email — `waterfall.verifyEmail` | 0.1 | ~1,000 checks |
| Full contact enrichment — `waterfall.enrichContact` | 2 | ~50 contacts |
| Find a phone — `FullEnrich.findPhone` | 6 | ~16 numbers |
The [quickstart demo](../cargo-quickstart/SKILL.md) spends about **0.5**. Phone lookups are the fastest way to burn a free tier, so phone is the **guarded lever**: the escalation tier runs 3–7 credits/record, ~10× email, and never belongs in a default chain — it enters a plan only on explicit user request, on qualified leads only. Full spend rules in [`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md).
### Adding a card
A workspace holds exactly one card. `update-payment-method` sets it, whether or not one is already on file, and takes the details three ways.
```bash
# Card details — no browser, nothing to hand off
cargo-ai billing subscription update-payment-method \
--card-number 4242424242424242 --card-exp 12/2030 --card-cvc 123
# Same, but keeps the number out of shell history and the process list
echo '{"number":"4242424242424242","expMonth":12,"expYear":2030,"cvc":"123"}' \
| cargo-ai billing subscription update-payment-method --card-stdin
# No card details — prints a Stripe-hosted form URL and waits for the card to land
cargo-ai billing subscription update-payment-method
```
**Prefer `--card-stdin`.** Anything passed as a flag is visible in shell history and to any process that can read the process list. Card details go from your machine straight to Stripe in exchange for a token; they never reach the Cargo API, and no output prints them.
**Never invent card details, and never reuse a number from elsewhere in the conversation.** Ask the user for them, or use the no-argument form and hand them the URL.
The no-argument form is the fallback when you have no details to submit: it prints a URL that opens directly on the card form, then polls until the card changes (`--timeout`, `--poll-interval`, `--no-open`). Relay that URL to the user — it works over SSH and in sandboxes.
Either way the card is verified against the issuer before it becomes the default, so a card that cannot be charged fails here rather than silently at the next renewal.
| Failure | What it means | What to do |
|---|---|---|
| `cardDeclined` + `declineCode` | The issuer refused the verification | Read `declineCode`. On a spend-limited virtual card, `insufficient_funds` or a limit code means the budget or merchant restrictions rule us out — ask the cardholder to raise it |
| `authenticationRequired` | The card wants 3-D Secure, which needs the cardholder present | Re-run with no arguments and hand the user the hosted-form URL |
| `paymentMethodNotFound` | The details did not resolve to a usable card | Re-check the number and expiry with the user |
Card updates are rate-limited to **10 per hour per workspace** (shared with setup intents). Retrying a declined card burns that budget — fix the cause rather than looping.
## Help
Every command supports `--help`:
```bash
cargo-ai billing usage get-metrics --help
cargo-ai billing subscription get --help
cargo-ai billing subscription get-invoices --help
```
Referenced files: 4
cargo-cdk12.1 KB
---
name: cargo-cdk
description: "Manage a whole Cargo workspace as code — declare connectors, models, plays, tools, agents, MCP servers, segments, context, folders, files, workers, and apps in TypeScript, then reconcile them with `cargo-ai cdk` (init → types → plan → deploy), the way you would run Pulumi or the AWS CDK. Triggers: \"as code\", \"in git\", \"version-controlled\", \"reproducible\", \"Terraform for Cargo\", \"set up a whole workspace\", \"staging and production\", \"deploy from CI\", \"review this in a PR\", \"cargo.state.json\", \"scaffold from a template\", \"is there a cookbook for this\", \"start from a cookbook\". Skills with a CDK example (TAM building, account scoring, contact sourcing, routing, AI SDR, rep cockpit) live in gtm-skills; menu in references/cookbooks.md. Skip when: it is a one-off operation, a read, or an ad-hoc query — use the matching capability skill."
version: "1.2.3"
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
---
# Cargo CDK — declarative workspace-as-code
Use this skill to define a Cargo workspace in TypeScript (`define*` builders from
`@cargo-ai/cdk`) and reconcile it to live infrastructure with `cargo-ai cdk deploy`.
It is the **declarative** counterpart to the imperative capability skills: instead
of running one CLI command per resource, you write the whole graph once and deploy
it repeatably, with a committed `cargo.state.json` linking your code to what Cargo
created.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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
cargo-ai cdk --help # `unknown command` = CLI too old; reinstall @cargo-ai/cli@latest
```
Two CDK-specific extras: the project needs **`@cargo-ai/cdk` as a dependency** for the `define*` builders you import (`cargo-ai cdk init` scaffolds a `package.json` with it — then `npm install`), and the `cargo-ai cdk` domain ships with the CLI itself.
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## 1) What this skill governs
- **Authoring** every Cargo resource with a `define*` builder that returns a
**handle**; wiring resources by passing handles to each other (the dependency
graph is your variable graph).
- **Deploying** the graph: `plan` (offline diff) → `deploy` (create/update, write
state) → `destroy` (tear down). Plus drift (`refresh`), adoption (`import`), and
recovery (`rollback`).
- **Typing** the config against your workspace's real integration schemas
(`cargo-ai cdk types`).
The CDK spans **every** resource kind — so it overlaps every imperative capability
skill (`cargo-connection`, `cargo-storage`, `cargo-ai`, `cargo-orchestration`,
`cargo-content`, `cargo-hosting`, …). Which to reach for is the first decision:
## 2) CDK or the CLI? — the routing decision
> **Declarative (this skill) vs imperative (a capability skill).**
Use the **CDK** when the user is **managing resources as an artifact**:
- "Set up / stand up / bootstrap a whole workspace (as code / from a template)."
- "Make this reproducible / version-controlled / in git / repeatable across
environments (dev → prod)."
- "Deploy these connectors + models + agents together" (a multi-resource graph
wired by dependency).
- Anything that should be re-runnable and diffable, where losing the definition
would be a problem.
Use the matching **capability skill** (imperative `cargo-ai <domain>`) when the
user is doing a **one-off operation** or **exploring**:
- "Create one connector", "add a column to this model", "list connectors",
"run this workflow", "query storage", "read this agent's memory."
- Any read, ad-hoc query, or single mutation that doesn't need to live in code.
When unsure, ask whether the result should be committed and re-deployable. If yes
→ CDK. If it's a quick action or a read → the capability skill (see the
[`cargo` router](../cargo/SKILL.md) to pick the right domain).
## 3) The lifecycle
```
cargo-ai cdk init <dir> scaffold a project from a template (blank | full)
│
cargo-ai cdk types generate per-workspace types for typed config (optional)
│
(author define* files) importing a .ts file IS registration — no manifest
│
cargo-ai cdk plan offline: compile the graph, diff against cargo.state.json
│
cargo-ai cdk deploy create/update resources in dependency order, write state
│
cargo-ai cdk destroy tear down resources recorded in state
```
> **`cdk plan` says what resources change; it doesn't show what a play does.**
> For a `definePlay` / `defineTool` graph past three nodes, present a Mermaid
> flowchart of the node graph alongside the plan — routing, fallbacks, and which
> nodes bill on every scheduled run are what the reviewer is approving. Generate it
> from the deployed release after the first deploy, or from the node array while
> authoring:
> [`../cargo-orchestration/references/node-diagram.md`](../cargo-orchestration/references/node-diagram.md).
Side branches: `cargo-ai cdk refresh` (read-only drift report) · `deploy --refresh`
(re-apply code over out-of-band edits) · `deploy --prune` (delete resources removed
from code) · `cargo-ai cdk import <id> <uuid>` (bind an existing live resource into
state) · `cargo-ai cdk rollback` (restore the pre-deploy state snapshot).
## 4) Documentation hierarchy
- **Level 1** — `SKILL.md` (this file): the decision model, lifecycle, critical
rules, and routing.
- **Level 2** — Guides:
[`guides/authoring-resources.md`](guides/authoring-resources.md),
[`guides/deploy-and-state.md`](guides/deploy-and-state.md),
[`guides/typed-config.md`](guides/typed-config.md).
- **Level 2.5** — Recipes: [`recipes/*.md`](recipes/) — step-by-step playbooks to
follow as your execution plan.
- **References** — [`references/resources.md`](references/resources.md) (the full
builder catalog), [`references/commands.md`](references/commands.md) (every
`cargo-ai cdk` subcommand + flags),
[`references/troubleshooting.md`](references/troubleshooting.md), and
[`references/examples/full-workspace.md`](references/examples/full-workspace.md).
## 5) Read behavior — match the task to a doc and READ IT
| When the task involves… | Read this first | What it gives you |
|---|---|---|
| Writing `define*` files, wiring resources, `secret()`/`env()`, `defineWorkflow` bodies (tool/play logic) | [`guides/authoring-resources.md`](guides/authoring-resources.md) | The builder catalog, the handle/ref model, secrets, and how workflow bodies compile. |
| `plan` / `deploy` / `destroy`, the state file, drift, adopting existing resources, CI | [`guides/deploy-and-state.md`](guides/deploy-and-state.md) | The deploy lifecycle, `cargo.state.json` semantics, drift/import/rollback, async builds. |
| Typed config, `cargo-ai cdk types`, tsconfig wiring, `integrations.*` in workflow bodies | [`guides/typed-config.md`](guides/typed-config.md) | What `cdk types` generates and how to wire it into your project. |
| A field/spec/output for a specific builder | [`references/resources.md`](references/resources.md) | Every builder → spec fields → which ref each takes → outputs. |
| Exact command flags | [`references/commands.md`](references/commands.md) | Every `cargo-ai cdk` subcommand and its flags. |
| A deploy error / footgun | [`references/troubleshooting.md`](references/troubleshooting.md) | The known failure modes and fixes. |
| A known GTM outcome, before authoring one | [`references/cookbooks.md`](references/cookbooks.md) | The cookbook menu: gtm-skills that carry a worked CDK example, and the adaptations each supports. |
### Cookbooks — check the menu before authoring a known outcome from scratch
[`getcargohq/gtm-skills`](https://github.com/getcargohq/gtm-skills) holds, beside its
one-off skills, **cookbooks**: skills that carry worked CDK resources, the same job as a deployed
pipeline that keeps producing the result (TAM building, account scoring, contact
sourcing, routing engine, AI SDR, rep cockpit, …). Every folder is self-contained: its
own models, connectors and folders, no shared foundation, no requires graph.
**The menu is local: [`references/cookbooks.md`](references/cookbooks.md).** Read it
before authoring a common GTM outcome from scratch. It is generated from gtm-skills'
`catalog.json`, so it cannot drift.
**A cookbook is a worked example, not a template to fill in.** Each one declares in its `SKILL.md` what may be reshaped, what must hold or it stops
working, and what has to be answered either way, and it carries its own procedure:
look at the repo, `cargo-ai cdk init --template blank` if there is no CDK project yet,
copy the folder in as a sibling and reconcile it with what is already declared, adapt,
plan and stop, deploy on a yes, walk its `Done when`. There is no scaffolder or copy
tool in the middle: **you place the code**, because you can see the project and a tool
cannot.
```sh
npx skills add getcargohq/gtm-skills/tam-building # then: "keep our TAM current"
cargo-ai cdk init my-project --template blank # only if there is no CDK project yet
```
**If you are mid-task and the skill is not in this session**, run the `skills add`
above and read `.agents/skills/<slug>/SKILL.md` directly; no reload needed. To read
one without installing, `npx skills use getcargohq/gtm-skills@<slug>` prints it.
**Routing rule: one-off versus standing.** A user who wants the list today wants
`cargo-gtm` (or gtm-skills' one-off `build-tam-list`); a user who wants a pipeline
that keeps producing it wants `tam-building`. The same words describe both ("build
our TAM"), so listen for whether the result is meant to keep arriving. A cookbook
matches → install it and follow it. No match → author from the recipes below.
**Never `cargo-ai cdk init --force` into a directory that is not empty.** It replaces
the project's `package.json` and reverts adapted code, while `cargo.state.json`
survives, so the next `plan` diffs a live workspace against code nobody wrote. Copy the
skill folder in as a sibling instead.
Caveat: the examples typecheck, but they are not yet deploy-verified against a live
workspace, and every one is `to-be-approved`. Treat each skill's `Done when` as the
acceptance test, and always review `cargo-ai cdk plan` before deploying.
### Recipes — follow step-by-step when one matches
| Recipe | Use when… |
|---|---|
| [`recipes/scaffold-a-workspace.md`](recipes/scaffold-a-workspace.md) | Standing up a new workspace from scratch (`init --template full` → types → plan → deploy). |
| [`recipes/add-connector-and-model.md`](recipes/add-connector-and-model.md) | Adding a data source + a model sourced from it, wired by handle. |
| [`recipes/build-an-agent.md`](recipes/build-an-agent.md) | Composing a model + tool + agent (with `uses` / `models` / `tools`) and deploying. |
| [`recipes/migrate-existing-workspace.md`](recipes/migrate-existing-workspace.md) | Bringing an already-live workspace under CDK management via `cdk import`. |
| [`recipes/deploy-from-ci.md`](recipes/deploy-from-ci.md) | Deploying non-interactively from CI (token auth + committed state). |
## 6) Critical rules
## Help
- `cargo-ai cdk --help` and `cargo-ai cdk <subcommand> --help` for the live flag
surface.
- When a documented command/flag/response doesn't match what you observe, file a
report: `cargo-ai workspaceManagement report create` (see
[`../cargo-workspace-management/SKILL.md`](../cargo-workspace-management/SKILL.md)).
Referenced files: 14
cargo-connection16.5 KB
---
name: cargo-connection
description: "Connect Cargo to an external system and find out what it can do — authenticate connectors, browse the integration catalog, and resolve the `connectorUuid` and `actionSlug` a workflow node needs. Triggers: \"connect my HubSpot\", \"is Salesforce connected\", \"what integrations do you support\", \"can Cargo talk to <tool>\", \"what actions does <provider> have\", \"I need the connector UUID\", \"set up the API key for\", \"it is asking for credentials again\", \"why is this connector failing auth\", \"list my connectors\". 138 integrations including HubSpot, Salesforce, Attio, Pipedrive, Outreach, Salesloft, Slack, Snowflake, BigQuery, Postgres, Stripe, and Google/LinkedIn ad audiences. Skip when: choosing between enrichment providers for a GTM job — use cargo-gtm and its provider playbooks."
version: "1.4.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
---
# Cargo CLI — Connections
Connector and integration management: listing connectors, discovering available integrations, and managing authenticated connector instances.
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/connectors.md` for connector CRUD and discovery examples.
> See `references/examples/integrations.md` for listing available integrations and OAuth flows.
> For third-party connector rate limit handling and retry config in workflows, see `cargo-orchestration/references/polling.md` and `cargo-orchestration/references/troubleshooting.md`. Native integrations do not have rate limits.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Key concepts
**Integration:** The external service type (e.g. HubSpot, Clearbit, Salesforce). Integrations define what actions are available.
**Connector:** An authenticated instance of an integration. One integration can have multiple connectors (e.g. two different HubSpot accounts). Connectors are what you reference in workflow node graphs.
## Discover resources first
**Looking for an action? Search for it — don't browse the catalog.** Two keyword
searches cover the whole surface, and both beat paging `integration list` or
reading a whole `integration get` payload:
```bash
cargo-ai orchestration action list <query> # START HERE — connector + native + tools + agents.
# Returns a ready-to-run action object (connectorUuid
# resolved) and the action's credit costs.
cargo-ai connection action search <query> --credits-only # connector catalog only, but filters by category
# and by "is it paid" — which `action list` cannot.
```
Reach for the catalog commands when you need the *integration*, not an action —
its auth fields, its extractors, or the full input schema of an action you have
already picked:
```bash
cargo-ai connection connector list # all authenticated connectors
cargo-ai connection integration list # all available integration types
cargo-ai connection integration list --search "hubspot" # search by name
cargo-ai connection integration get <slug> # one integration's actions + input schemas
cargo-ai connection native-integration get # built-in Cargo actions only (NOT third-party)
```
### Which action search?
| | `orchestration action list` | `connection action search` |
|---|---|---|
| Covers | connector, native, **tools, agents** | connector catalog only |
| Returns | a runnable `action` object with `connectorUuid`, workspace connectors, `credits`, autocompletes | `integrationSlug` + `actionSlug`, category, `credits` — you assemble the action yourself |
| Filters | `--kind`, `--integration-slug`, `--limit` | `--category`, `--integration`, **`--credits-only`**, `--limit` |
| Needs | CLI ≥ 1.0.66 | CLI ≥ 1.0.36 |
Default to `action list` — it is the one that hands you something you can execute.
Switch to `action search` for the two questions it alone answers: *which paid
actions match this?* (`--credits-only`) and *what does this category offer?*
(`--category`). Both rank an action-slug or name hit above an integration hit,
above a description hit, and require **all** query terms to match.
### `integration get` vs `native-integration get`
These two commands return **different sets of actions** and are not interchangeable:
| Command | Third-party service actions (HubSpot, Salesforce, Clearbit, …) | Built-in Cargo actions (HTTP, transforms, utilities) | When to use |
|---|---|---|---|
| `integration get <slug>` | ✓ | ✗ | You need actions for a specific third-party service — **use this for HubSpot, Salesforce, Clearbit, etc.** |
| `native-integration get` | ✗ | ✓ | You need Cargo-native capabilities that don't belong to any specific third-party connector |
**Example:** To find HubSpot-specific actions, use `integration get hubspot` — `native-integration get` will not return them.
## Quick reference
```bash
cargo-ai connection connector list --integration-slug <slug>
cargo-ai connection connector create --integration-slug <slug> --slug <slug> --name <name>
cargo-ai connection connector update --uuid <uuid> --name <name>
cargo-ai connection connector remove <connector-uuid>
cargo-ai connection connector get <connector-uuid>
cargo-ai connection connector autocomplete --connector-uuid <uuid> --slug <slug> --params '<json>'
cargo-ai connection integration list
cargo-ai connection integration get <slug>
cargo-ai connection integration get-documentation <slug>
cargo-ai connection native-integration get
```
## Connectors
Connectors are authenticated connections to external services.
```bash
# List all connectors
cargo-ai connection connector list
# Create a connector
cargo-ai connection connector create \
--integration-slug clearbit \
--slug clearbit_production \
--name "Clearbit - Production"
# Update a connector
cargo-ai connection connector update --uuid <connector-uuid> --name "Clearbit - Staging"
# Remove a connector
cargo-ai connection connector remove <connector-uuid>
# Check if a connector slug is taken
cargo-ai connection connector exists-by-slug --slug clearbit_production
```
**Note:** Creating a connector requires `--slug` (unique identifier) in addition to `--name` (display name) and `--integration-slug`. For OAuth-based integrations, the authentication flow is completed separately via `connection integration complete-oauth`.
## Integrations
Integrations define the available services and their connector actions.
```bash
# List all available integrations
cargo-ai connection integration list
# Filter by category
cargo-ai connection integration list --category enrichment
# Search by name
cargo-ai connection integration list --search "hubspot"
# Find by exact slug(s)
cargo-ai connection integration list --slugs clearbit
# Only integrations that have actions (usable in workflow nodes)
cargo-ai connection integration list --has-actions true
# Only integrations that have extractors (can sync data into models)
cargo-ai connection integration list --has-extractors true
# Get built-in Cargo actions and extractors (NOT third-party connector actions)
cargo-ai connection native-integration get
```
**Integration categories:** `engagement`, `marketing`, `sales`, `finance`, `analytics`, `freeform`, `success`, `support`, `enrichment`, `storage`, `custom`.
Use `integration get <slug>` to discover all actions available for a specific third-party service (e.g. HubSpot, Salesforce). Use `native-integration get` only for built-in Cargo actions — it does **not** return HubSpot or other service-specific actions. Actions are referenced by `actionSlug` in workflow node graphs (see the `cargo-orchestration` skill's `references/nodes.md`).
## Connector autocomplete — fetching available values for action fields
Some action fields don't accept freeform input — their allowed values must be fetched dynamically from the connector. When you inspect an action's config (via `integration get <slug>` or `native-integration get`), look at the `uiSchema` alongside the `jsonSchema`. If a field's `uiSchema` contains `"ui:widget": "IntegrationAutocompleteWidget"`, the valid values for that field **must** be retrieved using `connector autocomplete`.
### How to detect autocomplete fields
When an action's config looks like this:
```json
{
"jsonSchema": {
"type": "object",
"properties": {
"objectType": { "type": "string", "description": "The object type" }
}
},
"uiSchema": {
"objectType": {
"ui:widget": "IntegrationAutocompleteWidget",
"ui:options": {
"slug": "listObjects",
"allowRefresh": true
}
}
}
}
```
The `objectType` field requires autocomplete. The `ui:options.slug` (`"listObjects"`) is the autocomplete slug you pass to `connector autocomplete`.
### How to call connector autocomplete
```bash
cargo-ai connection connector autocomplete \
--connector-uuid <connector-uuid> \
--slug <autocomplete-slug> \
--params '{}'
```
| Flag | Required | Description |
| ------------------ | -------- | ----------------------------------------------------------------- |
| `--connector-uuid` | yes | The UUID of the connector to autocomplete against |
| `--slug` | yes | The autocomplete slug from `uiSchema[field]["ui:options"].slug` |
| `--params` | yes | JSON object of parameters (use `{}` when none are needed) |
| `--value` | no | Search string to filter results |
| `--refresh` | no | Bypass cache and fetch fresh results |
### Autocomplete with parameters
Some autocomplete fields depend on the value of another field. This is indicated by a `params` object in `ui:options`:
```json
{
"uiSchema": {
"objectType": {
"ui:widget": "IntegrationAutocompleteWidget",
"ui:options": { "slug": "listObjects" }
},
"propertyName": {
"ui:widget": "IntegrationAutocompleteWidget",
"ui:options": {
"slug": "listObjectProperties",
"params": { "objectType": "$this.$parent.objectType" }
}
}
}
}
```
Here, `propertyName` depends on the selected `objectType`. Replace the `$this.$parent...` expression with the actual value you chose:
```bash
# 1. First, get the list of object types
cargo-ai connection connector autocomplete \
--connector-uuid <uuid> --slug listObjects --params '{}'
# 2. Then, get properties for the chosen object type
cargo-ai connection connector autocomplete \
--connector-uuid <uuid> --slug listObjectProperties \
--params '{"objectType": "contacts"}'
```
### Response format
```json
{
"results": [
{ "label": "Contacts", "value": "contacts" },
{ "label": "Companies", "value": "companies" },
{ "label": "Deals", "value": "deals" }
]
}
```
Use the `value` field in your node config. The `label` is the human-readable display name. Results may also include optional `description` and `parent` fields.
### End-to-end example: configuring a HubSpot action
```bash
# 1. Find your HubSpot connector UUID
cargo-ai connection connector list --integration-slug hubspot
# 2. Get HubSpot actions and inspect their config + uiSchema
cargo-ai connection integration get hubspot
# → The "findRecords" action has objectType with autocomplete slug "listObjects"
# 3. Fetch available object types
cargo-ai connection connector autocomplete \
--connector-uuid <hubspot-connector-uuid> \
--slug listObjects --params '{}'
# → Returns: contacts, companies, deals, tickets, etc.
# 4. Fetch properties for the chosen object type
cargo-ai connection connector autocomplete \
--connector-uuid <hubspot-connector-uuid> \
--slug listObjectProperties \
--params '{"objectType": "contacts"}'
# → Returns: email, firstname, lastname, phone, etc.
# 5. Use these values in your workflow node config
```
## Using connector actions in workflows
Connector actions are used as nodes in workflow graphs. To use an action:
```bash
# 1. Find your connector UUID
cargo-ai connection connector list
# → Filter the output by integrationSlug to find the right connector
# 2. Discover the action — search first, and only then read its schema
cargo-ai orchestration action list <keywords> --integration-slug <integration-slug>
cargo-ai connection integration get <integration-slug>
# → actions are keyed by actionSlug, with config.jsonSchema (input) for each
# → many actions also carry output.schema — the JSON Schema of what the action
# emits; use it to wire downstream nodes instead of guessing (absent on some actions)
# → Or use get-documentation for a plain text overview
# → Or use native-integration get for built-in Cargo actions (not third-party)
# 3. Reference the connector and action in a node graph
# See cargo-orchestration references/nodes.md for the full node syntax
```
### Reading an action's input schema — and where the inputs go
An action's **input** fields live at `actions.<slug>.config.schema` in the `integration get <slug>` output (`config.jsonSchema` is the same schema decorated for the form UI). Read it before calling an action — don't guess field names.
```bash
# the required input fields for an action:
cargo-ai connection integration get linkedin \
| jq '.integration.actions.connectProfile.config.schema'
# → required: linkedinProfileUrl, identityIds
```
Two footguns:
- **For a top-level action (`action execute` / `execute-batch`), the input values go in `--data`, NOT in the action's `config`.** The fields described by `config.schema` are the `--data` payload; the action definition carries no `config` key at all. **Misplacing them is no longer a loud failure:** older backends rejected the call with `A top-level action does not use action.config; pass the action's inputs via data instead.`, newer ones drop `config` on the way in and run the action with **no inputs at all** — you get a missing-required-field error from the provider, or an empty result, not a message about `config`. If an action comes back empty for no obvious reason, check that the inputs are in `--data`. (Inside a workflow **node graph** those same fields go in the node's `config` — see `cargo-orchestration/references/nodes.md`. The "`--data`, not `config`" rule is specific to `action execute`/`execute-batch`.)
- **Some inputs must be resolved first via autocomplete.** If a field's `uiSchema` carries `IntegrationAutocompleteWidget`, fetch its values with `connector autocomplete` (above). Notably, LinkedIn engagement/extraction actions (`connectProfile`, `visitProfile`, `extractEventAttendees`, `extractProfileViewers`) require `identityIds` — the connected account that *acts* — resolved via the `listIdentityIds` autocomplete. A `must match format "uuid"` error means that identity is missing.
Example connector node (Clearbit company enrichment):
```json
{
"uuid": "node-uuid",
"slug": "enrich",
"kind": "connector",
"integrationSlug": "clearbit",
"actionSlug": "enrichCompany",
"connectorUuid": "<clearbit-connector-uuid>",
"config": {
"domain": {
"kind": "templateExpression",
"expression": "{{nodes.start.domain}}",
"instructTo": "none",
"fromRecipe": false
}
},
"childrenUuids": ["end-node-uuid"],
"fallbackOnFailure": false,
"position": { "x": 0, "y": 166 }
}
```
## Help
Every command supports `--help`:
```bash
cargo-ai connection connector list --help
cargo-ai connection connector create --help
cargo-ai connection integration list --help
```
Referenced files: 5
cargo-content6.04 KB
---
name: cargo-content
description: "Manage the knowledge a Cargo workspace holds — upload files (PDF, CSV, text), rename and organize them, and build native or connector-backed libraries that sync from an external source, so agents can retrieve them (RAG). Triggers: \"upload this PDF\", \"add these docs as knowledge\", \"build a knowledge base\", \"sync our help center into Cargo\", \"what files are in the workspace\", \"index this folder\", \"attach our pricing sheet\". Skip when: wiring the file or library into an agent — use cargo-ai; uploading a CSV that drives a batch run — that is a workspace-management file upload."
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
---
# Cargo CLI — Content
Workspace **knowledge** management: upload and organize **files** (PDFs, CSVs, text) and group or sync them into **libraries**. These are the binary/grouped knowledge resources that ground agent responses (retrieval-augmented generation, RAG).
> **New top-level domain (CLI ≥ 1.0.19).** Files and libraries moved out of the `ai` domain into the `content` domain — `cargo-ai content file …` and `cargo-ai content library …`. The old `cargo-ai ai file …` commands no longer exist; an `unknown command` error means you're on the old path.
> For **attaching** a file or library to an agent (via the release `resources` array), use [`cargo-ai`](../cargo-ai/SKILL.md).
> For **folders** that organize files, use [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md) (`cargo-ai workspaceManagement folder …`).
> For batch-run **input** files (CSVs uploaded to drive a batch), that's a different surface — `cargo-ai workspaceManagement file upload` — documented in [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md).
> See `references/examples/files.md` for end-to-end file, library, and attach-to-agent examples.
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover resources first
```bash
cargo-ai content file list # all uploaded files (uuid, name, contentType, size)
cargo-ai content library list # knowledge libraries (native or connector-backed)
```
## Files
Upload files (PDFs, CSVs, text) so an agent can ground its responses in specific knowledge. The upload response includes the `uuid` you reference when attaching the file to an agent release (see [`cargo-ai`](../cargo-ai/SKILL.md)).
```bash
# List all files
cargo-ai content file list
# Get a single file
cargo-ai content file get <file-uuid>
# Upload a file (optionally straight into a folder)
cargo-ai content file upload --file ./knowledge-base.pdf
cargo-ai content file upload --file ./knowledge-base.pdf --folder-uuid <folder-uuid>
# Update a file's name or folder
cargo-ai content file update --uuid <file-uuid> --name "Q1 Research Notes"
cargo-ai content file update --uuid <file-uuid> --folder-uuid <folder-uuid>
# Remove a file
cargo-ai content file remove <file-uuid>
```
> **Reading content files from the context sandbox.** Uploaded content files are also available **read-only** under `.files/` in the context runtime sandbox, so a command run there can consume them — e.g. `cargo-ai context runtime execute --command ls --args '["-1",".files"]'`. The directory sits outside the committed context tree (never pushed, not writable); to add or change files use `content file` here. See [`cargo-context`](../cargo-context/SKILL.md).
## Libraries
A library groups files into one resource an agent can reference. There are two kinds:
- **`native`** — workspace-managed collections of uploaded files.
- **`connector`** — synced from an external source (e.g. a help center or knowledge base) through an unstructured-data extractor (`--extractor-slug`). Get the `connectorUuid` from [`cargo-connection`](../cargo-connection/SKILL.md).
```bash
# List libraries (filter by kind or connector)
cargo-ai content library list
cargo-ai content library list --kind native
cargo-ai content library list --kind connector --connector-uuid <connector-uuid>
# Get a single library
cargo-ai content library get <library-uuid>
# Create a connector-backed library
cargo-ai content library create \
--name "Help Center" \
--connector-uuid <connector-uuid> \
--extractor-slug <extractor-slug> \
--folder-uuid <folder-uuid> \
--config '{}'
# Update / remove
cargo-ai content library update --uuid <library-uuid> --name "Updated Name"
cargo-ai content library remove <library-uuid>
```
## Attaching to an agent
Files and libraries are knowledge **resources** — they do nothing until attached to an agent via that agent's draft release `resources` array, then deployed. That wiring lives in [`cargo-ai`](../cargo-ai/SKILL.md) (`ai release update-draft --resources …` → `ai release deploy-draft`). See `references/examples/files.md` for the upload → attach → deploy sequence.
## Help
Every command supports `--help`:
```bash
cargo-ai content file upload --help
cargo-ai content library create --help
```
Referenced files: 4
cargo-context16.9 KB
---
name: cargo-context
description: "Read and write the workspace GTM knowledge base — the git-backed repository of markdown describing ICPs, personas, plays, proof points, objections, competitors, and signals — plus its runtime sandbox and typed knowledge graph. Triggers: \"document our ICP\", \"write up this persona\", \"what is our positioning\", \"add a battlecard\", \"capture this objection\", \"what do we know about <segment>\", \"update our context\", \"what is in the context repo\", \"who do we sell to\". Skip when: discovering who actually buys from you by analyzing won/lost data — that is cargo-gtm (this skill writes the conclusion down, it does not derive it); storing structured records rather than prose — use cargo-storage; attaching documents to an agent for RAG — use cargo-content."
version: "1.2.2"
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
---
# Cargo CLI — Context
The **context** is a git-backed repository of typed markdown/MDX files that captures a workspace's GTM knowledge (company narrative, ICPs, personas, plays, proof, objections, etc.) and is read/written by both humans and agents. The `cargo-ai context` domain has two subdomains you'll use:
- **runtime** — browse, read, write, edit, and execute against the workspace's runtime sandbox (a checked-out copy of the context repo). `write`/`edit` are pushed to the default branch; `execute` runs are **not** pushed.
- **graph** — build/load the knowledge graph derived from every markdown/MDX file in the context repo.
> The canonical example of a context repository is [`getcargohq/cargo-workspaces`](https://github.com/getcargohq/cargo-workspaces). Read its `README.md` to understand the domain layout and file conventions before writing new entries.
> For uploading runtime-independent files (CSVs, PDFs) used in batch runs, use [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md) (`cargo-ai workspaceManagement file upload`) instead.
> For RAG file attachments to agents, use [`cargo-ai`](../cargo-ai/SKILL.md) (`cargo-ai content file upload`).
> See `references/conventions.md` for the full context repo structure and per-domain templates.
> See `references/response-shapes.md` for the JSON shapes returned by each `cargo-ai context` command.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/authoring.md` for end-to-end add / edit / delete recipes.
> See `references/examples/lifecycle.md` for the bootstrap + refresh-from-calls playbook.
> See `references/examples/graph-queries.md` for inspecting the knowledge graph.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`. `runtime write` and `runtime edit` commit and push to the workspace's context repo, so confirming `workspace.name` first is non-negotiable. When the full skill bundle is installed, [`../cargo/references/prerequisites.md`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover the context first
Before editing anything, see what's in the context repo:
```bash
cargo-ai context runtime browse # list entries at the runtime sandbox root
cargo-ai context graph get # full knowledge graph derived from the repo's md/mdx files
```
## Quick reference
```bash
# Runtime sandbox (checked-out copy of the context repo)
cargo-ai context runtime browse [--path <path>]
cargo-ai context runtime read --path <path> [--start-line <n>] [--end-line <n>]
cargo-ai context runtime write --path <path> --content <content> [--commit-message <message>]
cargo-ai context runtime edit --path <path> --old-string <old> --new-string <new> [--commit-message <message>]
cargo-ai context runtime execute --command <command> [--args <json>]
# Knowledge graph
cargo-ai context graph get
```
## Runtime sandbox
The **runtime sandbox** is a checked-out, executable copy of the context repository. It's the surface you use to read and modify context files, and to run commands against them.
Two important behaviors to remember:
- **`write` and `edit` push to the default branch** of the context repo. They are not local-only.
- **`execute` does *not* push.** Changes made to files by a shell command run via `execute` stay in the sandbox and are discarded — use `execute` for builds, tests, or inspection, not for committing edits.
**Uploaded content files are available read-only under `.files/`.** The workspace's `content file` uploads (PDFs, CSVs, text — see [`cargo-content`](../cargo-content/SKILL.md)) appear in the sandbox under a `.files/` directory, so a command run via `execute` (or `read`/`browse`) can consume them — e.g. `cargo-ai context runtime execute --command ls --args '["-1",".files"]'`. It sits **outside the committed context tree**: the sandbox's auto-commit skips it, so nothing under `.files/` is ever pushed to the context repo, and you can't add or change content files from here (use `cargo-ai content file …` instead).
Because writes push immediately, **confirm the target workspace before the first `write`/`edit`**:
```bash
cargo-ai whoami # → workspace.uuid, workspace.name
```
Read the workspace name back to the user. If the session is for a specific client, make sure `workspace.name` matches before authoring anything — there is no dry-run mode. If `workspace.name` is generic or ambiguous (e.g. "Main", "Test", a person's name, an internal codename), don't guess — ask the user for the company name and canonical domain (`example.com`) and confirm both before the first write. If you logged in without pinning a workspace, re-run `cargo-ai login --oauth --workspace-uuid <uuid>` (or `--token <workspace-scoped-token>` for non-interactive use).
Edits derived from sales-call analysis should be applied **one at a time with human review**, not batched. Looping an agent over many calls tends to overweight the loudest signal and miss nuance — see `references/examples/lifecycle.md` for the call-refresh playbook.
### Browse and read
```bash
# List entries at the root of the runtime sandbox
cargo-ai context runtime browse
# List entries under a subpath (e.g. a domain folder like persona/ or play/)
cargo-ai context runtime browse --path persona
# Read a full file
cargo-ai context runtime read --path persona/vp-sales-mid-market.md
# Read only a line range (1-indexed, inclusive on both ends)
cargo-ai context runtime read --path play/inbound-trial-to-paid.md --start-line 1 --end-line 40
```
### Write a new file
`write` creates (or overwrites) a file and pushes a commit to the default branch.
Begin every `.md`/`.mdx` file with a YAML frontmatter block setting `title` and `description`. Frontmatter is **not validated** — a file with missing, empty, or malformed frontmatter is still written and committed; it just indexes poorly in the graph (a missing `title` falls back to the filename, the node summary to the first paragraph). `write` can still fail for other reasons — `repositoryNotFound`, `syncConflict`, `syncFailed`, `failedToWrite`, or `deniedPath` (e.g. writing under `.files/`); see `references/response-shapes.md`.
```bash
cargo-ai context runtime write \
--path persona/vp-sales-mid-market.md \
--content "$(cat <<'EOF'
---
title: VP of Sales, mid-market
description: Owns pipeline, quota, and rep productivity at a 200–2,000-person company.
---
## Role
- Title: VP of Sales
- Seniority: Executive
- Function: Revenue
- Reports to: CRO or CEO
## KPIs
- New ARR, win rate, pipeline coverage, rep ramp time
## Pains
- Pipeline gaps, slow ramp, low rep activity, forecasting drift
## Motivations
- Hit the number, build a repeatable motion, get visibility
## Day-to-day
Forecast calls, deal reviews, pipeline reviews, 1:1s with frontline managers.
## Preferred channels
- medium/linkedin-outbound
- medium/exec-warm-intro
## Common objections
- objection/we-already-have-an-ai-sdr
## How we land
Lead with pipeline-coverage math, not features.
EOF
)" \
--commit-message "Add VP of Sales mid-market persona"
```
### Edit an existing file
`edit` replaces a single exact substring. `--old-string` must occur **exactly once** in the file; pass an empty `--new-string` to delete the match.
`edit` does not validate frontmatter — an edit that strips or empties `title`/`description` still applies, so keep the block intact to keep the node discoverable. `edit` can fail for other reasons, though: `stringNotFound` / `stringNotUnique` (the `--old-string` match), `fileNotFound`, `noOp` (new string equals old), `syncConflict` / `syncFailed`, `failedToEdit`, or `deniedPath`.
```bash
# Replace one specific sentence
cargo-ai context runtime edit \
--path global/positioning.md \
--old-string "We help RevOps automate workflows." \
--new-string "We help RevOps run AI-native GTM motions." \
--commit-message "Refresh positioning one-liner"
# Delete a line (pass empty --new-string)
cargo-ai context runtime edit \
--path persona/vp-sales-mid-market.md \
--old-string "\n- Outdated stat: 4.2x pipeline\n" \
--new-string ""
```
For larger restructures, prefer `write` (full-file overwrite) over many sequential `edit` calls.
### Execute a command in the sandbox
`execute` runs a shell command in the sandbox. Useful for inspecting structure or running checks; **changes are not pushed**.
```bash
# Find every file that cross-references a specific slug
cargo-ai context runtime execute \
--command grep \
--args '["-r","-l","persona/vp-sales-mid-market","."]'
# Count entries per domain
cargo-ai context runtime execute --command ls --args '["-1","persona"]'
# Run a one-shot script (no quotes/escaping needed inside --command beyond JSON for args)
cargo-ai context runtime execute --command pwd
```
`--args` is a JSON array of string arguments. Omit it for a no-arg command.
## Context repository structure and conventions
The Cargo context repo is a typed knowledge base. The canonical example — and the source of the conventions below — is [`getcargohq/cargo-workspaces`](https://github.com/getcargohq/cargo-workspaces); read its `README.md` and `_template.md` files in each domain before writing new entries. For the full domain reference, see `references/conventions.md`.
### Domains
| Domain | Purpose |
|---|---|
| `global/` | Company-level context: mission, voice, positioning, narrative, pricing |
| `icp/` | Ideal Customer Profile segments |
| `persona/` | Buyer personas (roles inside an ICP) |
| `jtbd/` | Jobs-to-be-done framings |
| `alternative/` | Competitors, substitutes, status quo |
| `client/` | Customer profiles, case studies, reference accounts |
| `insight/` | Market insights and observations |
| `medium/` | Channel playbooks (email, LinkedIn, cold call, etc.) |
| `objection/` | Objections + responses + proof |
| `play/` | GTM plays (signal → audience → channel → sequence → outcome) |
| `proof/` | Atomic proof points (metrics, quotes, case data) |
| `signal/` | Buying signals and intent triggers |
### File conventions
- **Filename:** `kebab-case.md` (e.g. `vp-sales-mid-market.md`).
- **Frontmatter:** start every `.md`/`.mdx` file with YAML frontmatter setting `title` and `description`. This is a **strong convention, not enforced** — a write with missing, empty, or malformed frontmatter is still created and committed; it just indexes poorly. The graph reads `title` (fallback: filename) and `summary` (fallback: the file's first paragraph); it does **not** read `description`, so add a `summary:` if you want to control the node summary. See [Source references and graph edges](#source-references-and-graph-edges).
- **Cross-references:** use the `domain/slug` form, **no `.md` extension** (e.g. `persona/vp-sales-mid-market`). To register as a graph **edge** a reference must use one of the three link forms below — a bare `domain/slug` (or file path) in plain prose creates no edge.
- **Templates:** each domain ships an `_template.md`. Read it (`cargo-ai context runtime read --path persona/_template.md`) before authoring a new entry. `_template.*` files are excluded from the graph — never reference them.
### Source references and graph edges
The knowledge graph is built from every `.md`, `.mdx`, `.yaml`, and `.yml` file in the repo (any folder; only `.git/` is excluded). Each file is a node, but **edges are created only from three forms** — anything else is invisible to the graph:
1. **Frontmatter `references:` list** (preferred for source citations — keeps prose clean):
```yaml
---
title: AgoraPulse expansion thesis
description: Why AgoraPulse is ready for a multi-thread expansion play.
references:
- outputs/sales-notes/2026-06-05-agorapulse-build-session-1-outcomes.md
---
```
2. **A Markdown link** in the body — standard `[label]` followed immediately by `(path)` syntax, where the target is the file path, e.g. an anchor linking to `outputs/sales-notes/2026-06-05-agorapulse-build-session-1-outcomes.md`.
3. **Wikilinks** in the body (extension optional): `[[outputs/sales-notes/2026-06-05-agorapulse-build-session-1-outcomes]]`.
Key constraints:
- **Never cite a source as a bare path in prose** (e.g. a `Source:` line that just mentions `outputs/sales-notes/foo.md` as text) — it is not parsed and creates **no** edge.
- **Prefer root-relative paths** (resolved from the repo root first, then relative to the citing file) so links work regardless of where the document lives.
- **Extensions are optional** — the resolver auto-tries `.md`, `.mdx`, `.yaml`, `.yml` in that order. Including the extension is fine.
- **The target must exist** or the edge is **broken** (a dead link in the graph UI). Verify with `runtime browse` before citing.
- For docs with a **Source**/**Evidence** section, cite the files in frontmatter `references:`; use inline markdown links when the citation needs surrounding prose. Full rules: `references/conventions.md`.
### Workflow: add a new entry
1. Confirm the target domain and copy its template:
```bash
cargo-ai context runtime read --path persona/_template.md
```
2. `write` a new file at `<domain>/<slug>.md` with `title` + `description` and the body sections filled in.
3. Add cross-refs (`domain/slug`) where useful — keep them bidirectional when it makes sense.
4. Rebuild the knowledge graph to verify the new entry and its links:
```bash
cargo-ai context graph get
```
For full per-domain templates and worked examples, see `references/conventions.md` and `references/examples/authoring.md`.
### Workflow: bootstrap and refresh
To stand up a new workspace's context repo from scratch, or to refresh an existing one on a cadence, follow the two-phase lifecycle in `references/examples/lifecycle.md`:
1. **Bootstrap (one-time):** seed `global/`, `persona/`, `client/`, `proof/`, `objection/`, `signal/` from public sources, then open a fresh agent session against the seeded repo. For the prescriptive, automatable version (domain in → files out, idempotent, with credit budget), use `references/examples/bootstrap-from-domain.md`.
2. **Refresh (every 2–4 weeks):** pull the last ~3 months of sales-call transcripts → analyze one at a time, human-in-the-loop → apply a repetition threshold before promoting any claim to context → validate by generating sequence permutations → diff the graph before/after and retire stale entries.
The repetition threshold (how many calls a claim must appear in before it lands in context) is documented in `references/conventions.md`.
## Knowledge graph
`context graph get` builds (or loads from cache) the knowledge graph over every markdown/MDX file in the context repo. Use it to:
- Audit cross-references between domains (e.g. find personas that link to plays with no proof attached).
- Discover what already exists before writing a new entry (avoid duplicates).
- Power downstream agents that need the typed structure of the workspace's context.
```bash
cargo-ai context graph get
```
The response includes the parsed frontmatter and outbound `domain/slug` references for each node — pipe it through `jq` to slice it. See `references/examples/graph-queries.md` for ready-to-run queries.
## Help
Every command supports `--help`:
```bash
cargo-ai context --help
cargo-ai context runtime browse --help
cargo-ai context runtime read --help
cargo-ai context runtime write --help
cargo-ai context runtime edit --help
cargo-ai context runtime execute --help
cargo-ai context graph get --help
```
Referenced files: 8
cargo-diagnostics7.7 KB
---
name: cargo-diagnostics
description: "Explain what a Cargo run or batch actually did, after the fact — trace one run node by node, draw the graph it executed with the failing step marked, sweep a batch or play for errors grouped by root cause, and attribute credit spend down to the node and the provider. Triggers: \"why did this fail\", \"it succeeded but the output is wrong\", \"half my rows are empty\", \"why is this column blank\", \"what broke in this batch\", \"why did that cost so much\", \"which node is burning credits\", \"it worked yesterday\", \"these results look wrong\", \"it went down the wrong path\", \"this step never ran\", \"show me what the run did\". Skip when: setting up an alert for next time — use cargo-observability; just downloading the data — use cargo-analytics."
version: "1.3.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
---
# Cargo CLI — Diagnostics
Forensic runbooks for workflow behavior: trace one run, sweep a batch for errors, profile a play's credit spend. This skill is the **interpretation layer** — the raw surfaces (`run get`, orchestration SQL, billing metrics) are documented in `cargo-orchestration` and `cargo-billing`; each runbook here tells you which of them to pull, in what order, and what each output shape means.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`. Credit attribution steps (`billing usage get-metrics`, `billing subscription get`) need a token with **admin access**; everything else works with a standard token. When the full skill bundle is installed, [`../cargo/references/prerequisites.md`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Which runbook?
```
What are you diagnosing?
│
├── One run / one record ("why did this record fail?",
│ "run succeeded but the output is wrong/empty")
│ └── references/run-trace.md
│
├── Many runs ("the batch has errors", "error rate spiked",
│ "which node keeps failing?")
│ └── references/batch-error-sweep.md
│
└── Cost ("this play is expensive", "where do the credits go?",
"make this cheaper")
└── references/play-optimize-credits.md
```
Rule of thumb: start with the **sweep** when you don't yet know which run to look at — it ends by handing you exemplar run UUIDs to feed into the **trace**.
**No run UUID at all** ("look at the last run", "the run for acme.com", "what did my play do in the editor")? That's [`references/run-trace.md`](references/run-trace.md) § 0, which resolves a symptom to a UUID. Note that `orchestration run list` **requires** `--workflow-uuid` and cannot answer it — orchestration SQL over `runs` takes no filter and can. Never conclude that run inputs and outputs are inaccessible because `run list` refused.
**Boundary with `cargo-analytics`:** analytics *measures and exports* ("what's the error rate?", "download the batch results", "export this segment"); this skill *explains* ("why is the error rate up?", "why is this record's output empty?"). A diagnosis often starts from an analytics signal (error count spiked, batch reports `failedRunsCount > 0`) and ends back in analytics — once the cause is fixed and runs re-executed, bulk retrieval goes through `run download-outputs` / `batch download` / `segment download`, all documented in `../cargo-analytics/SKILL.md`. This skill's evidence surfaces (`run get`, orchestration SQL, billing metrics) are for diagnosis, not bulk export.
## References
| Doc | What it covers |
| --- | --- |
| [`references/run-trace.md`](references/run-trace.md) | Find a run from a symptom when you have no UUID (§ 0), then walk it end-to-end: per-node executions, `runContext` outputs, branch routing, per-node credits and timing. |
| [`references/batch-error-sweep.md`](references/batch-error-sweep.md) | Find errored runs across a batch/play/workspace, group failures by root cause, pick exemplars, decide fix vs report. |
| [`references/play-optimize-credits.md`](references/play-optimize-credits.md) | Attribute credit spend to workflows and nodes, then apply the cost levers in priority order. |
## The surfaces every runbook draws on
| Surface | Command | Gives you |
| --- | --- | --- |
| Run detail | `cargo-ai orchestration run get <run-uuid>` | `run.executions[]` (node-by-node trace), `runContext` (per-node output keyed by `nodeSlug`), `runComputedConfigs` (what each node was actually called with) |
| Orchestration SQL | `cargo-ai orchestration query execute "<sql>"` | Aggregates over `runs`, `batches`, `spans`, `records` (ClickHouse; no schema prefix; workspace-scoped) |
| Billing metrics | `cargo-ai billing usage get-metrics --from <date> --to <date>` | Credit totals, filterable and groupable by `workflow_uuid`, `connector_uuid`, `agent_uuid`, `integration_slug`, `model_uuid` |
| Graph picture | `cargo-ai orchestration node diagram --run-uuid <uuid> --highlight <slug> --format ascii --raw` | The graph the run executed, with the failing node marked. Free, runs nothing |
**Draw the graph before explaining a routing bug.** For "it took the wrong branch"
or "this step never ran", the picture is the evidence, and it shows one thing
`run get` does not make obvious: the `on failure` edges. A step that looks skipped
is often one the run *reached* via a `fallbackChildUuid` edge, which means the
provider errored rather than returning nothing — a different diagnosis with a
different fix. Flags and the ASCII legend: [`../cargo-orchestration/references/node-diagram.md`](../cargo-orchestration/references/node-diagram.md).
Full query syntax, table columns, and caps: [`../cargo-orchestration/references/examples/queries.md`](../cargo-orchestration/references/examples/queries.md). Debugging field semantics: [`../cargo-orchestration/references/troubleshooting.md`](../cargo-orchestration/references/troubleshooting.md).
## Presenting findings
Follow [`../cargo/references/interaction.md`](../cargo/references/interaction.md): lead with the conclusion ("18 of 20 failures are one cause: the connector's token expired"), summarize evidence in a short table, never dump raw `run get` JSON or full query results into the conversation. Any fix that re-runs paid nodes goes through the pilot gate: re-run **10–20 records** first, report the observed cost and hit-rate, then ask the user to approve the rest quoting the **record count** and **credit estimate** — a diagnosis is not approval to re-bill the batch that produced it. Full spend rules in [`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md).
## When diagnosis dead-ends
If the evidence contradicts documented behavior (a field missing from `run get`, a query cap that doesn't match the docs, an error that makes no sense), file a report — that's the official channel and the team reads every one:
```bash
cargo-ai workspaceManagement report create \
--title "<one-line summary>" \
--description "<commands run, errorMessage verbatim, expected vs actual, UUIDs>"
```
Referenced files: 4
cargo-gtm33.4 KB
---
name: cargo-gtm
description: "Business-to-business go-to-market work on Cargo — research accounts and buying committees, enrich and verify B2B contact records from licensed data providers, score and qualify leads, draft outreach for the user's own sequencer, sync to CRM, and monitor buying signals. Runs on audiences with a documented lawful basis, screens every contact step against a workspace-wide suppression list, and requires per-recipient relevance; the skill sends no messages itself. Triggers: \"build me a list of\", \"find 50 <title> at <segment>\", \"who works at\", \"find work emails for these accounts\", \"enrich this CSV\", \"verify these emails\", \"build a TAM\", \"who fits our ICP\", \"score these leads\", \"write a first-touch email\", \"push these to my CRM\", \"who changed jobs\", \"who just raised funding\", \"companies using <tech>\", \"who is hiring <role>\", \"find the buying committee\", \"upload this audience to Google/LinkedIn ads\". Licensed B2B data providers only. Skip when: a run already happened and misbehaved — use cargo-diagnostics."
version: "1.17.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
---
# Cargo GTM — Meta Skill
Use this skill for prospecting, account research, contact enrichment, verification, lead scoring, personalization, signal monitoring, and campaign activation.
## Acceptable use — MANDATORY, before anything that touches a person
Full spec: [`references/acceptable-use.md`](references/acceptable-use.md). The short version, binding on every recipe here:
- **B2B professional identities only**, from the licensed providers in [`provider-playbooks/`](provider-playbooks/) — never consumer targeting, purchased lists, or data taken from a platform in breach of its terms.
- **Three checks before any outreach step** — *basis* (customers, opted-in contacts, event attendees, or a documented legitimate-interest case), *suppression* (filter on unsubscribe / DNC / hard-bounce **before** enriching or sending), *relevance* (name, per recipient, why this message is for them). Any check that fails is a stop-and-ask, not a warning.
- **Refuse and say why**: undifferentiated fan-out ("email everyone in `<industry>`"), contacting a suppressed record, filter evasion or disguised sender identity, auto-dialing and SMS blasts, batch-blasting LinkedIn engagement actions. Offer the compliant version once — state it, don't lecture.
- **This skill never sends.** Outreach recipes stop at send-ready variables and hand off to the user's own sequencer, under that sequencer's limits, domains, and identities. Copy it drafts must carry an honest sender and subject, a working opt-out, and a postal address where the jurisdiction requires one.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## 1) What this skill governs
- Route GTM decisions, safety gates, and provider/quality defaults **before** execution.
- Keep long command chains and tooling nuance in sub-docs; provider-specific implementation detail in `provider-playbooks/*.md`.
- Anchor recipes in **credits-based actions** (the high-value action calls). Free CRUD (createLead, getLead, deleteRecords) doesn't need this skill — agents can compose those ad hoc.
### Process / goal
The user is generally trying to go from "I have an ICP" to "Here's a list of prospects with verified emails and personalized signals." They may be anywhere in this process — guide them along.
**Discovery order: companies first, then people.** When the task requires finding contacts at companies matching criteria (portfolio, ICP, hiring signal), discover the company set first, then find people at each company. Don't start with broad people-search queries.
### Documentation hierarchy
- **Level 1** — `SKILL.md` (this file): decision model, guardrails, routing table, links to sub-docs.
- **Level 2** — Phase docs: [`guides/finding-companies-and-contacts.md`](guides/finding-companies-and-contacts.md), [`guides/enriching-and-researching.md`](guides/enriching-and-researching.md), [`guides/writing-outreach.md`](guides/writing-outreach.md).
- **Level 2.5** — Recipes: [`recipes/*.md`](recipes/) — step-by-step playbooks for specific scenarios.
- **Level 3** — Provider playbooks: [`provider-playbooks/<slug>.md`](provider-playbooks/) — provider-specific quirks, costs, and fallback behavior.
## 2) Read behavior — MANDATORY before any execution
**STOP. Do not call any provider, run any `cargo-ai orchestration action execute` command, or write any search query until you have opened the correct sub-doc for your task.**
These docs encode what works, what fails, and why. They contain validated parameter schemas, cheapest-provider mappings, parallel execution patterns, sample payloads, and known pitfalls. Reading the right doc for 10 seconds saves 10 failed action calls, wasted credits, and garbage output.
### Routing rules — match your task to a doc and READ IT
| When the task involves… | You MUST read this doc first | What it gives you |
|---|---|---|
| **Finding companies, finding people, building lead lists, prospecting, portfolio/VC sourcing, contact finding at known companies** | [`guides/finding-companies-and-contacts.md`](guides/finding-companies-and-contacts.md) | Provider filter schemas, cheapest-source decision tree, parallel patterns, role-based search rules, portfolio/VC shortcuts, contact-finding patterns. |
| **Enriching companies or contacts, finding emails/phones/LinkedIn, waterfall enrichment, signal lookup (job change, funding, tech stack), coalescing data** | [`guides/enriching-and-researching.md`](guides/enriching-and-researching.md) | Waterfall patterns with fallback chains, when to use cargo-native vs waterfall vs FullEnrich vs peopleDataLabs, email/phone/LinkedIn fallback orders, signal segments, output retrieval via `run download-outputs`. |
| **Writing first-touch outreach, personalizing messages, lead scoring, qualification, sequence design, campaign copy** | [`guides/writing-outreach.md`](guides/writing-outreach.md) + [`references/acceptable-use.md`](references/acceptable-use.md) (§3 checks, blocking) | LLM provider routing (openAi/anthropic/perplexity/gemini), prompt templates, scoring rubrics, email length/tone rules, personalization patterns — gated on basis, suppression, and per-recipient relevance. |
| **Building or modifying a recurring workflow** (cron / webhook / scheduled tool / play), designing step sequences, triggers, deploy/verify cycles | [`../cargo-orchestration/SKILL.md`](../cargo-orchestration/SKILL.md) (capability) + apply-patterns from this skill's recipes + the [provider playbook](provider-playbooks/) of **every paid node** (§11, esp. its **Recurring use** section) | Schema for tool/play workflows, node graph syntax, polling strategies, output retrieval; per-provider cadence defaults and re-billing gates. |
### Recipes: step-by-step playbooks (check before executing)
Scan this list and read the recipe matching your task. **When a recipe matches: follow it step-by-step as your execution plan.**
| Recipe | Use when… |
|---|---|
| [`recipes/source-planning.md`](recipes/source-planning.md) | **Read first when the source isn't obvious.** Turn the question into a field, probe 2–3 candidate sources on 5–10 rows, present cost-per-*hit* — before any fan-out |
| [`recipes/prospecting.md`](recipes/prospecting.md) | End-to-end find → enrich → verify → sync (P1/P2/P3 variants) |
| [`recipes/build-tam.md`](recipes/build-tam.md) | Building a Total Addressable Market list at scale (100–10,000 companies) |
| [`recipes/linkedin-url-lookup.md`](recipes/linkedin-url-lookup.md) | Resolving a person's LinkedIn profile URL from name + company with strict identity validation |
| [`recipes/portfolio-prospecting.md`](recipes/portfolio-prospecting.md) | Investor / accelerator → portfolio companies → contacts |
| [`recipes/job-change-monitoring.md`](recipes/job-change-monitoring.md) | `waterfall.detectJobChange` (cargo-unique) on a contact segment |
| [`recipes/funding-watch.md`](recipes/funding-watch.md) | Tracking companies that recently raised funding |
| [`recipes/tech-intent.md`](recipes/tech-intent.md) | Finding companies by tech-stack or hiring-intent signals |
| [`recipes/icp-discovery.md`](recipes/icp-discovery.md) | Diffing Closed-Won vs Closed-Lost segments to surface ICP signals |
| [`recipes/custom-datapoints.md`](recipes/custom-datapoints.md) | Designing *which* custom attributes and live signals to collect for a seller's ICP — feasibility-gated against the catalog, then wired into columns, scoring, segments, and a refresh cadence |
| [`recipes/outreach-activation.md`](recipes/outreach-activation.md) | Turning a signal segment into send-ready outreach (enrich → verify → personalize → sequencer handoff) |
| [`recipes/ads-audience-activation.md`](recipes/ads-audience-activation.md) | Pushing a segment to paid media — Google Ads Customer Match or LinkedIn Matched Audiences — and reading the match rate |
| [`recipes/review-and-iterate.md`](recipes/review-and-iterate.md) | Judgment output a human must review — sheet handoff, grouped corrections, permanent fixes, kept as an eval set |
| [`recipes/re-engagement.md`](recipes/re-engagement.md) | Waking up stale contacts only when a fresh signal fires (job change, funding, tech intent) |
| [`recipes/lost-deal-revival.md`](recipes/lost-deal-revival.md) | Reviving Closed-Lost CRM deals by branching on `lost_reason` (champion left, budget, timing) |
| [`recipes/account-expansion.md`](recipes/account-expansion.md) | Multi-threading existing customer accounts — net-new buyers, deduped against the workspace's Contacts model |
| [`recipes/save-as-play.md`](recipes/save-as-play.md) | Converting a successful ad-hoc run into a durable scheduled play or cron tool — offer after any repeatable pull |
| [`recipes/import-gtm-data.md`](recipes/import-gtm-data.md) | Importing existing GTM data (CSV/CRM exports from any tool) into models, QA-auditing it, and selectively rebuilding recurring logic as plays with a parity check |
| [`recipes/clay-to-cargo.md`](recipes/clay-to-cargo.md) | **Clay specifically**: getting the column *configuration* out (not the CSV), the column-family → action map, the four Clay concepts that do not map one to one (waterfalls, run conditions, auto-update, partial runs), and the parity check against Clay's own output |
If none match, scan the phase docs above for the closest pattern and adapt — or invoke [`agents/execution-plan-creator.md`](agents/execution-plan-creator.md) to compose a custom chain with provider/action slugs and cost estimates. For wide sourcing sweeps that fan out (per-industry, per-geo), delegate approved slices to [`agents/list-builder.md`](agents/list-builder.md) — it executes exactly one pre-approved action per slice and returns rows to a file, keeping row data out of the main context. (On Claude Code with the plugin, both are installed as native subagents: `cargo-execution-planner` and `cargo-list-builder`.)
## 3) Cost discipline — MANDATORY gates
Full spec: [`references/cost-discipline.md`](references/cost-discipline.md). The short version every task must honor:
1. **Sample → approval → full run, in that order.** Run a slice of the exact input first — 1–3 rows to prove one action's config, **10–20 records before any batch** (one row can't show a hit-rate). Then present the 4-section approval message (Assumptions · Sample result verbatim · Credits/Scope/Cap — always stating **how many records** the full run enrolls and **what they cost**, reconciled against the actual balance · 3 shaped choices); stay in AWAIT_APPROVAL until the user picks. Never fan out on an unapproved or cost-unknown action, and never read approval of the sample as approval of the full enrollment.
2. **Receipt after every paid action**: credits spent + balance remaining + hit-rate ("found 34 emails of 40") + estimate-vs-actual with the why when they diverge. Prefer `billing usage get-metrics` over your own arithmetic.
3. **Over-provision 1.4×N, then filter** — coverage is a property of the company; drop incomplete rows instead of chasing them with more providers.
4. **Count first, pay second** — search is billed on returned rows; keep `limit` strict and size the pool with a 1-row probe before any full pull.
5. **Phone is the guarded lever** — explicit user request only, qualified leads only. Still true at the cheap end: `aiArk.findMobilePhone` (0.5, mobile-only) is the first rung and bills 0 on a miss, but the escalation behind it is 3–7 credits (~10× email), so a full-list phone sweep needs the same approval as any other paid fan-out.
## 4) After every run — receipt, then grounded next steps
End every completed run with the receipt (above), then propose **2–3 next steps maximum, computed from the data just produced — never a generic menu**. Required shape:
1. **Continuity** — builds on this session's artifacts ("67 of these 70 companies have RevOps teams — find the leads?"), not a fresh generic idea.
2. **Budget-aware** — framed against the remaining balance ("with your ~9 credits left, ~5 verified emails fits").
3. **Cost-per-unit stated** — "email waterfalls run ~1.4 credits each."
4. **A default picking heuristic** so answering takes one word ("I'd default to: has funding data + RevOps ≥ 2 + posting is recent").
5. **An escape hatch** — always end with "or something else entirely."
When a run produced a durable, repeatable result, one of the suggestions should be **making it systematic** — see [`recipes/save-as-play.md`](recipes/save-as-play.md).
When a run or batch **misbehaved** — errors, missing downstream values, cost surprises — hand off to the `cargo-diagnostics` skill (`../cargo-diagnostics/SKILL.md`): sweep the batch for root causes before re-running anything paid. Interaction defaults for plan gates, shaped choices, and presenting results live in `../cargo/references/interaction.md`.
## 5) Priority provider stack (recipes lead with these 8)
These eight credits-based providers cover the full prospecting → enrichment → verification → signal pipeline at the lowest credit cost in the catalog. Every recipe in this skill's `recipes/` leads with this stack:
| Provider | Role | Key actions (cost in credits) |
|---|---|---|
| **salesNavigator** | Sourcing | `searchLeads` (0.02), `searchAccounts` (0.05), `findCompanyInsights/Metrics/EmployeesCount/Distribution` (0.25 each) |
| **cargo** (native) | Firmographic + signal intelligence | `enrichBusinessFirmographics` (0.5), `…Technographics` (1), `…FundingAndAcquisitions` (0.5), `enrichProspectDetails/LinkedinProfile/LinkedinPosts` (2), `matchBusiness/matchProspect` (0.5), 13 more |
| **aiArk** | LinkedIn-anchored enrichment + cheapest search | `searchCompanies` (0.01/record, lookalike seeds), `searchPeople` / `reverseLookup` (0.05), `enrichPerson` (0.1 — profile **+ verified email**), `findMobilePhone` (0.5) |
| **waterfall** | Multi-source enrichment + signal | `enrichContact` (2), `enrichCompany` (1), `verifyEmail` (0.1), `detectJobChange` (3), `searchProspects` (3), `findPhone` (7) |
| **FullEnrich** | Premium contact lookup | `findEmail` (1), `findPhone` (6), `findPhoneAndEmail` (7), `reverseEmailLookup` (2) |
| **apolloio** | Niche-coverage enrichment | `enrichPerson` (1, **3** with `revealPhoneNumber`), `enrichOrganization` (1) — the **only two** credits-based actions; its other nine need your own Apollo API key |
| **theirStack** | Tech-stack + hiring intent | `searchTechnologies` (0.5), `searchJobs` (0.5), `searchCompanies` (0.5) |
| **peopleDataLabs** | Heavyweight backfill | `enrichPerson` (3), `enrichCompany` (3), `searchPeople` (3), `searchCompanies` (3), `queryPeople/Companies` (3) |
`aiArk` and `apolloio` sit at opposite ends of the enrich tier and are picked by **what you hold**, not by preference: `aiArk` wins whenever a **LinkedIn URL** is in hand (profile + verified email at 0.1, mobile at 0.5, both billing 0 on a miss), `apolloio` is the **1-credit niche-coverage rung** you promote per-batch when a pilot shows Apollo hits where `cargo` (2) and `waterfall` (2) miss — investor-backed and portfolio niches especially. Neither displaces `salesNavigator` for plain at-scale sourcing (0.02/lead) or `cargo` native for match-verified firmographics.
See [`provider-playbooks/`](provider-playbooks/) for per-provider deep dives — including each provider's **Recurring use** section for when the task is a monitor, play, or scheduled pull rather than a one-off. See [`references/stage-action-map.md`](references/stage-action-map.md) for the complete cheapest-action-per-stage table across the full 120-integration catalog.
> **Already holding identifiers (not sourcing)?** The stack above leads the *sourcing-first* spine. When you already have **LinkedIn URLs**, the cheapest enrich is [`aiArk.enrichPerson`](provider-playbooks/aiArk.md) (0.1 — full profile **plus** a verified email, bills 0 when no email is found); drop to [`linkedin.enrichProfile` / `enrichCompany`](provider-playbooks/linkedin.md) (0.25) when you don't need the email, and skip `waterfall.enrichContact` entirely (it keys on email or name+company, not a URL). Need a **phone**? `aiArk.findMobilePhone` (0.5) is the first rung, not the 3–7 tier. Have **emails**? `aiArk.reverseLookup` (0.05), then `leadMagic` / `contactOut`. See `references/stage-action-map.md` for the full input-type → cheapest-action map.
## 6) Recipe spine (default chain)
```
1. SOURCE → salesNavigator.searchLeads / searchAccounts (0.02–0.05/record)
lookalike seeds, or filters SN can't express (skills,
education, tenure)? aiArk.searchCompanies / searchPeople (0.01–0.05/record)
2. DEDUPE → cargo.matchProspect / cargo.matchBusiness (0.5/record)
3. ENRICH → LinkedIn URL in hand? aiArk.enrichPerson (0.1) FIRST — profile + verified
email in one call; linkedin.enrichProfile/enrichCompany (0.25) if no email needed
cargo.enrichBusinessFirmographics / Technographics
+ waterfall.enrichContact / enrichCompany (0.5–2/record)
+ apolloio.enrichPerson / enrichOrganization on the niche residue (1/record)
4. SIGNAL → cargo.enrichBusinessFundingAndAcquisitions
+ theirStack.searchJobs
+ waterfall.detectJobChange (0.5–3/record)
5. CONTACT → FullEnrich.findEmail — only on rows step 3 left without
an email (fallback peopleDataLabs) (1–3/record)
6. VERIFY → waterfall.verifyEmail (0.1/record)
7. BACKFILL → peopleDataLabs.enrichPerson (only if step 5 missed) (3/record)
8. QA → scripts/contact-accuracy-audit.ts (free, local)
```
Two spine notes from the 8-provider stack: step 3's `aiArk.enrichPerson` **already returns a verified email**, so step 5 runs on the residue only — don't pay `FullEnrich.findEmail` (1) behind a row that already has one. And when the goal reaches a **phone**, `aiArk.findMobilePhone` (0.5, mobile-only, bills 0 on a miss) is the first rung before `prospeo` (3) / `FullEnrich` (6) / `waterfall` (7) — the guarded-lever rule in §3 still applies to all four.
Adapt by phase: drop steps that aren't relevant to the user's goal. For pure sourcing, run step 1 only. For "enrich a list I already have," run steps 2–7.
## 7) Output retrieval — use `run download-outputs`, not `run download`
When the agent needs the actual data produced by an action (enriched fields, found emails, search results), use:
```bash
cargo-ai orchestration run download-outputs \
--workflow-uuid <uuid> \
--output-node-slug <slug> \
--format json
```
(Don't pass `--is-finished` — the CLI help still lists it but the API currently rejects it with `unrecognized_keys`; reported.)
Returns `{"url": "..."}` — a signed URL to a CSV/JSON containing only the output node's data. Faster and cheaper than `run download` (which pulls full run records). See [`references/output-retrieval.md`](references/output-retrieval.md) and [`../cargo-analytics/SKILL.md`](../cargo-analytics/SKILL.md).
## 8) Contact accuracy — run the QA scripts, don't eyeball
Four deterministic TypeScript scripts in [`scripts/`](scripts/) (Node ≥ 22.18, zero deps, fixture-tested in CI) replace in-context row checking. **Run the script — never re-derive its logic by reasoning over rows.** Full doctrine, pipeline order, and the SEND/VERIFY/REVIEW/REMOVE verdict semantics: [`references/contact-accuracy.md`](references/contact-accuracy.md).
- `scripts/validate-emails.ts` — free syntax/risk/duplicate cull **before** paid `verifyEmail`.
- `scripts/select-current-role.ts` — pick the real current role from an experiences array (catches job changers).
- `scripts/validate-linkedin-names.ts` — name↔profile match (catches same-name decoys); pairs with [`recipes/linkedin-url-lookup.md`](recipes/linkedin-url-lookup.md).
- `scripts/contact-accuracy-audit.ts` — final per-row `audit_action` stamp on the merged output; cite its summary counts in the receipt. Reads files or a finished run directly (`--workflow-uuid`, via `@cargo-ai/api`).
## 9) Action shape rules (every recipe)
Every action JSON in this skill follows the rules in [`../cargo-orchestration/references/examples/actions.md`](../cargo-orchestration/references/examples/actions.md):
- `kind: "connector"` action shape: `{"kind":"connector","integrationSlug":"<slug>","actionSlug":"<slug>"}`. **`connectorUuid` is NOT in `config`** — the platform resolves the workspace's authenticated connector from `integrationSlug` automatically.
- **A top-level action has no `config` — omit it.** Inputs go in `--data` / `--records`, and every recipe here now writes the action without the key. The one command that still demands it is `action get-output-schema` (`400` at `action.config` without `"config": {}`). And inputs misplaced in `config` are no longer rejected — they are dropped and the action runs with **no input**, so check this first when a call returns empty for no visible reason.
- **Don't hand-write a slug you're unsure of, and don't page the catalog looking for one.** `cargo-ai orchestration action list <keywords> [--integration-slug <slug>]` is free, searches every integration plus native actions, tools, and agents, and returns the action object ready to paste **with the action's credit costs** — a cheap sanity check on both the slug and the price before a paid call. When the question is *which paid actions exist for this?*, `cargo-ai connection action search <keywords> --credits-only` is the one that filters on it. Neither replaces the provider playbook below: the playbook is where the input quirks, hit-rates, and recurring-use traps live.
- For multi-step node graphs: `connectorUuid` lives at the top level of the node, not in `config`. Cross-node interpolation uses `{{nodes.<slug>.<field>}}`. Agent node outputs wrap under `.answer` (read as `{{nodes.<slug>.answer.<field>}}`).
## 10) When stuck — file a workspace report
If a recipe fails repeatedly and the cause isn't obvious, escalate via `cargo-ai workspaceManagement report create`. See [`../cargo-workspace-management/SKILL.md`](../cargo-workspace-management/SKILL.md) (Reports section).
## 11) Provider playbooks — read before you call (one-off or recurring)
**STOP — do not execute any paid action against a provider below, and do not wire a provider into a recurring play/tool node graph, until you have opened its playbook.** Each playbook carries the exact action slugs, config shapes, input quirks, and cost traps; reading it for five seconds is cheaper than one failed paid call, and a failed batch is 100 failed paid calls. The stakes are higher, not lower, when the provider goes into a **recurring** workflow: a bad config repeats on every scheduled run, and a wrong cadence re-bills the same rows forever — each playbook ends with a **Recurring use** section (schedule fit, cadence default, re-billing gates, extractors) for exactly this. **Every credits-based provider with callable actions has a playbook, with three stated exceptions**: `brightData` (consumer social-platform scraping, outside this skill's acceptable use for person targeting), `proxycurl`, and `openRouter` (which exposes a model lister rather than credits-based actions, so there is nothing to document). Own-key integrations fall back to [`references/alternatives.md`](references/alternatives.md) and [`references/stage-action-map.md`](references/stage-action-map.md).
**Priority stack (recipes lead with these):**
- [`provider-playbooks/salesNavigator.md`](provider-playbooks/salesNavigator.md) — cheapest sourcing in the catalog (0.02–0.05/record).
- [`provider-playbooks/cargo.md`](provider-playbooks/cargo.md) — 22 native enrichment + signal actions; the `match*` actions are key for dedup.
- [`provider-playbooks/aiArk.md`](provider-playbooks/aiArk.md) — LinkedIn-anchored people/company data: `enrichPerson` returns profile **+ verified email** at 0.1, `findMobilePhone` (0.5) is the cheapest phone rung, `searchCompanies` (0.01/record) does lookalikes. All actions run on the managed connection.
- [`provider-playbooks/waterfall.md`](provider-playbooks/waterfall.md) — swiss-army-knife: enrichment, verification, and the cargo-unique `detectJobChange` signal.
- [`provider-playbooks/FullEnrich.md`](provider-playbooks/FullEnrich.md) — premium contact lookup; `reverseEmailLookup` is unique.
- [`provider-playbooks/apolloio.md`](provider-playbooks/apolloio.md) — the 1-credit niche-coverage enrich rung (person + organization); **read it before assuming Apollo is available** — only two of its eleven actions are credits-based, the rest need your own Apollo API key.
- [`provider-playbooks/theirStack.md`](provider-playbooks/theirStack.md) — tech-stack + hiring-intent signals.
- [`provider-playbooks/peopleDataLabs.md`](provider-playbooks/peopleDataLabs.md) — heavyweight backfill at flat 3-credit tier.
**Sourcing & company-data specialists:**
- [`provider-playbooks/linkedin.md`](provider-playbooks/linkedin.md) — the native LinkedIn integration's action set (profiles, companies, posts, jobs).
- [`provider-playbooks/oceanio.md`](provider-playbooks/oceanio.md) — lookalike-company discovery from seed domains, with technographic / web-traffic filters `aiArk.searchCompanies` (0.01) can't express.
- [`provider-playbooks/datagma.md`](provider-playbooks/datagma.md) — lightweight person/company enrichment alternative.
- [`provider-playbooks/companyEnrich.md`](provider-playbooks/companyEnrich.md) — cheapest company-by-domain (0.25) + per-item-billed lookalikes.
- [`provider-playbooks/enrichCrm.md`](provider-playbooks/enrichCrm.md) — CRM-record enrichment; `getFunding` is the funding-signal fallback.
- [`provider-playbooks/societeInfo.md`](provider-playbooks/societeInfo.md) — French-registry company/contact data (SIREN/SIRET).
- [`provider-playbooks/piloterr.md`](provider-playbooks/piloterr.md) — ultra-cheap bulk company extractor + G2 product info.
- [`provider-playbooks/g2.md`](provider-playbooks/g2.md) — software-review & category signal data.
- [`provider-playbooks/theSwarm.md`](provider-playbooks/theSwarm.md) — warm-intro network mapping to target companies/people.
- [`provider-playbooks/mixrank.md`](provider-playbooks/mixrank.md) — premium person/company backfill (4/lookup, phone-only reverse lookup).
**Email & contact specialists** (all feed the VERIFY step — see [`references/waterfall-strategy.md`](references/waterfall-strategy.md)):
- [`provider-playbooks/hunter.md`](provider-playbooks/hunter.md) — domain-search email finding + verification.
- [`provider-playbooks/prospeo.md`](provider-playbooks/prospeo.md) — email/phone lookup, LinkedIn-URL input path.
- [`provider-playbooks/icypeas.md`](provider-playbooks/icypeas.md) — budget email find/verify.
- [`provider-playbooks/findyMail.md`](provider-playbooks/findyMail.md) — email finding alternative.
- [`provider-playbooks/leadMagic.md`](provider-playbooks/leadMagic.md) — email + mobile lookup alternative.
- [`provider-playbooks/contactOut.md`](provider-playbooks/contactOut.md) — contact info from LinkedIn profiles.
- [`provider-playbooks/zeroBounce.md`](provider-playbooks/zeroBounce.md) — email-verification second opinion to `waterfall.verifyEmail`.
- [`provider-playbooks/bouncer.md`](provider-playbooks/bouncer.md) / [`neverBounce.md`](provider-playbooks/neverBounce.md) / [`kitt.md`](provider-playbooks/kitt.md) / [`enrichley.md`](provider-playbooks/enrichley.md) — verification long tail (0.3 / 0.2 / 0.05 / 0.1; enrichley's slug is `verify`, not `verifyEmail`).
- [`provider-playbooks/dropcontact.md`](provider-playbooks/dropcontact.md) — email finding with French/EU registry depth; `email` output is an array.
- [`provider-playbooks/enrowio.md`](provider-playbooks/enrowio.md) — email find (1) + verify (0.1); takes `fullName` only.
- [`provider-playbooks/reverseContact.md`](provider-playbooks/reverseContact.md) — company-from-LinkedIn (credits); profile lookups are own-key.
- [`provider-playbooks/rocketreach.md`](provider-playbooks/rocketreach.md) — person lookup (1); healthcare/NPI niche; beware the `currrentEmployer` schema key.
- [`provider-playbooks/cleon1.md`](provider-playbooks/cleon1.md) — terminal phone rung (15/lookup) — explicit user request only.
**Research & scraping:**
- [`provider-playbooks/firecrawl.md`](provider-playbooks/firecrawl.md) — web scraping for research/personalization stages.
- [`provider-playbooks/serper.md`](provider-playbooks/serper.md) — Google SERP queries for research and URL discovery.
- [`provider-playbooks/linkup.md`](provider-playbooks/linkup.md) — web search (0.5 standard / 2 deep) + sourced/structured answers.
- [`provider-playbooks/parallel.md`](provider-playbooks/parallel.md) — cheapest page read in the catalog (`extract`, 0.025/URL) plus `createTask`, the only action that fills a caller-supplied output schema.
- [`provider-playbooks/exa.md`](provider-playbooks/exa.md) — semantic search with a document-type `category` filter and publication-date bounds.
- [`provider-playbooks/builtwith.md`](provider-playbooks/builtwith.md) — a domain's technology stack; `getDomainSummary` is **free** and runs in front of the paid rung.
- [`provider-playbooks/sillage.md`](provider-playbooks/sillage.md) — inbound signal detections read back from a model, **free**, so it runs first on any signal question.
**LLM providers** (all: one `instruct` action, cost per 1,000-token package, per-model tiers — prompts come from [`references/prompt-library/index.md`](references/prompt-library/index.md)):
- [`provider-playbooks/anthropic.md`](provider-playbooks/anthropic.md) — judgment-tier default (Haiku/Sonnet 0.2, Opus 2); temperature nests under `advancedSettings` with required `maxTokens`.
- [`provider-playbooks/openAi.md`](provider-playbooks/openAi.md) — cheapest bulk tier (`gpt-5-nano` 0.006) + native JSON-schema output.
- [`provider-playbooks/gemini.md`](provider-playbooks/gemini.md) — cheap high-throughput (Flash 0.01, 15,000/min) + search grounding.
- [`provider-playbooks/perplexity.md`](provider-playbooks/perplexity.md) — web-grounded research answers; default model is the expensive `sonar-deep-research` — always set `model` explicitly.
## 12) References
- [`references/cost-discipline.md`](references/cost-discipline.md) — the mandatory spend rules: pilot → approval gate, per-run receipts, 1.4×N over-provision, count-first sizing, provider-billing rules.
- [`references/contact-accuracy.md`](references/contact-accuracy.md) — the deterministic QA scripts (email cull, current-role, name match, final audit) and the SEND/VERIFY/REVIEW/REMOVE verdicts.
- [`references/prompt-library/index.md`](references/prompt-library/index.md) — ~40 named, parameterized LLM prompts (personalization, scoring, research, qualification, signal analysis, extraction). **Before authoring any enrichment/scoring prompt from scratch, grep this index** — reuse beats reinvention, and each entry carries a tested output contract. Load only the shard you need, never all of them.
- [`references/stage-action-map.md`](references/stage-action-map.md) — cheapest credits-based action per stage across the full 120-integration catalog.
- [`references/credits-cost-table.md`](references/credits-cost-table.md) — auto-generated cost table for all 145 credits-based actions.
- [`references/waterfall-strategy.md`](references/waterfall-strategy.md) — canonical waterfall chains by enrichment goal (every recipe's "fallback" follows these).
- [`references/alternatives.md`](references/alternatives.md) — provider swap-ins from the long tail when the priority stack can't serve.
- [`references/output-retrieval.md`](references/output-retrieval.md) — `run download-outputs` patterns for fetching action data.
Referenced files: 94
cargo-hosting8.92 KB
---
name: cargo-hosting
description: "Put something on the internet from Cargo — Vite single-page apps served at https://<slug>.cargo.app and serverless edge workers that answer HTTP requests, plus the deployments that build and promote them. Triggers: \"build me a dashboard for this\", \"host this app\", \"give me a URL to share\", \"deploy this\", \"I need a webhook endpoint\", \"make it live\", \"promote to production\", \"put it on cargo.app\", \"ship a UI for my team\". Skip when: the app or worker should be declared as committed workspace code — use cargo-cdk."
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
---
# Cargo CLI — Hosting
**Cargo Hosting** runs two kinds of workspace-scoped resources, plus the deployments that ship them:
- **App** — a Vite single-page app served on `https://<slug>.cargo.app`, built on `@cargo-ai/app-sdk` (Vite + refine + shadcn primitives, with `getCargoEnv()` / `useCargoApi()` wired to the workspace).
- **Worker** — a serverless HTTP handler that runs on the edge (`fetch(request, env)`), built on `@cargo-ai/worker-sdk` (auto OpenAPI 3.1 spec at `/openapi.json`, Swagger UI at `/docs`).
- **Deployment** — one build+upload of a local source directory to an app or worker. A deployment is **not live until it's promoted**.
> For organizing apps/workers into **folders**, use [`cargo-workspace-management`](../cargo-workspace-management/SKILL.md) (`folder …`). The `--folder-uuid` flags here consume those folder UUIDs.
> See `references/examples/apps.md`, `references/examples/workers.md`, and `references/examples/deployments.md` for end-to-end walkthroughs.
> See `references/response-shapes.md` for JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## The lifecycle
Apps and workers follow the same shape — **scaffold → create slot → deploy → promote**:
```
init (local scaffold) → create (slot + slug) → deployment create (build+upload) → deployment promote (go live)
```
1. **Scaffold** a local project from a template — `hosting app init <dir>` / `hosting worker init <dir>`.
2. **Create the slot** in the workspace — `hosting app create --name --slug` → `appUuid` (or `workerUuid`). The `--slug` becomes the subdomain and **must be globally unique within the hosting domain**.
3. **(apps, optional) Wire local dev** — `hosting app env <appUuid>` prints the `.env.local` lines a local copy needs (Cargo OAuth + workspace + app UUID + API URL).
4. **Deploy** — `hosting deployment create --app-uuid <uuid> --source <dir>` uploads the source; the backend runs `npm ci && vite build` (apps) or bundles the entrypoint (workers) in a sandbox. Returns a `deploymentUuid`.
5. **Promote** — `hosting deployment promote --uuid <deploymentUuid>` points the live URL at that build.
Deploys build asynchronously — **poll `hosting deployment get <uuid>`** until the status is terminal before promoting (see [Async polling](#async-polling)).
## Apps
```bash
# Discover
cargo-ai hosting app list # all apps (filter with --folder-uuid <uuid>)
cargo-ai hosting app get <uuid> # one app's details + URL
# Scaffold locally (Vite + @cargo-ai/app-sdk)
cargo-ai hosting app init ./my-app --list-templates # see available templates, then:
cargo-ai hosting app init ./my-app --template blank --name "My App"
# Create the slot (slug must be globally unique → it's the subdomain)
cargo-ai hosting app create --name "My App" --slug my-app --folder-uuid <folder-uuid>
# Print .env.local for local development
cargo-ai hosting app env <app-uuid>
cargo-ai hosting app env <app-uuid> --api-url https://api.getcargo.io
# Update / remove
cargo-ai hosting app update --uuid <app-uuid> --name "Renamed"
cargo-ai hosting app update --uuid <app-uuid> --folder-uuid null # move to workspace root
cargo-ai hosting app remove <app-uuid> # also removes its deployments
```
Templates: `blank` (minimal starting point) and `territories-overview` (read-only territories grid demoing `useCargoApi()` + react-query). Run `app init <dir> --list-templates` for the current list.
## Workers
Same command shape as apps — substitute `worker` for `app`:
```bash
cargo-ai hosting worker list # filter with --folder-uuid <uuid>
cargo-ai hosting worker get <uuid>
# Scaffold (edge fetch(request, env) handler on @cargo-ai/worker-sdk)
cargo-ai hosting worker init ./my-worker --list-templates
cargo-ai hosting worker init ./my-worker --template blank --name "My Worker"
cargo-ai hosting worker create --name "My Worker" --slug my-worker --folder-uuid <folder-uuid>
cargo-ai hosting worker update --uuid <worker-uuid> --name "Renamed"
cargo-ai hosting worker remove <worker-uuid> # also removes its deployments
```
Templates: `blank` (auto OpenAPI spec + Swagger UI) and `custom-integration` (a Cargo Custom Integration — manifest / actions / extractors / autocompletes / dynamic schemas). Workers have **no `env` subcommand** — they read config from the `env` argument passed to `fetch` at runtime.
## Deployments
A deployment belongs to exactly one app **or** one worker (`--app-uuid` and `--worker-uuid` are mutually exclusive).
```bash
# List / inspect
cargo-ai hosting deployment list --app-uuid <uuid> # or --worker-uuid <uuid>
cargo-ai hosting deployment get <deployment-uuid> # status + metadata
cargo-ai hosting deployment get-promoted --app-uuid <uuid> # what's currently live
# Build & upload a local source directory (point at the package root, NOT dist/)
cargo-ai hosting deployment create --app-uuid <uuid> --source ./my-app
cargo-ai hosting deployment create --worker-uuid <uuid> --source ./my-worker
# default ignores: node_modules,dist,build,.git,.next — override with --ignore "a,b,c"
# Go live
cargo-ai hosting deployment promote --uuid <deployment-uuid>
```
## Critical rules
- **`--slug` must be globally unique within the hosting domain** — it's the live subdomain (`<slug>.cargo.app`). A clash fails at `create`.
- **Deploying ≠ going live.** `deployment create` builds and uploads; the URL only changes when you `deployment promote` that deployment. Use `deployment get-promoted` to see what's live now.
- **`--source` is the package root, not `dist/`.** The build runs in a Cargo sandbox: `npm ci && vite build` for apps, entrypoint bundling for workers. Shipping a pre-built `dist/` will not work.
- **Builds are async** — poll `deployment get` until terminal before promoting (see below).
- **`--app-uuid` / `--worker-uuid` are mutually exclusive** on `deployment create`, `deployment list`, and `deployment get-promoted`. Pass exactly one.
- **`remove` cascades** — removing an app or worker also removes all of its deployments.
- **`update --folder-uuid null`** (literal string `null`) moves a resource back to the workspace root.
- **Hosting consumes credits monthly per resource.** Each app/worker carries a `chargedUntil` that an hourly sweep advances a month at a time, so a live app or worker bills hosting credits on an ongoing basis — `remove` resources you no longer serve. Track consumption via [`cargo-billing`](../cargo-billing/SKILL.md).
## Async polling
`deployment create` kicks off a sandboxed build. The deployment's `status` moves `pending → building → success` (or `error` / `cancelled`). Poll until terminal, then promote the `success` one:
```bash
cargo-ai hosting deployment get <deployment-uuid> # poll ~2–5s until status is terminal
```
Terminal statuses are `success`, `error`, and `cancelled` — only promote a `success` deployment. On `error`, read the deployment's `errorMessage` (and `buildLogS3Filename`) to diagnose the build. For the general polling pattern (intervals, retries), see [`../cargo-orchestration/references/polling.md`](../cargo-orchestration/references/polling.md).
## Help
Every command supports `--help`:
```bash
cargo-ai hosting app create --help
cargo-ai hosting deployment create --help
```
Referenced files: 6
cargo-mcp8.61 KB
---
name: cargo-mcp
description: "Drive Cargo from its hosted MCP server at https://mcp.getcargo.io/mcp — connect a client, discover and price an action, run it over one record or a batch, poll it, and read workspace models, with no CLI install. Also when to call an MCP tool instead of shelling out to `cargo-ai`. Triggers: \"connect Cargo to Claude Desktop\", \"add Cargo to ChatGPT\", \"Cargo MCP server\", \"mcp.getcargo.io\", \"use Cargo without installing anything\", \"which Cargo tool do I call\", \"search_actions\", \"execute_action_batch\", \"MCP server is showing the wrong workspace\". Tools: whoami, search_actions, get_action_schema, execute_action, execute_action_batch, get_run, query_models. Skip when: you have a shell and the job is a workflow, a CDK deploy, or warehouse SQL — use the CLI skills; when publishing an MCP server out of your own workspace or attaching one to a Cargo agent — use cargo-ai."
version: "1.0.1"
compatibility: Requires the hosted Cargo MCP server at https://mcp.getcargo.io/mcp — OAuth (discovered from the 401 challenge) or a workspace-scoped API token as a bearer. The CLI is needed only for the jobs this skill routes away
homepage: https://github.com/getcargohq/cargo-skills
---
# Cargo — the hosted MCP server
Cargo has two surfaces. The rest of this bundle documents the CLI. This one
documents `https://mcp.getcargo.io/mcp`, and, more usefully, **when to reach for
which.**
> **Three different things here are called MCP.** This skill is the **hosted
> server Cargo runs**, which you point a client at. Publishing a curated server
> *out of* your own workspace (`ai mcp-server create`, then `cargo-ai mcp` over
> stdio) and attaching somebody else's server *to* a Cargo agent
> (`release update-draft --mcp-clients`) are both
> [`cargo-ai`](../cargo-ai/SKILL.md). Check which one the user means before
> answering: the words are identical and the answers share nothing.
## Which surface
| The job | Surface |
| --- | --- |
| Run one action, or one action over many records | either; MCP if it is already connected |
| Find what Cargo can do, and what it costs | either (`search_actions` is the MCP half) |
| Read records off a model | either |
| Warehouse SQL, aggregates, joins | **CLI** ([`cargo-storage`](../cargo-storage/SKILL.md)) |
| Build or edit a multi-step workflow, tool, or play | **CLI** ([`cargo-orchestration`](../cargo-orchestration/SKILL.md)) |
| Workspace as code, plan and deploy | **CLI** ([`cargo-cdk`](../cargo-cdk/SKILL.md)) |
| Segments, connectors, content libraries, alerts, hosting, billing admin | **CLI** |
| No shell at all (ChatGPT, Claude Desktop, claude.ai, n8n) | **MCP**, and say plainly what is out of reach |
The rule underneath the table: **MCP is the runtime, the CLI is the platform.**
Thirteen tools cover discovering an action, running it, watching it finish, and
reading data back. Everything that *builds* something reusable is CLI only. An
agent holding both should prefer the CLI for anything the user will want to
re-run or version, and MCP for one-shot execution inside a conversation.
When the job routes to the CLI, this is the whole bootstrap:
```bash
npm install -g @cargo-ai/cli
cargo-ai login --email you@company.com # emailed code, no browser; creates the account on first use
cargo-ai whoami # confirm the workspace before anything that spends
```
## Connect
The endpoint is `https://mcp.getcargo.io/mcp`, Streamable HTTP. An
unauthenticated request returns `401` with a `WWW-Authenticate` challenge
carrying `resource_metadata`, so an OAuth-capable client discovers the
authorization server, registers, and prompts the user with no configuration
beyond the URL. A `401` on first connect is the handshake, not a fault.
```bash
claude mcp add --transport http cargo https://mcp.getcargo.io/mcp
```
Any client taking a JSON block (Claude Desktop, Cursor, a project `.mcp.json`):
```json
{
"mcpServers": {
"cargo": {
"type": "http",
"url": "https://mcp.getcargo.io/mcp"
}
}
}
```
For CI, a headless agent, or a client with no OAuth, pass a workspace-scoped API
token from **Settings > API** instead. Read it from the environment; never inline
the value:
```json
{
"mcpServers": {
"cargo": {
"type": "http",
"url": "https://mcp.getcargo.io/mcp",
"headers": { "Authorization": "Bearer ${CARGO_API_TOKEN}" }
}
}
}
```
**The tool list is not fixed.** The endpoint serves the platform tools below
plus whatever that workspace published with `defineMcpServer`, so two tokens can
see two different lists. Read the list you actually got rather than the one
documented here.
## The spine
```
whoami → which workspace am I in, how many credits
search_actions → find the action, and read its cost
get_action_schema → what inputs it takes
autocomplete_action → resolve a field needing a picked id (HubSpot object type, Slack channel)
execute_action │ one record
execute_action_batch │ many records
get_run / get_batch → poll while outcome is "executing"
```
For data: `list_models` → `describe_model` → `query_models`. Alongside,
`list_runs` lists recent ad-hoc runs, and `get_usage` breaks the last 7 days of
credit spend down by integration.
**Open every session with `whoami`.** The token binds the session to exactly one
workspace and there is no flag to override it. A session pointed at the wrong
workspace returns plausible, confidently wrong reads: the models are real and
the records are real, they just belong to somebody else. Name the workspace back
to the user before acting on anything.
**`search_actions` prices the work before you do it.** Each result carries
`credits[].cost` beside the `action` object you pass verbatim to everything
downstream:
```json
{
"name": "Enrich person & find email",
"credits": [{ "cost": 0.1, "type": "fixed" }],
"action": {
"kind": "connector",
"integrationSlug": "aiArk",
"actionSlug": "enrichPerson",
"connectorUuid": "7bb944ec-0254-44bc-b0e4-8a56378e80cf"
}
}
```
**Pass that `action` object exactly as it comes, with no `config` key.** Inputs
belong in `data` (single) or `records` (batch); this surface never wants a
`config`, and `get_action_schema` supplies the empty one the backend needs on
your behalf. That is one place MCP is *safer* than the CLI, where the sibling
command `orchestration action get-output-schema` still rejects a config-less
action with a `400`. Inputs misplaced into `config` are silently dropped and the
action runs with none, so an unexplained empty result is worth checking here
first.
Four `kind` values come back: `connector` (a third-party integration), `native`
(a built-in platform operation), `tool` (a saved workflow in this workspace),
and `agent` (an AI agent in this workspace). Narrow a noisy catalog with the
`kind` and `integrationSlug` filters.
## Three ways this goes wrong
**Fanning out `execute_action`.** One call per record is slower, bills more, and
leaves nothing to inspect afterwards. `execute_action_batch` takes the same
`action` plus a `records` array, produces one batch object, and a finished batch
carries a download for its output CSV. The tool description says never to loop
it: take that literally.
**Spending before quoting.** Run **10–20 records** first, report the observed
cost and hit rate, then quote the full **record count** and **credit estimate**
and let the user approve. Hit rates on people data run 40 to 70 percent, so cost
per *usable* row is not the sticker price and is not knowable without the
sample. Full discipline:
[`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md).
**`query_models` mistaken for SQL.** It lists records off one model with a limit
and an offset. It does not aggregate, join, or filter by expression. Any
question shaped like "how many", "grouped by", or "joined to" is a CLI question
([`cargo-storage`](../cargo-storage/SKILL.md)). Say so, rather than pulling rows
and counting them yourself, which silently truncates at the limit.
## Anything that touches a person
The consent rules do not relax because the surface changed. A lawful basis, a
suppression check, and relevance to that person's job gate every step that
sources, enriches, or contacts someone. Bulk unsolicited messaging, purchased or
scraped lists, and consumer targeting are refused. The full text is
[`../cargo-gtm/references/acceptable-use.md`](../cargo-gtm/references/acceptable-use.md);
where no sibling skill is installed, the paragraph above binds on its own.
## Reporting back
Narrate and summarize; never paste raw JSON at a user. After a batch, give the
record count, the hit rate, the credits actually spent, and the download, in
that order.
Referenced files: 1
cargo-observability11.1 KB
---
name: cargo-observability
description: "Watch a Cargo workspace and get told when something breaks — scheduled threshold alerts over workflow telemetry (spans, runs, records), a storage model freshness or row count, or any SQL query, firing a connector, tool, or agent when a metric breaches. Triggers: \"alert me when\", \"notify me if\", \"let me know when the error rate\", \"monitor this workflow\", \"tell me if the sync stops\", \"warn me before I run out of credits\", \"dead man’s switch\", \"is this still running\", \"set up monitoring\", plus listing, previewing, editing, and reviewing an alert firing history. Skip when: diagnosing something that already went wrong — use cargo-diagnostics."
version: "1.0.2"
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
---
# Cargo CLI — Observability
**Alerts.** An alert is a scheduled threshold check. On every cron tick it measures a **scope** (what to watch), compares the measured value against a **threshold** (the breach condition), and on breach fires **actions** — each as its own run — and records an **event**. This is the proactive counterpart to `cargo-diagnostics`: diagnostics explains a failure *after* you notice it; an alert *tells you* the moment a metric crosses a line.
Everything lives under one CLI domain:
```bash
cargo-ai observability alert … # the alert CRUD + preview surface
cargo-ai observability event … # an alert's firing history
```
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`. Alerts are guarded by `observability:read` / `observability:write` permissions. If a create/update/remove returns a permission error, the token lacks `observability:write` — use an admin token or have one granted ([`../cargo-workspace-management/SKILL.md`](../cargo-workspace-management/SKILL.md)). When the full skill bundle is installed, [`../cargo/references/prerequisites.md`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## The three moving parts of every alert
| Part | Flag | What it is |
| --- | --- | --- |
| **Scope** | `--scope <json>` | *What* to measure — one of six sources: `spans`, `runs`, `records`, `orchestrationQuery`, `storageQuery`, `model`. |
| **Threshold** | `--threshold <json>` | *When it breaches* — a `metric` + `operator` (`gte`/`lte`) + `value`. The metric menu depends on the scope. |
| **Actions** | `--actions <json>` | *What happens on breach* — an `Action[]` (connector / tool / agent / native nodes), each fired as its own run. Optional; omit for a silent alert whose breaches you read from its events. |
The scope and threshold are a **matched pair** — a metric can only be computed over the scopes that produce it (e.g. `errorRate` needs telemetry, `freshness` needs a model). The full compatibility matrix, every metric's meaning and units, and every scope filter field are in **[`references/scopes-and-thresholds.md`](references/scopes-and-thresholds.md)** — read it before writing a `--scope`/`--threshold` pair you haven't used before.
## The golden rule: `preview` before you `create`
`alert preview` evaluates a scope + threshold **right now, without firing actions or writing an event**. It returns the value the alert would measure and whether that value breaches — so you calibrate the threshold against reality instead of guessing, and you confirm the scope/threshold pairing is even valid before committing it to a schedule.
```bash
cargo-ai observability alert preview \
--scope '{"kind":"runs","workflowUuid":"<uuid>","statuses":["error"]}' \
--threshold '{"metric":"errorRate","operator":"gte","value":10}' \
--window-minutes 1440 # last 24h; default 60
```
- `outcome: "computed"` → `{ value, total, failed, isBreached }`. Set your threshold from `value`.
- `outcome: "empty"` → the window had nothing to measure (see the empty-vs-zero rule in `references/alert-lifecycle.md`).
- `outcome: "notComputed"` → `{ errorMessage }`. A bad SQL query, a deleted model, or an **invalid scope/threshold pairing** all land here — fix it before creating.
`--window-minutes` only shapes the window for telemetry scopes (`spans`/`runs`/`records`). A `model` is measured as it stands right now; a query scope windows itself in its SQL.
**Always preview first.** It is free, it is the only way to size a threshold correctly, and it catches an invalid pairing before it becomes a schedule that writes an `error` event every tick.
## Commands
All commands output JSON. Reads need a token with `observability:read`; create/update/remove need `observability:write` (an admin token has both; a plain member token may not — see Bootstrap above).
### Create an alert
```bash
cargo-ai observability alert create \
--name "CRM sync error rate" \
--description "Page when the HubSpot sync starts failing" \
--cron "*/30 * * * *" \
--scope '{"kind":"runs","workflowUuid":"<workflow-uuid>","statuses":["error"]}' \
--threshold '{"metric":"errorRate","operator":"gte","value":10}' \
--actions '[{"kind":"agent","agentUuid":"<agent-uuid>","config":{"message":"{{alert.name}} breached: {{event.value}}% errors. {{alert.url}}"}}]'
```
- `--cron` — 5-field cron **or** `@every <interval>` (e.g. `@every 30m`), always **UTC**, at most once a minute. The UI presets bottom out at 30 minutes; go tighter only with reason (every tick scans ClickHouse and can fire paid runs).
- `--disabled` — create it paused (evaluate nothing until you `update --enabled true`).
- `--folder <uuid>` — file it under a folder (from `cargo-workspace-management`).
- `--actions` — optional. Omit for a silent alert. Each entry is a **configured** action: unlike `orchestration action execute`, which carries no `config` at all, an alert action **requires** one — that is where the templated message lives. The config is templated against the firing context (`{{alert.*}}`, `{{event.*}}`) — see [`references/alert-lifecycle.md`](references/alert-lifecycle.md) for the full variable list. Each action's target (`agentUuid`/`toolUuid`/`connectorUuid`) is validated to exist in the workspace at create time.
### List, get, update, remove
```bash
cargo-ai observability alert list # all alerts, each with its lastEvent
cargo-ai observability alert get <uuid> # one alert + its lastEvent
cargo-ai observability alert update --uuid <uuid> \
--enabled false # pause it (true/false — must be literal)
cargo-ai observability alert update --uuid <uuid> \
--threshold '{"metric":"errorRate","operator":"gte","value":20}' # raise the bar
cargo-ai observability alert update --uuid <uuid> \
--description none # "none" clears; --folder none unfiles
cargo-ai observability alert remove <uuid>
```
`--enabled` is strict: only the literal `true` or `false` are accepted — `--enabled yes` is rejected rather than silently disabling the alert. On `update`, any flag you omit is left unchanged; `--description none` / `--folder none` are the explicit "clear it" spellings.
### Inspect firing history
```bash
cargo-ai observability event list <alertUuid> # latest evaluation events, newest first
```
Each event carries `status` (`healthy` / `unhealthy` / `error`), the measured `value`, a **snapshot** of the `scope`/`threshold`/`actions` as they were when it fired (the alert can change afterwards), `runUuids` (the runs the actions spawned — feed these to `cargo-diagnostics` or `orchestration run get`), the evaluation window, and `errorMessage` for `error` events. `unhealthy` = breached and fired; `error` = the metric could not be computed.
## How evaluation actually works
The lifecycle — cron windows and the ClickHouse indexing lag, the **at-most-once** firing guarantee (an alert never re-fires on the same rows; a *sustained* breach is re-detected on the next tick), the empty-window-vs-real-zero rule that makes `lte` a dead-man's switch, and the full `{{alert.*}}`/`{{event.*}}` templating context — is documented in **[`references/alert-lifecycle.md`](references/alert-lifecycle.md)**. Read it before you rely on an alert for anything time-sensitive.
## Worked recipes
**[`references/examples/recipes.md`](references/examples/recipes.md)** — copy-paste starting points: error-rate pager, credit-budget guard, p95-latency watch, a **dead-man's switch** (`count lte 0` — alert when a workflow *stops* running), model freshness / empty-model alerts, and a custom SQL-query alert.
## Declarative alternative: `defineAlert` (CDK)
This skill is the **imperative** surface — one-off `cargo-ai observability alert …` calls. To manage an alert **as code** (in git, reproducible, deployed alongside the workflow it watches), use CDK's `defineAlert` builder instead — see [`../cargo-cdk/SKILL.md`](../cargo-cdk/SKILL.md) and "Declarative vs imperative" in the router. Same scope/threshold/action model; different authoring mode.
## Cost discipline
An alert's **actions fire as real runs** — if an action calls a paid connector action or an agent, every breach re-bills. A poorly-sized threshold on a tight cron can breach (and bill) every tick. Two safeguards:
- **Preview to size the threshold** so it fires on genuine anomalies, not normal variance.
- If an action node calls a **credits-based provider action**, treat it like any scheduled paid workflow: read that provider's playbook (esp. its *Recurring use* section) in `../cargo-gtm/provider-playbooks/`, and apply the spend rules in [`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md). Prefer cheap notification actions (an agent that posts to Slack, a connector notification) over anything that fans out.
## When the CLI surprises you
If a documented flag, scope field, or response shape doesn't match what you observe (a fix may have shipped, or the docs may have drifted), re-refresh the CLI and skills; if it still doesn't add up, file a report — it's read by the team:
```bash
cargo-ai workspaceManagement report create \
--title "<one-line summary>" \
--description "<exact command(s), errorMessage verbatim, expected vs actual, UUIDs>"
```
## Presenting results
Follow [`../cargo/references/interaction.md`](../cargo/references/interaction.md): lead with the outcome ("alert created, will page the on-call agent when the CRM sync's error rate hits 10% over 30 min"), summarize an alert or its events as a compact table, never dump raw `alert get` / `event list` JSON into the conversation.
Referenced files: 4
cargo-orchestration28.9 KB
---
name: cargo-orchestration
description: "Make Cargo actually run something, or show what it would run — execute one connector action, run a multi-step workflow, trigger a batch across a whole segment or model, message an AI agent, build or edit a node graph, draw a workflow, tool or play as a diagram, and query the runtime tables (runs, batches, spans, records) with SQL. Triggers: \"run this on all my contacts\", \"execute the action\", \"kick off a batch\", \"build a workflow\", \"schedule a play\", \"make it run every morning\", \"ask the agent\", \"show me the workflow\", \"what does this tool do\", \"visualize this play\", \"draw the graph\", \"explain this workflow\", \"how many runs failed today\", \"what is the output schema for this action\", \"add a step that\". Skip when: explaining why a run misbehaved — use cargo-diagnostics; downloading result files — use cargo-analytics; committing the workflow as code — use cargo-cdk."
version: "1.9.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
---
# Cargo CLI — Orchestration
Runtime operations for the Cargo platform.
**What do you want to run?**
```
Need to run something?
├── Don't know the action yet → action list <keywords>
├── One action, one record → action execute
├── One action, many records → action execute-batch
├── Multiple actions chained
│ ├── One-off / ad-hoc → run create --nodes (one record)
│ │ batch create --nodes (many records)
│ └── Reusable workflow → build a tool, then run create --workflow-uuid
│ or batch create --workflow-uuid
├── Conversational AI agent → message create
└── Testing ONE node of a
workflow you're building → node execute (debug only — see below)
```
> **Fanning out across many records (`action execute-batch`, `batch create`)? Sample first.** Run 10–20 records, report the observed cost and hit-rate, then ask the user to approve the full enrollment — quoting the **record count** and the **credit estimate**. See [Create a batch → the sample gate](#the-sample-gate).
> **Find the action before you hand-write the JSON.** `cargo-ai orchestration
> action list <keywords>` searches the integration catalog, Cargo native actions,
> workspace tools, and agents in one call — free, runs nothing — and each result
> carries a ready-to-paste `action` object (with `connectorUuid` already filled
> in), the action's **credit costs**, and its autocomplete slugs. Narrow with
> `--kind connector|native|tool|agent`, `--integration-slug <slug>`, `--limit`
> (default 20, max 50). `unknown command` means the CLI predates it — refresh.
> **`action execute`, not `node execute`, is the default for running something.**
> `node execute` is a **debug** surface for a node that already lives in a workflow:
> it requires `--workflow-uuid`, `--release-uuid`, `--node`, `--computed-config`
> **and** `--context` (all five, enforced client-side), and it bills like any live
> call. If you just want an operation's output — enrich a domain, call a connector
> action, invoke a tool or agent — use `action execute` / `action execute-batch`
> with a small `--action` + `--data` payload. Only reach for `node execute` when
> verifying one node's behavior before running the full graph.
> **Terminology:** An orchestration **tool** is a saved on-demand workflow (listed via `tool list`). An **action** is a single operation you execute without building a workflow — it can embed a saved orchestration tool (`kind: "tool"`), call a third-party connector (`kind: "connector"`), invoke an AI agent (`kind: "agent"`), or run a built-in platform operation (`kind: "native"`).
> **Composing a node graph? Prefer built-in actions + expressions.** Use the
> actions Cargo already provides plus template expressions; avoid `python`,
> `script` (JS), and raw HTTP nodes unless you truly have no alternative. Reshape
> data → `variables`; call an LLM and get parsed JSON → native `agent` node; call an
> API → the integration's dedicated **connector action**; route → `branch`/`filter`/`switch`.
> See **`references/node-selection.md`**.
> **Show the graph, don't describe it.** Before deploying a draft, and whenever
> the user asks what a workflow or play does, draw it:
> `cargo-ai orchestration node diagram --workflow-uuid <uuid> --format ascii --raw`
> (free, runs nothing; `--format` needs CLI ≥ 1.0.56, the command itself ≥ 1.0.54).
> Routing, fallback edges, and which steps bill are what the user is actually
> approving, and prose flattens all three. **Pick the format by where the output
> goes:** `ascii` renders a picture a person can read in a terminal or a chat
> reply; `mermaid` (the default) is source code, correct only when you are
> pasting into a PR, a doc, or a page that renders it. Sources, the ASCII legend,
> cost marking, and the duplicate-slug footgun: **`references/node-diagram.md`**.
**References:**
> `references/examples/actions.md` — action execute and execute-batch examples
> `references/examples/tools.md` — tool (on-demand workflow) examples
> `references/examples/plays.md` — play (segment-driven automation) examples
> `references/examples/agents.md` — AI agent chat examples
> `references/examples/templates.md` — pre-built workflow templates
> `references/examples/queries.md` — `orchestration query execute` (ClickHouse: runs/batches/spans/records) SQL examples. For `storage query` (workspace storage), see the `cargo-storage` skill.
> `references/examples/segments.md` — segment fetch and filter examples
> `references/nodes.md` — full node creation guide (kinds, native actions, expressions, validation, routing)
> `references/node-diagram.md` — **draw a node graph as a Mermaid flowchart** (`node diagram`): every source (workflow / draft / release / run / raw nodes), marking paid nodes, highlighting a failing node, and why diagrams key on `uuid` rather than `slug`
> `references/node-selection.md` — **how to pick the right node and avoid unnecessary `python` nodes** (decision table, native LLM `agent` node, template-expression limits, the silent-undefined footgun, inspecting node data via `runContext`, Pyodide sandbox limits, what survives a `delay`, group result access)
> `references/filter-syntax.md` — complete filter condition reference
> `references/polling.md` — async polling patterns, error handling, retry strategies
> `references/response-shapes.md` — full JSON response structures
> `references/troubleshooting.md` — common errors, plus a "Debugging a workflow run" section for runs that succeed but produce wrong output (wrong-branch routing, empty downstream values)
> **Diagnosing after the fact?** For the ordered forensic runbooks built on these surfaces — trace one run, sweep a batch for errors grouped by root cause, profile a play's credit spend — load the [`cargo-diagnostics`](../cargo-diagnostics/SKILL.md) skill.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover resources first
Most commands require UUIDs. Always discover them before acting.
```bash
cargo-ai orchestration action list <query> # actions across connectors, native, tools, agents (+ credits)
cargo-ai orchestration play list # all plays (name, workflowUuid, modelUuid, segmentUuid)
cargo-ai orchestration tool list # all tools (name, workflowUuid, description)
cargo-ai orchestration workflow list # all workflows (uuid only — no name)
cargo-ai orchestration template list # all workflow templates (slug, name, kind)
cargo-ai ai agent list # all agents (uuid, name)
cargo-ai ai template list # all AI agent templates (slug, name, languageModelSlug)
cargo-ai storage model list # all models (uuid, name, slug, columns)
cargo-ai storage dataset list # all datasets
cargo-ai segmentation segment list # all segments (uuid, name, modelUuid)
cargo-ai connection connector list # all connectors
```
**Plays vs tools:** Both are backed by a workflow. A **play** is a segment-driven automation — it reacts to data changes in a segment (records added, updated, removed). A **tool** is an on-demand workflow — triggered manually, via API, or on a cron schedule. Workflows don't have a `name` field; use `play list` or `tool list` to find names and extract the `workflowUuid`.
**Retrieve in the UI:** plays live at `app.getcargo.io/workspaces/<WORKSPACE_UUID>/plays/<PLAY_UUID>` and tools at `app.getcargo.io/workspaces/<WORKSPACE_UUID>/tools/<TOOL_UUID>`. Get `<WORKSPACE_UUID>` from `cargo-ai whoami` under `workspace.uuid`.
**Designing a new tool or play?** Check templates first — they are pre-built node graphs for common automation patterns (enrichment pipelines, CRM syncs, lead scoring) and are an excellent starting point. List templates with `cargo-ai orchestration template list` and inspect a specific one with `cargo-ai orchestration template get <slug>`. Templates are tagged by `kind` so you can find ones suited for tools (`"kind":"tool"`) or plays (`"kind":"play"`) right away. See `references/examples/templates.md` for the full guide.
**Compatibility rules:**
- **`run create`** — only works with **tool** workflows (or no `workflowUuid`). Play workflows return `playNotCompatible`.
- **`batch create`** — allowed data kinds depend on the workflow type:
- **Play** workflows: `filter`, `recordIds`, `segment`, `change`. Trigger a play with `filter`; `segment` takes a standalone segment only, never the `segmentUuid` from `play list`.
- **Tool** workflows (or no `workflowUuid`): `file`, `records`
## Quick reference
```bash
# Find an action (free — no run, no credits)
cargo-ai orchestration action list enrich company
cargo-ai orchestration action list send --kind connector --integration-slug slack
# Single actions
cargo-ai orchestration action execute --action '{"kind":"tool","toolUuid":"<uuid>"}' --data '{"domain":"acme.com"}'
cargo-ai orchestration action execute-batch --action '{"kind":"connector","integrationSlug":"clearbit","actionSlug":"enrichCompany"}' --records '[{...},{...}]'
cargo-ai orchestration action get-output-schema --action '{"kind":"connector","integrationSlug":"clearbit","actionSlug":"enrichCompany","config":{}}' # → {"schema": <JSON Schema>} without executing
# Workflows (chain multiple actions)
cargo-ai orchestration run create --workflow-uuid <uuid> --data '{"company":"Acme","domain":"acme.com"}'
cargo-ai orchestration run create --data '{"domain":"acme.com"}' --nodes '[...]'
cargo-ai orchestration batch create --workflow-uuid <uuid> --data '{"kind":"filter","modelUuid":"...","filter":{"conjonction":"and","groups":[]}}'
# AI agents
cargo-ai ai message create --chat-uuid <uuid> --parts '[{"type":"text","text":"..."}]'
# Data
cargo-ai orchestration query execute "SELECT count() FROM runs WHERE status='error'" # ClickHouse: spans, runs, batches, records
cargo-ai segmentation segment fetch --model-uuid <uuid> --filter '{"conjonction":"and","groups":[]}' --fetching-limit 100
# For SQL against workspace storage (Companies, Contacts, …), see the cargo-storage skill: `storage query execute`
```
## Polling async operations
All operations are asynchronous. Either poll until terminal state, or pass `--wait-until-finished` to block.
`action execute` returns a run. `action execute-batch` returns a batch. They poll the same way:
| Result type | Poll command | Interval | Done when |
| --------------- | -------------------- | -------- | ---------------------------------------------- |
| Run | `run get <uuid>` | 2s | `status` is `success`, `error`, or `cancelled` |
| Batch | `batch get <uuid>` | 5s | `status` is `success`, `error`, or `cancelled` |
| Agent message | `message get <uuid>` | 2s | `status` is `success` or `error` |
For long-running batches (1000+ records), increase the interval to 10-15s after the first minute.
## Execute actions
Run a single action — no workflow or node graph needed.
### Find it first — `action list`
```bash
cargo-ai orchestration action list enrich company # all kinds
cargo-ai orchestration action list --kind tool # this workspace's tools
cargo-ai orchestration action list send --kind connector --integration-slug slack
```
Free, executes nothing. All query terms must match (AND); a hit on the action
slug or name ranks above the integration, which ranks above the description.
Returns `{query, totalMatches, results[]}` where each result carries `name`,
`description`, `score`, an `action` object to paste straight into `execute` /
`execute-batch` / `get-output-schema`, the workspace `connectors` for that
integration, `credits` (the cost table, when the action bills), and
`autocompletes` (config fields that need a picked id — a HubSpot object type, a
Slack channel). Defaults to 20 results, max 50.
```bash
# One action, one record → returns a run
cargo-ai orchestration action execute \
--action '{"kind":"connector","integrationSlug":"clearbit","actionSlug":"enrichCompany"}' \
--data '{"domain":"acme.com"}' \
--wait-until-finished
# One action, many records → returns a batch
cargo-ai orchestration action execute-batch \
--action '{"kind":"tool","toolUuid":"<tool-uuid>"}' \
--records '[{"domain":"acme.com"},{"domain":"globex.com"}]' \
--wait-until-finished
```
Action kinds: `tool`, `connector`, `agent`, `native`. See `references/examples/actions.md` for all action kinds, parameters, retry config, response shapes, and end-to-end examples.
> **A top-level action has no `config` — omit it.** Inputs belong in `--data` /
> `--records`; `execute` and `execute-batch` take the action with no `config` key
> at all, which is exactly what `action list` hands back, so its result pastes
> straight in. (`"config": {}` is still accepted there, harmlessly.)
>
> **The exception that will bite you: `get-output-schema` still *requires*
> `config`.** Give it the same action object from `action list` and it fails
> `400 — expected record, received undefined` at `action.config`. Add `"config": {}`
> for that one command. Workflow **nodes**, an alert's `--actions`, a play's
> `healthAlertActions`, and an agent's or MCP server's `--actions` require it too
> — that is where a node's real configuration lives.
>
> **Inputs put in `config` are now dropped, not rejected.** The guard that used to
> answer `A top-level action does not use action.config…` is gone, so the action
> runs with *no input* — you get a provider-side missing-field error or an empty
> result that never mentions `config`. Check this first when a call comes back
> empty for no visible reason.
> **`execute-batch` bills per record.** Pass a 10–20 record slice of `--records` first, report the observed per-record cost and hit-rate, and get approval (with the full record count and credit estimate) before sending the rest — same gate as [Create a batch](#the-sample-gate).
### Resolve an action's output schema (without executing)
**Never guess what an action outputs.** Two free sources — no run, no credits:
1. **Connector actions:** the integration catalog carries the output schema inline — `integration get <slug>` (and `integration list`) return `actions.<actionSlug>.output.schema` next to the input `config.jsonSchema`. Not every action declares one.
2. **Any action kind** (`tool` / `connector` / `agent` / `native`) — resolve it with the same `--action` object as `action execute`:
```bash
cargo-ai orchestration action get-output-schema \
--action '{"kind":"connector","integrationSlug":"clearbit","actionSlug":"enrichCompany","config":{}}'
# → {"schema": {"type": "object", "properties": {...}}} — the JSON Schema is under the top-level "schema" key
```
Actions that declare no output schema fail with `"Action has no output schema."` (non-zero exit, status 404) — that's the signal to fall back to inspecting `runContext` from a real run. Use these to:
- Know which fields a downstream node can read (`{{nodes.<slug>.<field>}}`) **before** wiring the graph.
- See an `agent` action's real output envelope — a default free-text agent resolves to `{"schema":{"type":"object","properties":{"answer":{"type":"string"}}}}`, which is why downstream references need `{{nodes.<slug>.answer...}}`.
- Map an action's output onto storage columns without a throwaway run.
See `references/examples/actions.md` ("Resolve an action's output schema") for verified per-kind examples and the response/error shapes.
## Create a run
A run processes a single record through a workflow. Use `run create` when you need to **chain multiple actions** together via a node graph, or when running an existing tool workflow.
**Runs only work with tool workflows.** Play workflows return `playNotCompatible` — use `batch create` instead.
```bash
cargo-ai orchestration run create \
--workflow-uuid <tool.workflowUuid> \
--data '{"company":"Acme","domain":"acme.com"}'
# → Poll with: cargo-ai orchestration run get <run-uuid>
# Or wait synchronously — blocks until the run reaches a terminal state and returns the final result
cargo-ai orchestration run create \
--workflow-uuid <tool.workflowUuid> \
--data '{"company":"Acme","domain":"acme.com"}' \
--wait-until-finished
```
Also supports `--release-uuid` to pin a specific release.
**Cancelling runs:**
```bash
cargo-ai orchestration run cancel --workflow-uuid <uuid> --uuids run-uuid-1,run-uuid-2
```
See `references/examples/tools.md` for file uploads, monitoring, and cancellation. See `references/nodes.md` for custom node graphs.
## Create a batch
> **Sample first, then ask before enrolling everything — blocking.** A batch fans one workflow across every record in its data source, so a mistake and a full bill land together. Never enroll a full segment/file/model on the first attempt: run a **10–20 record sample**, report what it cost and returned, then ask the user to approve the full enrollment with the **record count and credit estimate** in the question. Mechanics below; the spend rules behind it are [`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md).
### The sample gate
**1. Count the pool first (free).** Never quote an estimate from a guess:
```bash
cargo-ai segmentation segment get <segment-uuid> # → recordsCount (also on `segment list`)
cargo-ai storage query execute "SELECT count() FROM <dataset>.<model>" # for a filter/model source
# For a file source: wc -l on the CSV, minus the header row.
```
**2. Run 10–20 records through the exact workflow and config.** Sample by data kind:
```bash
# Play workflow, segment source → reuse the segment's own filter, capped by `limit`
cargo-ai segmentation segment get <segment-uuid> # → copy .filter and .modelUuid
cargo-ai orchestration batch create \
--workflow-uuid <play.workflowUuid> \
--data '{"kind":"filter","modelUuid":"<modelUuid>","filter":<segment.filter>,"limit":15}' \
--wait-until-finished
# Play workflow, explicit records → pick 10–20 ids
cargo-ai orchestration batch create \
--workflow-uuid <play.workflowUuid> \
--data '{"kind":"recordIds","modelUuid":"<modelUuid>","ids":["id-1","…","id-15"]}'
# Tool workflow, inline records → slice the array
cargo-ai orchestration batch create \
--workflow-uuid <tool.workflowUuid> \
--data '{"kind":"records","records":[ /* first 15 only */ ]}'
# Tool workflow, file → upload a truncated CSV (header + 15 rows), not the full file
head -n 16 leads.csv > leads-sample.csv
cargo-ai workspaceManagement file upload --file ./leads-sample.csv
```
`limit` is the sampling lever for `kind: "filter"`. `kind: "segment"` and `kind: "change"` have **no limit** — they always enroll the whole set, so sample via `filter` or `recordIds` and switch to `segment` only for the approved full run.
**3. Report the sample, then ask.** The confirmation must carry both numbers the user needs to decide:
```
Sample: 15 of 1,240 records · 6.2 credits (0.41/record) · 13/15 enriched (87%)
Full enrollment: 1,225 remaining records ≈ 502 credits (balance: 780)
Enroll all 1,225? Or:
1. Enroll all 1,225 (≈502 cr, leaves ~278)
2. Trim scope — e.g. the 610 records with a domain set (≈250 cr)
3. Stop here and review the sample output first
```
Wait for an explicit answer. **Do not enroll the full set on an unanswered question**, and don't treat approval of the sample as approval of the full run. Skip the gate only when the batch is free (no paid nodes) *and* small, or when the user has already named the scope and approved the cost this session.
Batches process multiple records at once. Allowed data kinds depend on the workflow type:
- **Play** workflows: `filter`, `recordIds`, `segment`, `change`
- **Tool** workflows (or no `workflowUuid`): `file`, `records`
Use `filter` to trigger a play — it queries the model directly. `segment` only
accepts a **standalone** segment from `segmentation segment list`; passing the
`segmentUuid` that `play list` returns is rejected (`segmentLinkedToPlay`, or
`noRecords` on older backends) because a play's generated segment never has a
populated record count.
```bash
# Play workflow — run over the play's model (empty filter = all rows)
cargo-ai orchestration batch create \
--workflow-uuid <play.workflowUuid> \
--data '{"kind":"filter","modelUuid":"...","filter":{"conjonction":"and","groups":[]}}'
# Tool workflow — run on a file
cargo-ai orchestration batch create \
--workflow-uuid <tool.workflowUuid> \
--data '{"kind":"file","s3Filename":"..."}'
# → Poll with: cargo-ai orchestration batch get <batch-uuid>
# Or wait synchronously — blocks until the batch reaches a terminal state and returns the final result
cargo-ai orchestration batch create \
--workflow-uuid <play.workflowUuid> \
--data '{"kind":"filter","modelUuid":"...","filter":{"conjonction":"and","groups":[]}}' \
--wait-until-finished
```
**Downloading results:** get the `releaseUuid` from batch get, then `cargo-ai orchestration release get <release-uuid>` to find `nodes[].slug`, then `cargo-ai orchestration batch download --uuid <batch-uuid> --output-node-slug <slug>`.
**Cancelling a batch:**
```bash
cargo-ai orchestration batch cancel <batch-uuid>
```
See `references/examples/plays.md` and `references/examples/tools.md` for filtering, record IDs, file uploads, monitoring, and cancellation.
## Send a message to an AI agent
```bash
cargo-ai ai agent list # 1. Find the agent
cargo-ai ai chat create \ # 2. Create a chat
--trigger '{"type":"draft"}' \
--agent-uuid <agent-uuid> --name "Research session"
cargo-ai ai message create \ # 3. Send a message
--chat-uuid <chat-uuid> \
--parts '[{"type":"text","text":"Find the VP of Sales at Acme Corp"}]'
# → Extract assistantMessage.uuid, poll with: cargo-ai ai message get <uuid>
# Done when .message.status is "success" (read .parts) or "error" (read .errorMessage)
```
Also supports `--actions`, `--resources`, `--language-model-slug`, `--temperature`, `--max-steps`, and `--wait-until-finished` (blocks until the assistant message reaches a terminal status). See `references/examples/agents.md` for multi-turn conversations, action/resource injection, and model selection.
## Inspect records
Records are individual items processed by a workflow. Use these commands to list, count, download, or cancel records within a workflow.
```bash
# List records for a workflow
cargo-ai orchestration record list --workflow-uuid <uuid> --limit 50
# Filter by batch or status
cargo-ai orchestration record list --workflow-uuid <uuid> --batch-uuid <uuid> --statuses error
# Count records
cargo-ai orchestration record count --workflow-uuid <uuid>
# Download records as a file
cargo-ai orchestration record download --workflow-uuid <uuid>
# Get per-node execution metrics
cargo-ai orchestration record get-metrics --workflow-uuid <uuid>
# Cancel records
cargo-ai orchestration record cancel --workflow-uuid <uuid> --ids record-id-1,record-id-2
```
## Query orchestration history (orchestration query)
Run SQL against orchestration runtime tables — `spans`, `runs`, `batches`, `records` — with `orchestration query execute`. Use this for ad-hoc analytics on workflow execution (error rates, throughput, slowest nodes) without the workflow-scoped filters of `run get-metrics` / `run count`.
```bash
cargo-ai orchestration query execute "SELECT count() FROM runs WHERE status = 'error'"
cargo-ai orchestration query execute "SELECT status, count() FROM batches GROUP BY status"
cargo-ai orchestration query execute "SELECT * FROM spans ORDER BY execution_started_at DESC LIMIT 10"
```
Tables are referenced without a schema prefix — just `spans`, `runs`, `batches`, or `records`. Workspace scoping is applied automatically. The query is read-only; DDL, table functions, dictionary accessors, and introspection are denied. See `references/examples/queries.md` for the schemas, example queries, and limits.
## Fetch segment data
Retrieve live records from a segment. **IMPORTANT:** requires `--model-uuid` (not `--segment-uuid`). Get the `modelUuid` from `segment list`. Filter JSON uses `conjonction` (not `conjunction`) — this is intentional.
```bash
cargo-ai segmentation segment fetch \
--model-uuid <uuid> \
--filter '{"conjonction":"and","groups":[]}' \
--fetching-limit 100 --fetching-offset 0
```
Supports `--sort`, `--enrich`, and `--sync`. See `references/filter-syntax.md` for the full filter syntax and `references/examples/segments.md` for filtering, pagination, sorting, enrollment filters, and enrichment.
**Managing segments:**
```bash
# Update a segment's name or filter
cargo-ai segmentation segment update --uuid <segment-uuid> --name "Updated Name"
cargo-ai segmentation segment update --uuid <segment-uuid> --filter '{"conjonction":"and","groups":[...]}'
# Remove a segment (fails if linked to a workflow)
cargo-ai segmentation segment remove <segment-uuid>
```
## Use a workflow template
Templates are pre-built node graphs for common automation patterns (enrichment pipelines, CRM syncs, lead scoring). Browse with `template list`, inspect with `template get <slug>`, fill in placeholders, validate, and run.
```bash
cargo-ai orchestration template list # list available templates
cargo-ai orchestration template get <slug> # get template nodes + config
```
See `references/examples/templates.md` for the full guide including placeholder conventions and end-to-end examples.
## Validate and test nodes
Always validate custom node graphs before running them.
```bash
cargo-ai orchestration node validate --nodes '[...]'
# → { "outcome": "valid" } or { "outcome": "notValid", "invalidNodes": [...] }
```
Then **show it before deploying it** — `validate` proves the graph is well-formed,
not that it does what the user asked for:
```bash
cargo-ai orchestration node diagram --nodes '[...]' --format ascii --raw # free, runs nothing
```
Same command draws a deployed workflow (`--workflow-uuid`), a draft (`--draft`), a
release (`--release-uuid`), or the graph a run executed (`--run-uuid`). See
`references/node-diagram.md`.
For debugging, use `node compute` (dry-run expressions) or `node execute` (live test of one node **of an existing workflow** — needs `--workflow-uuid` + `--release-uuid` + `--computed-config`, and costs credits; for anything that isn't node-level debugging, use `action execute` instead). For runs that complete with `status: success` but produce wrong output (wrong branch taken, empty downstream values), use `run.executions[].title` from `run get` only as a quick summary — it may be truncated — and read `runContext.<nodeSlug>` (returned at the top level of the same `run get <run-uuid>` response) to verify field-level data. See `references/troubleshooting.md` → "Debugging a workflow run" and `references/nodes.md` for the full node creation guide, validation error codes, and examples.
## Help
Every command supports `--help`:
```bash
cargo-ai orchestration run create --help
cargo-ai orchestration template list --help
cargo-ai orchestration node validate --help
cargo-ai ai message create --help
cargo-ai orchestration query execute --help
```
Referenced files: 15
cargo-quickstart8.94 KB
---
name: cargo-quickstart
description: "Guided first-run demo for Cargo — one persona question to the accounts that match it, with a free pool count and a cost receipt, in under two minutes, ending by saving the pull as a recurring play. Triggers: \"show me what Cargo can do\", \"give me a demo\", \"take me on a tour\", \"quickstart\", \"getting started with Cargo\", \"I just installed Cargo\", \"my workspace is empty\", \"does this actually work\". Skip when: the user has a real job to run (build an account list, enrich a CSV) — use cargo-gtm; when they want CLI reference or routing — use the cargo router skill."
version: "1.0.2"
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
---
# Cargo Quickstart — first value in two minutes
One guided demo: size the user's addressable market for free, pull 25 of those accounts, show the cost receipt, then save the pull as a recurring play. The point is not the list — it's that in minute 3 the user owns a running system, not a one-off result.
**A new account starts with 100 free credits — no card.** This demo spends about **0.25** of them. Say that out loud before the first paid call ("this costs a quarter of a credit of your 100 free ones"): it converts the moment from *a purchase decision* into *a look around*, which is the whole job of a quickstart. Never let a new user think the demo is why they'd run out.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## The one question
Ask exactly **one** question before doing anything:
> **"Who do you sell to?"** (a persona in a few words — e.g. "Heads of RevOps at mid-market SaaS")
Everything else — provider, filters, limits — you decide. Don't ask about output format, volume, or providers; defaults below.
## Speed budget — HARD RULES
The demo has a two-minute budget from answer to deliverable. On the fast path:
- **No discovery detours.** Do not run `cargo-ai --version`, `cargo-ai whoami`, `connection connector list`, or any exploratory command first. Auth problems will surface as errors on the first real call — handle them then.
- **One command block per step**, no narration between commands.
- **Paid work is capped at ~1 credit total.** The demo uses the cheapest account search in the catalog (`aiArk.searchCompanies`, 0.01/record → 25 records = 0.25 credits) on **cargo's managed connection**, so it works on a workspace with nothing wired up yet. Nothing else paid runs without asking.
- **Never dead-end.** Every step has a fallback (ladder below). If a rung fails, drop one rung silently and keep moving.
## Fast path
Translate the persona into two things: the **title its buyer holds** (`employeeRole.employee_title_or` — companies that employ that role) and the **company shape** around it (`employeeSize`, and `industry` when the persona names one). Then count for free before paying for anything.
```bash
# 1. Count the pool — FREE (countCompanies is fixed-cost 0). This is the demo's
# first beat: the user's whole addressable market, before a credit is spent.
FILTER='{"employeeRole": {"employee_title_or": ["<buyer title>", "<buyer title variant>"]},
"employeeSize": {"min_employee_count": 50, "max_employee_count": 1000},
"industry": {"industry_or": ["<industry>"]}}'
cargo-ai orchestration action execute \
--action '{"kind":"connector","integrationSlug":"aiArk","actionSlug":"countCompanies"}' \
--data "$FILTER" --wait-until-finished > /tmp/quickstart-count.json
# 2. Pull 25 of them — 0.01/record, so this is 0.25 credits.
cargo-ai orchestration action execute \
--action '{"kind":"connector","integrationSlug":"aiArk","actionSlug":"searchCompanies"}' \
--data "$(jq -c '. + {limit: 25}' <<<"$FILTER")" \
--wait-until-finished > /tmp/quickstart-run.json
# 3. Fetch the output data (NOT in the execute stdout) — signed URL, then filter to THIS run
RUN_UUID=$(jq -r '.run.uuid' /tmp/quickstart-run.json)
WF_UUID=$(jq -r '.run.workflowUuid' /tmp/quickstart-run.json)
curl -fsS "$(cargo-ai orchestration run download-outputs \
--workflow-uuid "$WF_UUID" --output-node-slug action --format json | jq -r '.url')" \
> /tmp/quickstart-outputs.json
# 4. Show the table (the file holds ALL of the workflow's runs — filter by _uuid;
# each row's .output is the company array directly, fields are snake_case)
jq -r --arg u "$RUN_UUID" \
'[.[] | select(._uuid==$u)][0].output[]
| [.name, .industry, (.employee_count|tostring),
([.city,.country]|map(select(.!=null and .!=""))|join(", ")), .domain] | @tsv' \
/tmp/quickstart-outputs.json | column -t -s $'\t'
```
Show the table (company · industry · headcount · location · domain), not the raw JSON. **Lead with the count from step 1** — "1,904 companies match that description; here are 25 of them, for a quarter of a credit" is the demo's headline, because it reframes the 25 rows as a sample of a market rather than a list. Companies only; the demo names no individuals.
Filter notes worth knowing before you improvise:
- `industry_or` takes ordinary lowercase strings — `"software development"`, `"financial services"` — matching what comes back in each row's `industry`. Drop the group entirely when the persona doesn't name an industry; adding it typically halves the pool.
- Every group is nested (`_or` includes, `_not` excludes) and headcounts are numbers, not strings. Other useful groups on the same action: `technologies`, `funding`, `companyLocation`, `headcountGrowth`.
- Rows also carry `linkedin_url`, `revenue`, `founded_year`, and `technologies` if a richer table suits the persona better.
### Fallback ladder (on auth/error, drop a rung — don't stop)
1. `aiArk.searchCompanies` (0.01/record, managed connection) — primary.
2. `salesNavigator.searchAccounts` (0.05/record) — same idea by industry, headcount and geo. 25 rows ≈ 1.25 credits, just over the demo cap, so **say the number before running it**: "about a credit more than planned — still ~1.5 of your 100 free credits."
3. `theirStack.searchCompanies` (0.5/call, flat) — reframe as "companies hiring for your persona's role right now". Needs its own connector, so it is a rung, not the default.
4. Nothing connected at all → run the free path: `cargo-ai connection integration list | head`, show what *could* be wired, and offer to connect one (browser auth) — the demo resumes after.
## The receipt (mandatory, verbatim discipline)
The demo is itself the pilot from [`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md). Close it with a receipt:
- Credits spent + balance remaining (`cargo-ai billing subscription get` — remaining = `subscriptionAvailableCreditsCount − subscriptionCreditsUsedCount`). For a brand-new account, frame it against the **100 free starting credits** rather than as a bare number — "0.25 spent, 99.75 of your 100 free credits left" lands very differently from "99.75 credits remaining".
- Hit-rate: "25 of 25 returned" (or what actually came back, and which rows look off), against the free pool count from step 1.
## Minute 3 — save it as a play
Immediately offer to make the pull recurring — this is the step that shows what Cargo *is*:
> "Want this to run by itself? I can save this exact search as a play that runs weekly and writes new matches into a model — new `<persona>` accounts land without you asking."
On yes, follow [`../cargo-gtm/recipes/save-as-play.md`](../cargo-gtm/recipes/save-as-play.md) with the demo's action + filter as the workflow body and a weekly cron. `searchCompanies` bills per returned record on every run, so dedup against the workspace model (`cargo.matchBusiness`) before any paid downstream node.
## After the demo — route onward
Propose 2–3 next steps grounded in the rows just pulled, per the next-step spec in [`../cargo-gtm/SKILL.md`](../cargo-gtm/SKILL.md) (§4): e.g. "enrich these 25 with firmographics (~0.5 cr each)", "check which of them run your category's tooling", or something else entirely. From here, real GTM work belongs to [`cargo-gtm`](../cargo-gtm/SKILL.md) — read it before anything beyond the demo.
Referenced files: 1
cargo-segmentation11.5 KB
---
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
---
# 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`](../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.
```bash
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`](../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.
```bash
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
```bash
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`](../cargo-orchestration/references/filter-syntax.md). The shape:
```json
{
"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.
```bash
# 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`](../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.
```bash
# 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`](../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`](../cargo-orchestration/references/examples/plays.md).
- **Export it** — [`../cargo-analytics/SKILL.md`](../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`](../cargo-observability/SKILL.md).
- **Act on it as GTM** — signal segments (job change, funding, tech intent) drive the recipes in [`../cargo-gtm/SKILL.md`](../cargo-gtm/SKILL.md).
- **Declare it as code** — `defineSegment` in [`../cargo-cdk/SKILL.md`](../cargo-cdk/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:
```bash
cargo-ai workspaceManagement report create \
--title "<one-line summary>" \
--description "<commands run, errorMessage verbatim, expected vs actual, UUIDs>"
```
Referenced files: 3
cargo-storage13.8 KB
---
name: cargo-storage
description: "Work with the data inside a Cargo workspace — models (Companies, Contacts, Deals…), datasets, columns, relationships, records, and SQL over workspace storage. Triggers: \"what models do I have\", \"show me the schema\", \"add a column for\", \"how many contacts do I have\", \"SELECT … FROM\", \"query my companies table\", \"join contacts to companies\", \"what is the DDL\", \"set up a webhook-fed model\", \"where does this field live\", \"import this into a model\", \"unify these models\", \"merge duplicate accounts\", \"link contacts to companies\", \"set up a relationship between\". Skip when: querying run or batch telemetry rather than business data — use cargo-orchestration; naming a reusable filtered audience — use cargo-segmentation."
version: "1.2.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
---
# Cargo CLI — Storage
Data layer management: inspecting and modifying models, datasets, columns, relationships, unification, and records, and running SQL queries against workspace storage.
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/models.md` for model CRUD, DDL inspection, and schema discovery examples.
> See `references/examples/datasets.md` for dataset listing and navigation examples.
> See `references/examples/columns.md` for column creation and management examples.
> See `references/examples/queries.md` for `storage query execute` / `storage query download` SQL examples (WHERE, aggregations, joins, pagination, exports).
> See `references/examples/ingest-webhook.md` for ingest (webhook-fed) models — deriving the webhook URL and POSTing records.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover resources first
Always list before inspecting or modifying.
```bash
cargo-ai storage dataset list # all datasets (uuid, slug)
cargo-ai storage model list # all models (uuid, name, slug, columns)
cargo-ai storage model list --dataset-uuid <uuid> # models in a specific dataset
```
**Retrieve in the UI:** models live at `app.getcargo.io/workspaces/<WORKSPACE_UUID>/models/<MODEL_UUID>`. Get `<WORKSPACE_UUID>` from `cargo-ai whoami` under `workspace.uuid`.
## Quick reference
```bash
cargo-ai storage model list
cargo-ai storage model get <model-uuid>
cargo-ai storage model get-ddl <model-uuid>
cargo-ai storage dataset list
cargo-ai storage column list --model-uuid <uuid>
cargo-ai storage relationship list
cargo-ai storage record list --model-uuid <uuid>
cargo-ai storage query execute "SELECT * FROM default.companies LIMIT 10"
cargo-ai storage query download --query "SELECT * FROM default.companies"
```
## Models
Models are structured tables in your workspace (e.g. Companies, Contacts).
```bash
# List all models
cargo-ai storage model list
# List models in a dataset
cargo-ai storage model list --dataset-uuid <uuid>
# Get a single model (includes columns)
cargo-ai storage model get <model-uuid>
# Get the DDL (full schema, table name and SQL dialect)
cargo-ai storage model get-ddl <model-uuid>
# → Useful for column discovery and SQL dialect (BigQuery vs Snowflake) before writing queries
# Create a model
cargo-ai storage model create \
--slug contacts \
--name "Contacts" \
--dataset-uuid <uuid> \
--extractor-slug <extractor-slug> \
--config '{}'
# Update a model
cargo-ai storage model update --uuid <model-uuid> --name "New Name"
# Remove a model
cargo-ai storage model remove <model-uuid>
```
**Querying:** Use `cargo-ai storage query execute "<sql>"` (or `storage query download --query "<sql>"` for full exports) to run SQL against storage. Tables are referenced as `<datasetSlug>.<modelSlug>` (e.g. `default.companies`) and rewritten to the underlying storage table under the hood. See [Query with SQL](#query-with-sql) below.
## Ingest models (webhook-fed)
A model whose extractor has `mode.kind === "ingest"` — `http.listenHook` and
friends — is filled by **pushing** records to Cargo. The app shows a "Webhook URL"
on the model settings screen; **no CLI command or API field returns it**, but it's
assembled from values the CLI already exposes:
```
<baseUrl>/v1/models/<model-uuid>/records/ingest?token=<api-token>
```
```bash
MODEL_UUID=<model-uuid>
BASE=$(cargo-ai whoami | jq -r '.baseUrl')
TOKEN=$(cargo-ai workspaceManagement token list | jq -r '.tokens[0].token')
echo "$BASE/v1/models/$MODEL_UUID/records/ingest?token=$TOKEN"
```
Check the extractor's mode first — when it reports `"autoIngest": true` (calendly,
smartlead, instantlyV2, heyReach, cargo signals) Cargo registers the
hook with the provider itself and the URL must **not** be handed out. Full flow,
payload shapes, and limits: `references/examples/ingest-webhook.md`.
## Datasets
Datasets are logical groupings of models.
```bash
# List all datasets
cargo-ai storage dataset list
# Get a single dataset
cargo-ai storage dataset get <dataset-uuid>
```
## Columns
Columns define the schema of a model.
```bash
# List columns for a model
cargo-ai storage column list --model-uuid <uuid>
# Create a column
cargo-ai storage column create \
--model-uuid <uuid> \
--column '{"slug":"my_column","type":"string","label":"My Column","kind":"custom"}'
# Update a column (pass the full column object — columns are identified by slug, not UUID)
cargo-ai storage column update \
--model-uuid <uuid> \
--column '{"slug":"my_column","type":"string","label":"Updated Label","kind":"custom"}'
# Remove a column
cargo-ai storage column remove --model-uuid <uuid> --column-slug <slug>
# Reorder a column (move to a specific index)
cargo-ai storage column reorder --model-uuid <uuid> --column-slug <slug> --to-index 2
```
Column types: `string`, `number`, `boolean`, `date`, `object`, `array`, `vector`, `any`.
Column kinds: `custom` (user-defined), `computed` (expression over other columns), `metric` (aggregated from a related model), `lookup` (single field pulled from a related model via a join).
## Preview what you built
A column list doesn't tell the user whether the model is right — rows do. Two checkpoints (the pack-wide convention lives in [`../cargo/references/interaction.md`](../cargo/references/interaction.md) §4):
**1. Right after `model create` / `column create` — show the schema, not rows.** A new model is empty; a `LIMIT 10` here returns nothing and reads as failure. Echo the columns as a compact table instead (column, type, what will fill it).
**2. As soon as data lands — show the rows.** After a batch, play, or import writes into the model, preview it:
```bash
cargo-ai storage query execute \
"SELECT * FROM <dataset-slug>.<model-slug> LIMIT 10"
```
Show ~10 rows and only the columns that carry meaning. Storage queries are free, so this costs nothing but a few lines of output — and it's the first moment the user can actually see what they built. When a play fills a *new* column, preview that column next to the record's identifying fields (`name`, `domain`) so filled vs. empty is obvious.
If the preview comes back empty or all-null when it shouldn't, that's a finding — surface it rather than reporting the write as a success. See [`cargo-diagnostics`](../cargo-diagnostics/SKILL.md) to trace why.
## Relationships
Relationships link models together (e.g. Contacts belong to Companies). They are
authored from the CLI, not just the UI.
`relationship list` takes **no flags** — it returns every relationship in the
workspace. Filter client-side on `fromModelUuid` / `toModelUuid`.
```bash
cargo-ai storage relationship list
```
**`relationship set` replaces the dataset's whole relationship set.** It takes a
dataset and the complete list that should exist within it: entries carrying a
`uuid` are updated, entries without one are created, and **any existing
relationship whose `uuid` is absent from the payload is deleted**. Sending one
relationship to a dataset that has five removes the other four. Always `list`
first, then send back the full array with your addition:
```bash
cargo-ai storage relationship set \
--dataset-uuid <dataset-uuid> \
--relationships '[
{"uuid":"<existing-uuid>","fromModelUuid":"<contacts-uuid>","fromColumnSlug":"account_id","toModelUuid":"<companies-uuid>","toColumnSlug":"id","relation":"manyToOne"},
{"fromModelUuid":"<deals-uuid>","fromColumnSlug":"company_id","toModelUuid":"<companies-uuid>","toColumnSlug":"id","relation":"manyToOne"}
]'
```
`relation` is `oneToOne`, `manyToOne`, or `oneToMany`. Both models must live in
the dataset you pass — relationships never span datasets, so `fromDatasetUuid`
and `toDatasetUuid` on the response always equal `--dataset-uuid`.
Failure reasons: `datasetNotFound`; `invalidRelationships` (a column slug or
model UUID that doesn't resolve, or a duplicate — including the same pair stated
in reverse); `modelNotCompatible` (see below).
**Unify models refuse manual relationships.** In the native dataset, a unify
model's relationships are generated during sync, so naming one as `fromModelUuid`
or `toModelUuid` returns `modelNotCompatible`. Those auto-generated rows are also
excluded from the replace above, so a `set` call cannot delete them.
## Unification
Unification is what merges records from several source models into one canonical
account/contact — and it is **configurable from the CLI**, via `--unification` on
`model update`. Pass `null` to clear it.
```bash
# Connector-driven: the integration decides how records unify
cargo-ai storage model update --uuid <model-uuid> --unification '{"source":"integration"}'
# Custom: you name the type, the matching keys, and optionally a parent
cargo-ai storage model update --uuid <model-uuid> --unification '{
"source": "custom",
"type": "account",
"uniqueColumns": [{"slug":"domain","reference":"domain"}],
"selectedColumnSlugs": ["name","industry","employee_count"],
"parent": {"kind":"model","columnSlug":"account_id","parentModelUuid":"<accounts-uuid>"}
}'
```
| Field | Applies to | Meaning |
|---|---|---|
| `source` | both | `integration` (connector-defined) or `custom` |
| `type` | custom | `account`, `contact`, `accountEvent`, `contactEvent` |
| `uniqueColumns` | custom | Match keys — `{slug, reference}` per column. This is what decides which rows are the same entity |
| `selectedColumnSlugs` | custom | Columns carried into the unified model. Omit for all |
| `timeColumnSlug` | custom | Event timestamp — for the two `*Event` types |
| `parent` | custom | Links contacts/events to their account: `{"kind":"model","columnSlug":…,"parentModelUuid":…}` or `{"kind":"reference","columnSlug":…,"reference":…}` |
| `filter` | custom | Segmentation filter restricting which rows unify — same `conjonction` shape as segments |
**Writing the config does not recompute anything.** The unified rows are rebuilt
by the model's sync run, so follow the update with a run and poll it:
```bash
cargo-ai storage run create --model-uuid <model-uuid>
cargo-ai storage run list --model-uuid <model-uuid>
```
Get the current config from `storage model get <uuid>` → `unification` (`null`
when the model doesn't unify). Once the run finishes, check the row count with
`storage query execute` before treating the change as done — a too-narrow
`uniqueColumns` under-merges and a too-broad one collapses distinct entities, and
both look like a successful run.
## Records
```bash
# List records in a model
cargo-ai storage record list --model-uuid <uuid>
```
For advanced record queries (filtering, sorting, pagination), use `segmentation segment fetch` from the `cargo-orchestration` skill.
## Query with SQL
Run SQL against workspace storage with `storage query execute`. Tables are referenced as `<datasetSlug>.<modelSlug>` (e.g. `default.companies`) and rewritten to the underlying storage table under the hood — no DDL lookup is needed for the table name.
```bash
cargo-ai storage query execute \
"SELECT name, domain FROM default.companies LIMIT 10"
# → { "rows": [...] } on success; non-zero exit with { "errorMessage": "..." } on error
```
For full exports, use `storage query download` — it returns a signed URL to a CSV (default) or Parquet file:
```bash
cargo-ai storage query download \
--query "SELECT name, domain, revenue FROM default.companies ORDER BY revenue DESC"
cargo-ai storage query download \
--query "SELECT * FROM default.companies" --format parquet
```
Get column slugs from `storage column list --model-uuid <uuid>` (or run `storage model get-ddl <model-uuid>` for the full schema and SQL dialect). Page through large result sets with `LIMIT` / `OFFSET` directly in the SQL.
See `references/examples/queries.md` for WHERE clauses, aggregations, joins, date queries, pagination, and the failure shapes returned on error.
## Help
Every command supports `--help`:
```bash
cargo-ai storage model list --help
cargo-ai storage column create --help
cargo-ai storage relationship set --help
cargo-ai storage query execute --help
cargo-ai storage query download --help
```
Referenced files: 8
cargo-workspace-management11.2 KB
---
name: cargo-workspace-management
description: "Administer a Cargo workspace and talk back to the Cargo team — invite and manage members, mint and rotate API tokens, organize plays, tools, and agents into folders, inspect roles, upload batch input files, and file reports. Triggers: \"invite my teammate\", \"create an API token for CI\", \"who has access\", \"organize these into folders\", \"rotate that token\", \"upload this CSV for a batch\" — and for feedback: \"report this bug to Cargo\", \"send feedback to the Cargo team\", \"this CLI command is broken\", \"share this session with Cargo\", \"request a feature\". Most commands need a token with admin access. Skip when: the question is about credits, plans, or invoices — use cargo-billing."
version: "1.2.2"
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
---
# Cargo CLI — Workspace
Workspace administration: managing users, API tokens, folders, roles, workspace-level files, and submitting reports to workspace management.
> See `references/response-shapes.md` for full JSON response structures.
> See `references/troubleshooting.md` for common errors and how to fix them.
> See `references/examples/users.md` for user invite and management examples.
> See `references/examples/tokens.md` for API token creation and rotation examples.
> See `references/examples/folders.md` for organizing resources into folders.
> See `references/examples/reports.md` for examples of submitting workspace management reports.
> See `references/examples/sessions.md` for session tracking — the Cargo installer scaffolds the Claude Code SessionStart + Stop + SessionEnd hooks automatically.
## Bootstrap
Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
```bash
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`. **Admin-only:** user, role, and token writes require a token with admin access on the workspace. Folder writes and `report create` work with non-admin tokens. When the full skill bundle is installed, [`../cargo/references/prerequisites.md`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
## Discover resources first
```bash
cargo-ai whoami # current user and active workspace
cargo-ai workspaceManagement user list # all workspace members
cargo-ai workspaceManagement role list # available roles
cargo-ai workspaceManagement token list # all API tokens
cargo-ai workspaceManagement folder list # all folders
```
## Quick reference
```bash
cargo-ai whoami
cargo-ai workspaceManagement user list
cargo-ai workspaceManagement user create --user-email <email> --role-slug <slug>
cargo-ai workspaceManagement token list
cargo-ai workspaceManagement token create --name <name>
cargo-ai workspaceManagement token remove <token-uuid>
cargo-ai workspaceManagement folder list
cargo-ai workspaceManagement folder create --name <name> --emoji-slug <slug> --kind <kind>
cargo-ai workspaceManagement report create --title <title> --description <description>
cargo-ai workspaceManagement session upsert --session-id <id> --title <title> --summary <summary> [--finished]
```
## Current user and workspace
```bash
# Get your current user and workspace context
cargo-ai whoami
# → Returns your user UUID, email, and active workspace UUID
```
## Users
```bash
# List all workspace members
cargo-ai workspaceManagement user list
# Invite a new user (requires their email and a role)
cargo-ai workspaceManagement user create \
--user-email user@example.com \
--role-slug <role-slug>
# Update a user's role
cargo-ai workspaceManagement user update --user-uuid <uuid> --role-slug <new-role-slug>
# Remove a user from the workspace
cargo-ai workspaceManagement user remove --user-uuid <uuid>
```
## Roles
Roles define what users can do in the workspace.
```bash
# List available roles
cargo-ai workspaceManagement role list
```
Always check available roles before inviting users — use the `slug` from `role list` when creating or updating users.
## API tokens
Each token has a human-readable `name` and a `permissions` field. Tokens created via the CLI are issued with `permissions: null`, which means the token mirrors the permissions of its owning user (the user who ran `token create`) — so a token's effective access is bounded by what that user can do in the workspace. Fine-grained permission scoping (an explicit allow/deny list) is configured via the API or the Cargo app.
```bash
# List all API tokens (includes name and permissions of each token)
cargo-ai workspaceManagement token list
# Create a new token — --name is required
cargo-ai workspaceManagement token create --name "CI/CD pipeline"
# → Returns the token value — store it securely, it won't be shown again
# Remove a token
cargo-ai workspaceManagement token remove <token-uuid>
```
**Naming:** Pick a `--name` that makes the token's purpose obvious in `token list` later (e.g. `"GitHub Actions — production"`, `"Local dev — alice"`, `"Zapier integration"`). The name is the only way to tell tokens apart in the listing.
**Security:** Token values are only shown once at creation. Store them in a secrets manager (e.g. GitHub Secrets, AWS Secrets Manager).
## Folders
Folders organize resources (plays, tools, agents) in the Cargo app.
```bash
# List all folders
cargo-ai workspaceManagement folder list
# Create a folder (kind: "tool", "play", "agent", or "file")
cargo-ai workspaceManagement folder create --name "Q1 Campaigns" --emoji-slug "rocket" --kind "play"
# Get a folder
cargo-ai workspaceManagement folder get <folder-uuid>
# Update a folder
cargo-ai workspaceManagement folder update --uuid <folder-uuid> --name "Q1 2025 Campaigns"
# Remove a folder
cargo-ai workspaceManagement folder remove <folder-uuid>
```
## Reports
Submit a report to workspace management. **Use this whenever the CLI is failing, behaving unexpectedly, lacks a capability you need, or whenever you (user or agent) are struggling to accomplish a task with the CLI.** This is the official feedback channel — every report is reviewed by the Cargo team and used to improve the CLI, its skills, and the underlying APIs.
```bash
# Submit a report to workspace management
cargo-ai workspaceManagement report create \
--title "<short summary>" \
--description "<detailed description, including the command(s) tried and the error(s) seen>"
```
**When to send a report (non-exhaustive):**
- A command exits non-zero with an `errorMessage` you cannot resolve from `--help` or `references/troubleshooting.md`.
- The CLI is being misused or the syntax is unclear (e.g. you can't figure out which flag to pass, or the JSON schema for `--filter` / `--nodes` / `--action` is ambiguous).
- A user or AI agent is repeatedly retrying the same command without progress (≥ 2 failed attempts on the same task).
- A documented command does not behave as the skill describes, or a response shape differs from what `references/response-shapes.md` documents.
- A capability appears to be missing entirely (no command exists for what you need to do).
- An async operation never reaches a terminal status, or returns inconsistent results across runs.
**What to put in the report:**
- `--title`: one-line summary of the problem (e.g. `"batch create fails with 'playNotCompatible' on tool workflow"`).
- `--description`: include the exact command(s) executed (with sensitive values redacted), the JSON `errorMessage`, what you expected, what you tried, and any relevant UUIDs (run, batch, workflow, model). The more context you provide, the faster it can be triaged.
```bash
# Example: report a CLI struggle after multiple failed attempts
cargo-ai workspaceManagement report create \
--title "segment fetch returns empty results despite matching records in UI" \
--description "Ran: cargo-ai segmentation segment fetch --model-uuid <uuid> --filter '{\"conjunction\":\"and\",\"groups\":[...]}'. Got 0 records. The same filter shows 1,200 matches in the app UI. Tried both --filter and --segment-uuid; both return empty. Expected: the same records as the UI."
```
> Do not silently give up on a failing CLI task. **Send a report.** This closes the feedback loop so the CLI and these skills can be improved.
## Sessions
Record a Claude Code session in `workspace_management.sessions`. One row per `(workspaceUuid, sessionId)`. Used by the `cargo` router's Claude Code SessionStart + Stop + SessionEnd hook recipe — see [`../cargo/SKILL.md`](../cargo/SKILL.md) for when to wire them up.
```bash
# Upsert a session. Idempotent on --session-id within the workspace.
cargo-ai workspaceManagement session upsert \
--session-id <claude-session-id> \
--title "<short title>" \
--summary "<one-or-two sentence summary>"
# Same call, but also stamp finished_at = now
cargo-ai workspaceManagement session upsert \
--session-id <claude-session-id> \
--title "<final title>" \
--summary "<final summary>" \
--finished
```
- `--session-id`, `--title`, `--summary` are required on every call. `title` and `summary` are `NOT NULL` in the schema — pass placeholders on the start call and overwrite on the end call.
- `--finished` stamps `finished_at = now`. Use `--finished-at <iso>` for an explicit timestamp instead.
- Calling `upsert` twice with the same `--session-id` updates the same row — `title`, `summary`, and `finished_at` are overwritten.
Returns the upserted session as JSON. The [Cargo installer](https://github.com/getcargohq/cargo-skills#staying-current) wires SessionStart + Stop + SessionEnd hooks that call this command automatically: SessionStart writes a placeholder, the per-turn Stop hook checkpoints the row (no `--finished`), and SessionEnd writes the transcript-driven AI summary with `--finished` — see [`references/examples/sessions.md`](references/examples/sessions.md).
## Workspace files
Workspace files are CSVs or other data files uploaded for use in batch runs.
```bash
# Upload a file
cargo-ai workspaceManagement file upload --file <path-to-file>
# → Returns s3Filename
# Inspect a file's columns before running a batch
cargo-ai workspaceManagement file list-columns --s3-filename <s3-filename>
# → Returns column names to use when mapping to workflow inputs
```
The `s3-filename` is returned when uploading a file via `cargo-ai workspaceManagement file upload`. See the `cargo-orchestration` skill's `references/examples/tools.md` for the full file upload and batch run workflow.
## Help
Every command supports `--help`:
```bash
cargo-ai workspaceManagement user create --help
cargo-ai workspaceManagement token create --help
cargo-ai workspaceManagement folder create --help
```
Referenced files: 8
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package license
- MIT
- Package author
- getcargo
- Keywords
- gtm, go-to-market, sales, prospecting, lead-enrichment, b2b-data, crm, revops, data-enrichment, outbound
Declared capabilities
- Read
- Write
Package observed Sep 30, 2026.
Technical details
- First seen
- Sep 30, 2026 · 22:02 UTC
- Last seen
- Oct 1, 2026 · 12:00 UTC
- Collection status
- Collected
plugins_6a7d29277df08191a68f23401570b188
Download plugin data (JSON)