Skip to main content
A Cargo workspace is a directory of TypeScript files. The CLI imports every .ts file under the project root, and each define* call registers a resource as a side effect. There is no manifest — the files are the interface.

The full template

cargo-ai cdk init <dir> --template full scaffolds a complete, runnable workspace that exercises every resource type and wires them together. For a guided walkthrough that builds and deploys this whole tree, see the End-to-end recipe:
my-workspace/
├── package.json          # scripts: "plan": "cargo-ai cdk plan", "deploy": "cargo-ai cdk deploy"
├── tsconfig.json         # includes .cargo-ai/**/*.d.ts for typed config
├── cargo.state.json      # created on first deploy — commit it
├── connectors/
│   ├── hubspot.ts        # defineConnector + secret()
│   └── openai.ts         # defineConnector({ adopt: true })
├── folders/crm.ts        # defineFolder (per-kind: model, agent, …)
├── models/contacts.ts    # defineModel — dataset handle + extractSlug + schedule
├── tools/enrich.ts       # defineWorkflow + defineTool
├── agents/
│   ├── enricher.ts       # defineAgent (sub-agent)
│   └── sdr.ts            # defineAgent (models, tools, subAgents, triggers, evaluator)
├── plays/onboarding.ts   # definePlay + per-row defineWorkflow
├── mcp/crm.ts            # defineMcpServer
├── context/              # defineContext + markdown/MDX
├── files/                # defineFile + local content
├── workers/webhook/      # defineWorker → a built bundle
└── apps/dashboard/       # defineApp → a Vite bundle

How the loader works

  • Every .ts file is imported. Importing registers whatever define* calls it contains. To add a resource, add a file.
  • Handles create dependencies. define* returns a handle whose outputs (uuid, datasetUuid, …) are deferred tokens. Passing a handle into another builder (e.g. dataset: hubspot, tools: [enrich]) both orders the deploy and injects the real uuid. The dependency graph is your variable graph.
  • Bundle directories are skipped. A subdirectory with its own package.json (a worker or app bundle) is treated as content to upload, not a resource file to import.

cargo.state.json

Every deploy writes cargo.state.json — the authoritative map from each code resource (kind:slug) to the real uuid Cargo assigned it, plus outputs and a content hash.
Commit cargo.state.json. Connectors and models are slug-addressable and self-heal, but plays, agents, tools, files, and MCP servers have no slug — their stored uuid is the only way to re-find them. Lose the file and a re-deploy creates duplicates. Recover a lost link with cargo-ai cdk import <id> <uuid>.
The lock/backup/audit siblings are ephemeral — git-ignore them:
.cargo-ai/
cargo.state.lock
cargo.state.bak.json
cargo.state.audit.jsonl

Which init do I want?

There are several scaffold/init commands — don’t confuse them:
CommandWhat it does
cargo-ai cdk init <dir>Scaffold a CDK workspace project (this page).
cargo-ai hosting app init <dir>Scaffold a hosted Vite app bundle.
cargo-ai hosting worker init <dir>Scaffold a hosted edge worker bundle.
cargo-ai initAn API call that fetches workspace initialization data — not a local scaffold.

Next steps

Connectors

Start wiring in your data sources.

Deploying

The full reconcile lifecycle and its flags.

State & drift

How state tracks live resources and detects out-of-band changes.