SuperAPI AI Directory

create-gtm-skill

Deployment & operations

View repository

Updated 10-15 21:51

About this skill

Create a GTM skill

This is an authoring skill for people writing this repo. It is not a customer skill and does not install with npx skills add. The canonical copy lives in .agents/skills so Codex, Claude Code, and Cursor all load the same file (the last two via symlink).

Read CONTRIBUTING.md first. That file is the contract the validators enforce; this file is the procedure.

One folder at the repo root is one customer skill. Install path: npx skills add getcargohq/gtm-skills/<name>.

1. Pick the kind

Kind Frontmatter Job
one-off metadata.source: one-off Runs once in a turn: exact cargo-ai command and a price
pipeline metadata.source: cookbook Deploys a standing play. Customer copy says pipeline, never "cookbook"

metadata.source must be exactly one of those two strings. The validator uses cookbook as the internal discriminator. Do not put that word in README, plugin listings, skill body, or examples. Customers learn: some skills run once; some deploy a pipeline that keeps running.

If the same job exists both ways, they compete for prompts. Pin the seam in evals/routing.jsonl: one case that must hit the pipeline, one that must hit the one-off sibling.

Name the folder after the job, not the vendor. name in frontmatter equals the folder name. The slug is what an agent matches before it opens the file, so the kind has to be readable from the name:

Kind Shape Examples
one-off verb + object enrich-company-data, score-leads, build-tam-list
pipeline the standing practice tam-building, account-scoring, crm-enrichment
migration x-to-cargo clay-to-cargo

A verb says "do this once." A standing noun says "keep this running." That is how build-tam-list and tam-building stay apart, and why score-leads pairs with account-scoring rather than score-accounts. Do not give both kinds the same stem.

enrich-crm would read as a one-off next to enrich-company-data. A pipeline that keeps CRM records filled is crm-enrichment. Contacts later stay in that same slug. Accounts that are not in a CRM, if they land, are account-enrichment. Planned pipelines stay nouns (contact-sourcing, signal-based-tam, rep-cockpit). Do not rename existing skills to force -ing vs -ment; the kind matters more than the suffix.

Inside a cookbook, resource slugs are snake_case: plays, workflows, tools, agents, segments and folders (score_accounts, enrich_crm_contact, account_enrichment, tam_tier_analyst, tam_tier_a, crm_enrichment_plays), the same as the connectors and models the CDK already requires it of. Workers and apps are the exception: the CDK requires kebab-case for them. File names stay kebab-case (score-accounts.ts). A slug is the resource's identity in cargo.state.json, so renaming one after a deploy creates a new resource and orphans the old one: get it right before the first deploy.

A model that extracts a system you hold (a CRM, a warehouse) pulls all the data. Never filter or pick columns in its config: extract every record and every column, and narrow in the SQL or the play filter that reads it. A filter in the config is a second place the question is asked, invisible to anyone reading the queries, and changing it means a redeploy and a re-extraction instead of an edited query. A paid search source is the exception, because there the search is the data source rather than a filter on it: aiArk.fetchCompanies or a Sales Navigator search bills per returned record, so its query in config is what decides what you buy.

Native models first. A worked example runs on Cargo native models, not a CRM connector, so it deploys on a bare workspace. When the outcome needs accounts, contacts, opportunities or activity, declare the shared gtm_* models exactly as references/native-models.md defines them; scripts/check-native-models.mjs fails on drift. The CRM is the crm-backed variation.

2. Description (the only text before load)

Four parts, in order:

  1. The job in one sentence
  2. Triggers: literal quoted phrases a user would type
  3. Proper nouns (connectors, CRM, CDK)
  4. Skip when: the sibling skill that should win instead

Quote any YAML value that contains colon-space. Unquoted, the installer skips the file with a warning nobody reads.

3. Write the kind

One-off

Copy the structure of enrich-company-data/SKILL.md:

  • Setup (CLI install, login, session stamp)
  • Do the job (exact cargo-ai orchestration action execute / execute-batch)
  • Example (see below)
  • What it costs (table of integration.action → credits)
  • Worth knowing / Going further / star ask

Slugs and prices are not yours to invent. validate.ts asserts every integrationSlug/actionSlug and every credit number against getcargohq/cargo-skills playbooks. Copy from a sibling, then run node scripts/validate.ts.

Register: skills.sh.json, hooks/skill-loads.sh, root README.md table.

Pipeline

Copy the section order from tam-building/SKILL.md. The validator requires these headings:

  1. Honest banner: **State: to-be-approved.**
  2. ## The outcome
  3. ## Example (see below)
  4. ## Put it in your project (copy the procedure from tam-building; each skill carries its own)
  5. ## What you will be asked — derive before ask; more than ~4 asked rows means you skipped lookups
  6. ## What you can change — offer unprompted; every variation has a cost
  7. ## What should not change — name the concrete symptom if violated
  8. ## Done when
  9. ## What it costs
  10. ## Composes into

Folder:

<name>/
  SKILL.md
  README.md
  infra/           # or models/, plays/, agents/ — whatever the outcome needs
  references/      # supporting agent docs; never a nested SKILL.md
  evals/acceptance.md

Isolation: every model and connector the resources import lives in this folder. No relative import may leave it. Two pipeline skills may both carry an accounts model; the placing agent rewires to the project's existing one.

Resources must earn their deploy:

  • Do not wrap a single connector action in a tool. That is a one-off.
  • Do not declare a segment that restates the play's own filter.
  • Do not add examples/example.md until a live install has sanitized audit findings, mappings, a plan summary, and lookup-backed credits.
  • A folder of CDK with no SKILL.md does not belong at the root. Older examples live in history: git checkout 305cd88 -- <name>, then write the skill.

Credits. Pipeline markdown must not contain a numeric credit amount. Fetch live prices at run time (cargo-ai connection integration get <slug>). One-offs quote playbook numbers; pipelines do not.

Write the system you write back to. If the outcome updates a CRM record, the play runs on that CRM extract and matches the CRM record id. Do not sit a native unifyAccounts / ids map between the play and the write — the run looks successful and nothing lands.

One shape in the file. A new pipeline's checked example runs on the shared gtm_* native models (references/native-models.md); its crm-backed variation names the HubSpot swap, and Salesforce and Attio adapt that (connector, extractor, record-id, write action, fill-blank guard). A pipeline whose whole job is a CRM (crm-enrichment, crm-deduplication) keeps HubSpot as its checked example. No parallel branches.

CDK workflow bodies must compile. These fail cargo-cdk check / plan: undefined/void, comma / SequenceExpression, Date#getTime().

Register: skills.sh.json (its stage, at its place in the order: the order is what an agent suggests next), hooks/skill-loads.sh, root README pipeline table, .github/data/approvals.json with state: to-be-approved and empty evidence.

Both kinds: personas and the example

validate.ts requires these of every skill; the site renders them before anyone installs.

  • metadata.personas, right after metadata.source: 1–3 of sales-development, account-executive, revops, sales-leadership, marketing, gtm-engineering, primary first.

  • ## Example, in exactly this shape:

    ## Example
    
    > Find work emails for the 40 people in webinar-attendees.csv.
    
    Illustrative output, fictional records:
    
    <table or fenced block, about 20 lines at most>
    
    <one closing line with the result in numbers>
    

    Fictional companies on the .example TLD. A one-off's credits must add up from its own cost table; a pipeline quotes none and shows what the deployed play writes. Never a command in it, and never a table row that opens on a backticked integration.action cell — the validator reads that as a price.

4. Finish

node scripts/build-catalog.mjs
node scripts/generate-llms-txt.ts
npm run typecheck
npm run validate
npm run format:check

catalog.json and llms.txt are generated. Edit SKILL.md, then regenerate.

Do not claim an outcome for a pipeline skill until it is approved (demo workspace + two implementations in approvals.json). The banner in SKILL.md must match that file exactly.

Anti-patterns

  • A new root skill that is the same job as an existing slug with extra words (crm-account-enrichment vs crm-enrichment)
  • A pipeline named like a one-off (enrich-crm, score-accounts, build-tam) or a one-off named like a pipeline (tam-building for a list today)
  • Customer-facing "cookbook"
  • Hardcoded credits in a pipeline
  • Stub walkthroughs that restate SKILL.md
  • PLACEHOLDER values that survive into a "done" template when the checked example can use real HubSpot (or whatever) property names
  • Asking the operator for anything a connector or live schema can answer