Build a total addressable market list of companies filtered by industry, headcount, and geography, powered by Cargo. Triggers: "build a TAM list", "how many companies match our ICP", "list every SaaS company in Europe under 200 employees", "size our addressable market", "find target accounts", "list building", "build a list of companies". Providers: salesNavigator. Skip when: you want the people at those companies — use find-b2b-leads or find-stakeholders; or you want companies by tech stack — use find-companies-using-tech.
Coding
tam-building
Try itStand up your account universe as a deployed pipeline: an AI Ark company search shaped by your ICP, sized for free before it bills, then tiered A / B / C / disqualified by an agent that reads your rubric from the workspace context and web-searches the evidence the sourced row does not carry. Triggers: "our TAM is a stale CSV", "build our account universe", "source companies matching our ICP and rank them", "keep our market list current", "which of these companies are actually worth a rep", "tier the market we just sourced". Cargo CDK, aiArk, countCompanies, fetchCompanies, agent tiering, workspace context, webSearch. Skip when: you want the list once rather than a pipeline that keeps producing it, which is build-tam-list; or the accounts already exist in a CRM or an accounts model and only need judging, which is account-scoring.
What it does
Stand up your account universe as a deployed pipeline: an AI Ark company search shaped by your ICP, sized for free before it bills, then tiered A / B / C / disqualified by an agent that reads your rubric from the workspace context and web-searches the evidence the sourced row does not carry. Triggers: "our TAM is a stale CSV", "build our account universe", "source companies matching our ICP and rank them", "keep our market list current", "which of these companies are actually worth a rep", "tier the market we just sourced". Cargo CDK, aiArk, countCompanies, fetchCompanies, agent tiering, workspace context, webSearch. Skip when: you want the list once rather than a pipeline that keeps producing it, which is build-tam-list; or the accounts already exist in a CRM or an accounts model and only need judging, which is account-scoring.
The skill document
Tam building
State: to-be-approved. Deploy-verified against a live workspace: not yet. Treat Done when
below as the acceptance test and review cargo-ai cdk plan before deploying. Make no outcome claim
for this skill until it is approved.
The outcome
Your account universe, built from the Sales Navigator search that describes your whole market,
even when that search returns far more than the extractor will hand over. Counted before it is
extracted, split into sub-searches that each sit under the cap, resolved to real domains, and
merged into the shared accounts model deduped.
The count is a design-time CLI call, not a deployed resource:
cargo-ai orchestration action execute --wait-until-finished \
--action '{"kind":"connector","integrationSlug":"salesNavigator","actionSlug":"searchCompanyMetrics","config":{}}' \
--data '{"url":""}'
It returns total_results and costs a fraction of a credit. Splitting order that usually works:
industry first (descend the LinkedIn taxonomy only where a segment is still oversized), then
geography, then headcount band. Recount every sub-search; split any that is still over.
Put it in your project
This folder is a worked example: real CDK resources written for some other company. The job
is to end up with the code your company would have written, in your project, and an agent does the
adapting. If the cargo-cdk skill is in your session it carries the long form of this; if not,
this is enough.
- Look first.
grep -l '@cargo-ai/cdk' package.jsonsays whether a CDK project already lives here;ls */models/*.ts */connectors/*.tssays what it already declares. If there is no project:cargo-ai cdk init --template blank && cd && npm install. That is the whole shell; this folder never ships one. - Copy this folder in as a sibling of what is there, then reconcile: for every model or
connector this example carries that the project already has (an accounts model keyed on
website, a HubSpot connector, an OpenAI connector), rewire the imports to the existing one and
drop the copy. Two resources with one slug is a collision at deploy. Append this folder's
.envneeds to the project's.env.example; never overwrite it. - Adapt. Work the sections below in order: What should not change is what you argue back
about (say what breaks, then do it if they still want it); What you can change is what you
offer unprompted (nobody asks for a variant they do not know exists); What you will be asked
is the floor, and you derive before you ask. If you are asking more than about four questions
you have skipped lookups. Record what you changed and why under a
## Decisionssection in your copy of this file. - Plan, then stop.
npm run typecheck && cargo-ai cdk plan. Show the diff. Deploy only on an explicit yes:cargo-ai cdk deploy. Nevercdk init --forceinto a non-empty directory. - Verify. Walk Done when line by line and report each with evidence. Deployed cleanly and produced nothing is the normal failure.
What you will be asked
Derive before you ask. An input with a lookup is looked up, not asked. Only the ones marked asked genuinely live in the operator's head.
| Input | Kind | How it is answered | Why it matters |
|---|---|---|---|
marketSearch | manual | checked, not written: Paste the Sales Navigator company search that describes your whole market, however oversized it is | This is the only input that cannot be derived: it encodes who you sell to. Everything else in this skill is arithmetic on top of it. |
searchUrls (models/salesnav-companies.ts) | value | derived: cargo-ai orchestration action execute --action salesNavigator.searchCompanyMetrics --data '{"url":""}' returns total_results. Over the cap, split by facet (industry first, descending the LinkedIn taxonomy only where still oversized, then geography, then headcount band) and recount each sub-search until every one is under the cap. | A search holding 4,000 companies extracts 1,000 and tells you nothing about the missing 3,000. Splitting under the cap is the entire point of this skill. |
limit (models/salesnav-companies.ts) | value | defaults to 1000; ask only to change it | This is the upstream cost control. Promotion is 1:1 with extraction, so what you extract is what you pay to enrich. |
Checked before moving on, not after the deploy:
marketSearch: the URL is a linkedin.com/sales/search/company URLsearchUrls: every sub-search count is strictly below config.limit; a count equal to the cap means it is still truncated and must be split againlimit: at or below 1000
What you can change
The code is a worked example. These reshapes are expected, and the agent offers them rather than waiting to be asked. Every one costs something; that is what makes it a variation and not the default.
| Variation | When it is right | How | What it costs |
|---|---|---|---|
non-linkedin-source | You do not want to source from LinkedIn at all, or Sales Nav does not cover your market | Swap the Sales Nav connector and landing model for the Ark enrichment API (https://ai-ark.com/platform/enrichment-api), keeping promote-to-accounts and the accounts contract unchanged (models/salesnav-companies.ts, connectors/sales-navigator.ts) | You lose the Sales Nav facet taxonomy that makes the split tactic mechanical, and the splitting has to be redesigned around the new source's own limits |
land-without-promoting | You want to see and filter the raw market before paying to enrich it | Deploy the landing model only and leave promote-to-accounts out until you have decided which rows are worth promoting (plays/promote-to-accounts.ts) | Nothing reaches accounts, so no downstream skill (scoring, contact sourcing, signals) has anything to work with until you promote |
sample-first | The market search is large and you want to see the cost curve before committing | Set config.limit well below the cap and start with one sub-search URL, then widen once rows land correctly (models/salesnav-companies.ts) | Your TAM is deliberately incomplete until you widen it, so do not score or report on coverage from a sample |
What should not change
However far you adapt, these hold. Ask for one anyway and the agent tells you what breaks, then does
it if you still want it, and records why under ## Decisions in your copy of this file.
- Every company is resolved to a real domain before it is promoted into
accounts. (plays/promote-to-accounts.ts) The sharedaccountsmodel keys onwebsite. A domainless account cannot be deduped, so it forks into duplicates the first time the same company appears in another list. This is why a row that cannot be resolved is dropped rather than written. - Every search is counted before it is extracted. (
models/salesnav-companies.ts) Extracting blind is how you take a silently truncated list: the search holds 4,000 companies, the extractor takes 1,000, and nothing tells you the rest exist. - No sub-search sits at or above the extraction cap. (
models/salesnav-companies.ts) A search returning exactly the cap is truncated. That is the failure this whole skill exists to prevent, and it is invisible unless you check the number.
Done when
- the sub-search extractions sum to roughly the count of the original whole-market search
- no sub-search returned exactly the cap, which would mean it is still truncated
- promoted accounts appear in
accountswith a website, deduped across overlapping sub-searches
What it costs
Counting is a fraction of a credit and is the cheapest insurance here. Promotion is the
expensive step: every promoted company costs two credited calls (matchBusiness +
enrichBusinessFirmographics), because Sales Nav returns no domain and both are needed to resolve
one. A 5,000-company TAM is roughly 10,000 enrichment calls. That is the price of the outcome, not
waste, but it is real money and it should be spent on purpose.
The control is upstream, where the rows are created: config.limit and how many sub-search URLs
you add. To spend less, extract less. Start with one small sub-search, watch it land correctly,
then widen.
Composes into
list-building (the same split tactic for people), contact-sourcing (the buyers at every account
you just built), account-scoring, signal-based-tam (watch the universe you just built).
Related skills
Score a list of companies against your ideal customer profile and rank them, powered by Cargo — every row gets a number, the reason behind it, and a tier, so the bottom of the list can be dropped before anyone spends time on it. Triggers: "score these leads", "which of these fit our ICP", "rank this list", "prioritise these accounts", "who should we go after first", "disqualify the bad ones", "tier this list". Firmographic fit, thresholds, tiering, prioritisation. Skip when: you have no list yet and need one built — use build-tam-list or find-b2b-leads; or you want people inside an account rather than a verdict on the account — use find-stakeholders.
Find the buying committee at a target account — every stakeholder matching a set of titles, seniorities, and departments, powered by Cargo. Triggers: "find the buying committee at Acme", "who are the decision makers at this company", "find stakeholders", "multi-thread this account", "who else should I be talking to at this account". Providers: aiArk. Skip when: you are sourcing across many companies rather than going deep on a few — use find-b2b-leads.
Give your agent a real email address, calendar, documents, spreadsheets, file storage, and web search via Tamaton's MCP endpoint. Self-register with no human...
Build a structured account plan for any key customer or target account. Use when asked to create an account plan, key account strategy, strategic account rev...
Keep every account scored and tiered against your written ICP by a deployed agent that re-scores as accounts arrive and as the ICP changes, writing the rationale back to the CRM. Triggers: "keep our accounts scored as they arrive", "re-score everything when the ICP changes", "which accounts should the team work first", "our scoring is a spreadsheet nobody trusts", "why is this account tier A", "stand up account tiering". Cargo CDK, defineAgent, cargo_score, cargo_tier, HubSpot, Salesforce, Attio. Skip when: someone hands you a list and wants it qualified once, which is cargo-gtm's job, not a deployed scorer's.