Office hours: Build your self-driving GTM engine·Oct 29, 9:00am PT, onlineRegister→
Cargo
  • ProductAgentsReduce manual effort and close more deals with AIPlaysAutomate every stage of lead management so you can move fasterToolsAutomate repetitive tasks so your team can focus on what drives impactData ModelsUnify, organize, and activate your revenue dataAppsCustom interfaces for your team, wired to your live GTMTerritoriesModel your team, territories, and capacity in one placeContextOne shared knowledge base for your team and agents
    Add-onsChrome ExtensionSell faster, right in your browserButtonTrigger AI agents inside your CRMFormTurn any tool into an embeddable formSlackTag Cargo in Slack. It does the GTM work
    MoreProjectsDefine your entire GTM in codeCLIUse Cargo from your terminalMCPUse Cargo from Claude and ChatGPTDeveloper resourcesCargo API docs, OpenAPI spec, auth docs, webhooks, MCP serverAPI ReferenceExplore the Cargo APIDocumentationLearn how to use CargoIntegrationsConnected to your entire GTM stack
  • VeriffHow Veriff replaced MuleSoft with Cargo under NetSuite, Stripe and SalesforceAugmentHow Augment Code routes developer sign-ups to reps in under an hourWeights & BiasesHow Weights & Biases ships a new purchase signal in 2 days on CargoSee all
  • Pricing
  • Cookbooks
  • Blog
Sign in
Blog

Test a Go-to-Market Change Before It Reaches Production

3 Nov6min read
AurelienAurelien

To test a go-to-market change before it reaches production on Cargo, ship the play switched off (isEnabled: false) and declare a pilot with defineBatch that runs it on 50 records. The pull request previews the pilot’s sends and credits, the merge runs it once, and a second pull request turns the play on after you have read the results. Before that, cargo-ai project check catches errors offline and cargo-ai orchestration action execute --dry-run shows an action’s sample output and price without calling the provider.

Software teams test code before it ships because a bug in production costs more than one caught on a branch. In go-to-market the cost is concrete: a scoring bug routes every inbound lead to the wrong rep, and an enrichment step on the wrong field spends credits on every contact. The steps below go from cheapest to closest to production.

1. Check the project compiles, offline #

shellscript
cargo-ai project check

check validates the whole resource tree in one pass and reports every error it finds: an unknown reference, a bad slug, a cycle in the graph. It needs no state and makes no API calls, so it runs in an editor, in a pre-commit hook or in CI, and works before you sign in. On a connected repository, the Cargo check on the pull request fails on the same errors.

2. Dry run an action before you wire it in #

When a change adds a step, try the action on its own first:

shellscript
cargo-ai orchestration action execute \
  --action '{"kind":"connector","integrationSlug":"aiArk","actionSlug":"enrichCompany"}' \
  --data '{"domain":"example.com"}' \
  --dry-run

--dry-run checks your --data against the action’s inputs and prints a sample result in the shape of a finished run, with its credit price. No provider is called and no credits are used, so you can see which fields come back and what each record will cost before the step goes into a workflow. It covers connector and native actions. A tool or an agent runs your own workflow, so only a real run shows its output. Try Cargo without an account lists what else works signed out.

3. Read the plan on the pull request #

Open the pull request and read the comment Cargo posts. The resource table shows which plays, tools and agents change. The “On merge” table above it counts the records each play and execution runs on, and what it can send and spend. If the totals cross the approval limits, the check waits for the cargo:approve-impact label. Preview what a change will send explains the counts, and require approval before a high-impact change goes live covers the gate.

4. Ship the play switched off, then pilot it on 50 records #

This is the step that tests the change on real data. Take a new version of the play that enriches, scores and routes every new HubSpot contact. Deploy it switched off:

typescript
// infra/plays/inbound.ts
import { definePlay } from "@cargo-ai/cdk";

import { contacts } from "../models/contacts";
import { enrichScoreAndRoute } from "../workflows/enrichScoreAndRoute";

export const inbound = definePlay("inbound", {
  model: contacts,
  changeKinds: ["added"],
  schedule: { type: "realtime" },
  workflow: enrichScoreAndRoute,
  isEnabled: false, // deployed, but runs on nothing yet
});

Cargo creates plays switched off, and isEnabled: false holds the switch to what the code says on every deploy that touches the play. In the same pull request, declare a pilot that runs the play on a bounded slice:

typescript
// outputs/2026-11-03-inbound-pilot/pilot.ts
import { defineBatch } from "@cargo-ai/cdk";

import { contacts } from "../../infra/models/contacts";
import { inbound } from "../../infra/plays/inbound";

export const pilot = defineBatch("2026-11-03-inbound-pilot", {
  workflow: inbound,
  data: {
    kind: "filter",
    model: contacts,
    filter: {
      conjonction: "and",
      groups: [
        /* contacts created this week, say */
      ],
    },
    limit: 50,
  },
});

The plan lists the pilot under “Will execute once”, and the “On merge” table gives it its own row with its records, sends and credits. A play that stays off has no row, so the table describes exactly what the merge will do: 50 records through the new workflow. The merge runs the pilot once, and a ledger in the deploy state makes sure no later deploy runs it again.

Read the 50 runs in Cargo: the scores, the owners each contact was routed to, the fields written back to HubSpot. If something is wrong, fix the workflow and add a pilot with a new id, since an id that has run never runs again. When the results look right, open a second pull request that sets isEnabled: true.

For a change that sends, pick the pilot’s records with care. A pilot that emails 50 real contacts has emailed them, and a revert does not recall it. Use kind: "recordIds" with records you own, such as your team’s own test contacts, when the step sends.

5. Evaluate agent prompts on every pull request #

An agent’s system prompt is a string in a defineAgent file, so a pull request can change it and a pilot will not catch every regression. The project scaffold ships an evals/ folder with a promptfoo configuration: run it on every pull request that touches an agent. Evaluate an agent before production shows the setup.

6. Use a second workspace as staging, for changes you cannot pilot #

Some changes cannot be tried on 50 records: a new data model, a new connector, a rework of several plays at once. For those, deploy the same code to a second Cargo workspace first. Cargo supports staging and production as two workspaces, each with its own deploy state:

  • Same code, different credentials. Write connector credentials with workspaceEnv("HUBSPOT_TOKEN") and store a value under that key in each workspace, so the staging workspace talks to a test CRM account and production to the real one.
  • Select the workspace with CARGO_WORKSPACE_UUID (or by logging in to it) before you plan and deploy.
  • Give staging its own state. A deploy refuses to run against a state that belongs to another workspace, so keep a separate checkout for staging and create its state there with cargo-ai project state create --force. The checkout starts out pointing at production’s state, and --force gives it its own; keep that pointer out of the commits you push.

A connected repository directory deploys to one state, so the production workspace keeps the deploy-on-merge connection and the staging workspace is deployed by hand or from your own CI with cargo-ai project plan and cargo-ai project deploy --yes. In staging, cargo-ai project deploy --draft stages plays, tools, agents, apps and workers as unpublished drafts and leaves their live configuration alone; running deploy again promotes them. The details are in Secrets and environments in the Cargo docs.

When a test misses something #

No test sees everything. When a bad change reaches production anyway, stop the play with isEnabled: false in a small pull request, then revert the change: roll back a go-to-market change covers both. The whole pipeline, from plan to rollback, is in CI/CD for go-to-market.

FAQ #

Deploy the play with isEnabled set to false, and in the same pull request declare a defineBatch on that play with a filter and a limit, such as 50 records. The merge runs the batch once. After reading the results, a second pull request sets isEnabled to true.

Yes. cargo-ai orchestration action execute with —dry-run prints a sample result in the shape of a finished run and the action’s credit price, with no provider called and no credits used. It works for connector and native actions, and without an account.

Yes, as two workspaces, each with its own deploy state. The same project code deploys to both, with credentials held per workspace through workspaceEnv() and the target selected with CARGO_WORKSPACE_UUID.

AurelienAurelienNov 3, 2026
On this page
  • 1. Check the project compiles, offline
  • 2. Dry run an action before you wire it in
  • 3. Read the plan on the pull request
  • 4. Ship the play switched off, then pilot it on 50 records
  • 5. Evaluate agent prompts on every pull request
  • 6. Use a second workspace as staging, for changes you cannot pilot
  • When a test misses something
  • FAQ

Stay Informed with our
weekly Newsletter

Related articlesSee all articles
GTM Engineering
CI/CD for Go-to-Market: What It Means and How to Set It Up

CI/CD for GTM means every change to enrichment, scoring, routing and sequences ships as a pull request that is planned, checked, approved, deployed on merge, logged and reversible. What each software CI/CD step becomes for go-to-market, and how to set it up on Cargo.

AurelienAurelien·Nov 3, 2026
GTM Engineering
Require Approval Before a High-Impact Go-to-Market Change Goes Live

How Cargo holds a go-to-market pull request that would send or spend more than set limits until a reviewer adds the cargo:approve-impact label: the thresholds, what counts as high impact, who should approve, and what the gate does not catch.

AurelienAurelien·Nov 3, 2026
GTM Engineering
Try Cargo Without an Account: Browse Go-to-Market Actions, Dry Run One, Plan a Project

What works in Cargo before you sign up: list every connector and native action with its credit price, dry run one for free, and plan a project offline with the cargo-ai CLI, or browse the catalog from any agent through the public MCP server at mcp.getcargo.io/public. Every command, what it returns, and what still needs an account.

AurelienAurelien·Oct 23, 2026

Build the self-driving GTM engine

Your coding agents build it on Cargo.Or our team builds, operates and improves it with you.

Start building
Cargo
Backed byY CombinatorSOC 2 Type IICertified
LinkedinX

Product

AI AgentsPlaysToolsData ModelsAppsTerritoriesContextEnrichmentRoutingIntegrationsPricing

Add-ons

Chrome extensionButtonFormSlack

Build

DocsDeveloper resourcesCargo API docsCargo OpenAPI specCargo auth docsCargo webhooksCargo MCP serverProjectsClaude Code

Resources

ReportsBlogCustomer storiesCookbooksGTM skillsGTM EngineeringGlossaryCompareCargo x ClayCargo x WorkatoCargo x n8nCargo x DeeplineCargo x DefaultCargo x LeanDataCargo x UnifyCargo x ValleyCargo x Gojiberry

Company

ManifestoCommunityEventsJobsPartners DirectoryPartner Program

Legal

SecurityTerms of servicePrivacy PolicyRefundsDPASupport
© 2026 Cargo
 ////////    ///////    ////////     ////////    ///////
///         ///   ///   ///   ///   ///         ///   ///
///         ///   ///   ///   ///   ///         ///   ///
///         /////////   ////////    ///  ////   ///   ///
///         ///   ///   /// ///     ///   ///   ///   ///
///         ///   ///   ///  ///    ///   ///   ///   ///
 ////////   ///   ///   ///   ///    ///////     ///////

$ npm install -g @cargo-ai/cli