mcpField
C
cargo-storage

cargo-storage

github.com/getcargohq数据与数据库2110.2k 次安装2 天前更新
代码仓库

关于 cargo-storage

cargo-storage 是管理 Cargo 工作区数据层的命令行技能,面向维护结构化数据和模型的操作者。它支持模型、数据集、列、关系、记录与 SQL 查询,并提供统一配置和数据预览流程。

主要功能

  1. 01检查与管理模型和数据集
  2. 02创建并管理列与关系
  3. 03配置模型统一规则
  4. 04增删记录并执行 SQL
  5. 05预览抽取配置与数据

适用场景

  1. 01检查工作区模型结构
  2. 02为模型添加自定义列
  3. 03关联不同模型的数据
  4. 04查询或导出工作区记录

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/getcargohq/cargo-skills --skill cargo-storage

安装后在 Claude Code 中输入/cargo-storage确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

skill-metadata.json
references/
response-shapes.md
troubleshooting.md
references/examples/
columns.md
datasets.md
ingest-webhook.md
models.md
queries.md

详细介绍

Cargo CLI — 存储

数据层管理:检查和修改模型、数据集、列、关系、统一配置和记录,并对工作区存储运行 SQL 查询。

完整的 JSON 响应结构请参阅 references/response-shapes.md。 常见错误及其修复方法请参阅 references/troubleshooting.md。 模型 CRUD、DDL 检查和架构发现示例请参阅 references/examples/models.md。 数据集列表和导航示例请参阅 references/examples/datasets.md。 列创建和管理示例请参阅 references/examples/columns.md。 storage query execute / storage query download SQL 示例(WHERE、聚合、联接、分页、导出)请参阅 references/examples/queries.md。 webhook 接入(由 webhook 提供数据)的模型示例——推导 webhook URL 并 POST 记录——请参阅 references/examples/ingest-webhook.md。

初始化

如果已登录(cargo-ai whoami 返回一个工作区),请跳至下一节。

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

每条命令都会将 JSON 输出到 stdout;失败时以非零状态码退出,并返回 {"errorMessage": "..."}。任何会创建运行或批次的操作都是异步的——请传入 --wait-until-finished,或轮询对应的 get。安装完整技能包后,../cargo/references/prerequisites.md 会补充 CLI 版本固定、令牌作用域和仅限管理员使用的功能。

先发现资源

检查或修改前,务必先列出资源。

cargo-ai storage dataset list              # all datasets (uuid, slug)
cargo-ai storage model list                # all models (uuid, name, slug, columns, datasetUuid)
# `model list` takes no flags — filter its output instead:
cargo-ai storage model list | jq '[.models[] | select(.datasetUuid == "<uuid>")]' 

在 UI 中查看: 模型位于 app.getcargo.io/workspaces/<WORKSPACE_UUID>/models/<MODEL_UUID>。通过 cargo-ai whoami 中的 workspace.uuid 获取 <WORKSPACE_UUID>。

快速参考

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 record create-bulk --model-uuid <uuid> --records '[{"data":{...}}]'
cargo-ai storage model preview --dataset-uuid <uuid> --slug <extractor-slug> --config '{...}'
cargo-ai storage query execute "SELECT * FROM default.companies LIMIT 10"
cargo-ai storage query download --query "SELECT * FROM default.companies"

模型

模型是工作区中的结构化表格(例如 Companies、Contacts)。

# List all models
cargo-ai storage model list

# List models in a dataset — every model carries `datasetUuid`, and
# `model list` has no flags of its own, so filter client-side
cargo-ai storage model list | jq '[.models[] | select(.datasetUuid == "<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 (--position moves its node on the app's data canvas)
cargo-ai storage model update --uuid <model-uuid> --name "New Name"
cargo-ai storage model update --uuid <model-uuid> --position '{"x":0,"y":0}'

# Remove a model
cargo-ai storage model remove <model-uuid>

# Is a slug taken in this dataset? → {"exists": true|false}
cargo-ai storage model exists-by-slug --dataset-uuid <uuid> --slug contacts
创建模型前,对提取器配置进行试运行

model preview 和 model preview-count 会运行提取器配置,但不会创建任何内容。--slug 是提取器的 slug(不是模型 slug),--dataset-uuid 是连接器的数据集(kind: "connector")——该数据集指定了连接器。

# Sample rows + the extractor's total, for extractors that preview records
cargo-ai storage model preview \
  --dataset-uuid <connector-dataset-uuid> --slug <extractor-slug> --config '{...}'

# Count only, for extractors that preview a count
cargo-ai storage model preview-count \
  --dataset-uuid <connector-dataset-uuid> --slug <extractor-slug> --config '{...}'

每个提取器仅支持两种操作之一(集成中提取器的 preview: "records" 或 "count"),另一种操作会返回 count: 0,而不是报错——在两种操作都试过之前,0 并不表示“没有匹配项”。preview 会向提取器请求一个简短的试运行页面;对于计费连接器,该页面报告的内容会产生费用。提取器执行空的试运行抓取时(例如 Store Leads 的 fetchDomains)不会产生费用,其余提取器则按项计费。对计费提取器运行预览前,请先查看其操作指南。无效配置会返回 invalidConfig 及验证器提供的消息——这是在执行 model create 前调试配置的最省钱方式。

查询: 使用 cargo-ai storage query execute "<sql>"(或使用 storage query download --query "<sql>" 完整导出)对存储运行 SQL。表以 <datasetSlug>.<modelSlug> 的形式引用(例如 default.companies),底层会将其重写为对应的存储表。请参阅下文的使用 SQL 查询。

接入模型(由 webhook 推送数据)

提取器的 mode.kind === "ingest" 的模型——http.listenHook 及类似项——通过推送记录来填充 Cargo。模型设置页面会显示一个“Webhook URL”;没有 CLI 命令或 API 字段会返回它,但可以使用 CLI 已公开的值拼装出来:

<baseUrl>/v1/models/<model-uuid>/records/ingest?token=<api-token>
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"

不适用于工作流。 Cargo 工作流通过原生的 modelUpsert / modelInsert 操作写入模型(参见 cargo-orchestration → references/nodes.md → “Storage”)。调用此 URL 的 HTTP 节点会额外增加一个节点、一段负载脚本,以及粘贴到节点配置中的 API 令牌。此 webhook 供 Cargo 之外的系统使用。

先检查提取器的模式——当它报告 "autoIngest": true(calendly、smartlead、instantlyV2、heyReach、cargoSignals、explorium 的 listen 提取器)时,Cargo 会自行向提供方注册 webhook,因此不得将此 URL 提供给他人。完整流程、负载格式和限制请参阅 references/examples/ingest-webhook.md。

数据集

数据集是模型的逻辑分组。

# List all datasets
cargo-ai storage dataset list

# Get a single dataset
cargo-ai storage dataset get <dataset-uuid>

列

列定义模型的架构。

# 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

# Is a slug taken on this model? → {"exists": true|false}
cargo-ai storage column exists-by-slug --model-uuid <uuid> --column-slug <slug>

# Values a column holds ([{label, value}]) — what a filter on it can match
cargo-ai storage column autocomplete --model-uuid <uuid> \
  --column '{"slug":"industry","type":"string","label":"Industry","kind":"custom"}'

# Write custom-column values onto existing records (custom column slugs only;
# a model's own extracted fields are refused)
cargo-ai storage column insert-custom-values --model-uuid <uuid> --id <record-id> --data '{"ai_fit_score":82}'
cargo-ai storage column insert-custom-values-bulk --model-uuid <uuid> \
  --records '[{"id":"rec_1","data":{"ai_fit_score":82}},{"id":"rec_2","data":{"ai_fit_score":40}}]'

insert-custom-values 用于将 Cargo 外部计算的值(例如自有流水线生成的评分、手动添加的标签)写入由连接器同步的模型:同步负责提取字段,自定义列则由你掌控。请先创建列。

列类型:string、number、boolean、date、object、array、vector、any。

列种类:custom(用户定义)、computed(基于其他列的表达式)、metric(从相关模型聚合而来)、lookup(通过联接从相关模型中提取的单个字段)。

预览构建结果

列列表无法让用户判断模型是否正确——行可以。两个检查点(整个技能包的约定见 ../cargo/references/interaction.md §4):

1. 执行 model create / column create 后立即检查——展示架构,而非行。 新模型是空的;此时执行 LIMIT 10 会返回空结果,看起来像是失败。请改为用简洁的表格列出各列(列名、类型、填充方式)。

2. 数据写入后立即检查——展示行。 批次、play 或导入将数据写入模型后,预览模型:

cargo-ai storage query execute \
  "SELECT * FROM <dataset-slug>.<model-slug> LIMIT 10"

展示约 10 行,并且只显示有意义的列。存储查询免费,因此只需增加几行输出,不会产生任何成本——而且这是用户首次真正看到自己构建的内容。当 play 填充了新列时,请将该列与记录的标识字段(name、domain)一同预览,让已填充和未填充的状态一目了然。

如果预览结果为空或全为 null,但本不应如此,这就是一个发现——请明确指出,而不是将写入报告为成功。请参阅 cargo-diagnostics 追查原因。

关系

关系用于将模型关联起来(例如,联系人属于公司)。关系通过 CLI 创建,而不仅仅是通过 UI 创建。

relationship list 不接受任何标志 — 它会返回工作区中的所有关系。请在客户端按 fromModelUuid / toModelUuid 筛选。

cargo-ai storage relationship list

relationship set 会替换数据集的整个关系集合。 它需要指定一个数据集,以及该数据集中应存在的完整关系列表:带有 uuid 的条目会被更新,不带 uuid 的条目会被创建,任何 uuid 未出现在负载中的现有关系都会被删除。向包含五个关系的数据集发送一个关系,会导致另外四个被移除。请始终先执行 list,再将包含新增关系的完整数组发送回去:

cargo-ai storage relationship set \
  --dataset-uuid <dataset-uuid> \
  --relationships '[
    {"uuid":"<existing-uuid>","fromModelUuid":"<contacts-uuid>","fromColumnSlug":"account_id","fromPropertySlug":null,"toModelUuid":"<companies-uuid>","toColumnSlug":"id","toPropertySlug":null,"fromSelectedColumnSlugs":null,"toSelectedColumnSlugs":null,"relation":"manyToOne"},
    {"fromModelUuid":"<deals-uuid>","fromColumnSlug":"company_id","fromPropertySlug":null,"toModelUuid":"<companies-uuid>","toColumnSlug":"id","toPropertySlug":null,"fromSelectedColumnSlugs":null,"toSelectedColumnSlugs":null,"relation":"manyToOne"}
  ]'

每个条目都必须包含 fromPropertySlug、toPropertySlug、fromSelectedColumnSlugs 和 toSelectedColumnSlugs(未使用时传入 null);缺少其中任何一项都会导致验证失败并返回 errorMessage。复制 relationship list 返回的条目即可保留这些字段。

relation 的值为 oneToOne、manyToOne 或 oneToMany。两个模型都必须位于你指定的数据集中 — 关系不会跨数据集,因此响应中的 fromDatasetUuid 和 toDatasetUuid 始终等于 --dataset-uuid。

失败原因:datasetNotFound;invalidRelationships(无法解析列 slug 或模型 UUID,或存在重复项 — 包括同一对关系以反向形式重复声明);modelNotCompatible(见下文)。

Unify 模型不允许手动创建关系。 在原生数据集中,unify 模型的关系会在同步期间生成,因此将其指定为 fromModelUuid 或 toModelUuid 会返回 modelNotCompatible。上述替换操作也会排除这些自动生成的行,因此 set 调用无法删除它们。

统一

统一用于将来自多个源模型的记录合并为一个规范的账户或联系人 — 并且可以通过 CLI 配置,使用 model update 上的 --unification。传入 null 可清除配置。

# 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>"}
}'
字段适用对象含义
source两者integration(由连接器定义)或 custom
typecustomaccount、contact、accountEvent、contactEvent
uniqueColumnscustom匹配键 — 每列使用 {slug, reference}。此字段决定哪些行属于同一实体
selectedColumnSlugscustom纳入统一模型的列。省略则包含全部列
timeColumnSlugcustom事件时间戳 — 适用于两种 *Event 类型
parentcustom将联系人或事件关联到其账户:{"kind":"model","columnSlug":…,"parentModelUuid":…} 或 {"kind":"reference","columnSlug":…,"reference":…}
filtercustom用于限制统一行范围的分段筛选器 — 结构与分段的 conjonction 相同

写入配置不会触发重新计算。 统一后的行会在模型同步运行时重建,因此更新后请启动一次运行并轮询其状态:

cargo-ai storage run create --model-uuid <model-uuid>
cargo-ai storage run list --model-uuid <model-uuid>

如果上次成功同步在提取器的最小间隔内,run create 会以 upToDate 拒绝请求;如果已有同步正在进行,则会以 alreadyRunning 拒绝请求。两个标志可覆盖这些限制:

  • --is-force true — 取消正在进行的同步(最多等待 60 s 使其停止),并在不考虑数据新鲜度的情况下启动新同步。
  • --is-reset true — 清除提取器的增量游标,并从源重新构建模型,就像首次同步一样。对于按项目计费的提取器,这会对整个结果集重新计费,因此运行前请先估算费用。

通过 storage model get <uuid> → unification 获取当前配置(模型未启用统一时为 null)。运行完成后,请使用 storage query execute 检查行数,再将变更视为完成 — uniqueColumns 过窄会导致合并不足,过宽则会将不同实体合并,两种情况看起来都像是运行成功。

记录

# List records in a model (sortable on _id, _title, or _emitted_at — the last
# only on models built from ingested records)
cargo-ai storage record list --model-uuid <uuid>
cargo-ai storage record list --model-uuid <uuid> --limit 100 --sort-column-slug _emitted_at --sort-kind desc
cargo-ai storage record get --model-uuid <uuid> --id <record-id>

# Write records — one at a time, or up to 1,000 per bulk call
cargo-ai storage record create --model-uuid <uuid> --data '{"name":"Ada","email":"[email protected]"}'
cargo-ai storage record update --model-uuid <uuid> --id <record-id> --data '{"status":"done"}'
cargo-ai storage record remove --model-uuid <uuid> --id <record-id>
cargo-ai storage record create-bulk --model-uuid <uuid> --records '[{"data":{"name":"Ada"}},{"data":{"name":"Lin"}}]'
cargo-ai storage record update-bulk --model-uuid <uuid> --records '[{"id":"rec_1","data":{"status":"done"}}]'
cargo-ai storage record remove-bulk --model-uuid <uuid> --ids '["rec_1","rec_2"]'

记录写入仅适用于原生模型和摄取模型。对于摄取模型,写入会经过提取器,采用与 webhook POST 相同的路径,因此会扣除每项记录的额度,且负载验证可能会拒绝整个批次(invalidRecords)。获取模式模型(由连接器同步的模型)会以 integrationNotCompatible 拒绝写入:其中的行属于同步数据。要为同步行添加注释,请改用 column insert-custom-values。在工作流中,请使用原生的 modelUpsert / modelInsert 操作写入,而不要调用 shell 命令。

对于高级记录查询(筛选、排序、分页),请使用 cargo-segmentation 技能中的 segmentation segment fetch。

使用 SQL 查询

使用 storage query execute 对工作区存储运行 SQL。表名以 <datasetSlug>.<modelSlug> 的形式引用(例如 default.companies),后台会将其重写为底层存储表名,因此无需查询 DDL 来获取表名。

cargo-ai storage query execute \
  "SELECT name, domain FROM default.companies LIMIT 10"
# → { "isRefreshing": false, "rows": [...] } on success; non-zero exit with { "errorMessage": "..." } on error

如需完整导出,请使用 storage query download,它会返回指向 CSV(默认格式)或 Parquet 文件的签名 URL(urls,一个数组):

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

使用 storage column list --model-uuid <uuid> 获取列名(存储名称:新增的列带有 custom__ / computed__ / metric__ / lookup__ 前缀);也可以运行 storage model get-ddl <model-uuid> 获取完整架构和 SQL 方言。对于较大的结果集,请直接在 SQL 中使用 LIMIT / OFFSET 分页。

请参阅 references/examples/queries.md,了解 WHERE 子句、聚合、联接、日期查询、分页,以及发生错误时返回的失败格式。

帮助

每条命令都支持 --help:

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

评论

支持 Markdown