Skip to main content
Cargo resolves credentials and configuration from your environment — both inside define* resources (secret() / env()) and for the CLI itself (CARGO_* variables). This page covers both, and how to deploy the same code to more than one workspace.

secret() vs env()

Both read a value from process.env at deploy time, but they differ in one important way — whether the value is tracked in the content hash:
HelperResolvedIn the content hash & cargo.state.json?Use for
secret("NAME")at apply timeNo — only a reference is storedCredentials: API keys, tokens, refresh tokens
env("NAME")at load timeYes — the value enters the specNon-secret config you want tracked (region, base URL, …)
connectors/hubspot.ts
import { defineConnector, secret, env } from "@cargo-ai/cdk";

export const hubspot = defineConnector("hubspot", {
  integration: "hubspot",
  config: {
    method: "privateApp",
    accessToken: secret("HUBSPOT_API_KEY"),  // never hashed or stored
    region: env("HUBSPOT_REGION"),            // tracked in the content hash
  },
});
Always use secret() — never env() — for credentials. secret() is excluded from the content hash and from cargo.state.json; env() bakes the value into the hash, so rotating it reads as drift and the value is written to state.

How each behaves

  • secret("NAME") returns a deferred reference (SecretRef). At apply time the CDK reads process.env.NAME, wraps it in Cargo’s encryption envelope, and sends it to the API. If the variable is unset at deploy, the deploy throws. Because the reference — not the value — enters the spec, rotating a secret doesn’t register as drift, and a plain deploy won’t push the new value (nothing in the hash changed). Re-apply the resource to roll a rotated secret: make any other change, or run cargo-ai cdk deploy --refresh.
  • env("NAME") reads process.env.NAME when the file is imported and inlines the value into the spec. If the variable is unset it returns a visible ${NAME} placeholder so the gap surfaces in cargo-ai cdk plan.
See State & drift for how the content hash drives what a deploy considers changed.

CLI environment variables

The cargo-ai CLI (and therefore cargo-ai cdk) reads three environment variables. They take precedence over the saved credentials file (~/.config/cargo-ai/credentials.json):
VariablePurposeDefault
CARGO_API_TOKENAPI token used to authenticate every request— (falls back to the saved credentials)
CARGO_WORKSPACE_UUIDThe workspace to operate on— (falls back to the token’s workspace)
CARGO_BASE_URLCargo API base URLhttps://api.getcargo.io
In CI or an AI coding agent, set these instead of running cargo-ai login:
export CARGO_API_TOKEN=<your-api-token>
export CARGO_WORKSPACE_UUID=<workspace-uuid>   # optional; pins the target workspace
cargo-ai whoami                                # confirms the active token, workspace, and source
whoami reports the source as environment when a CARGO_API_TOKEN is set, or credentials-file when it’s reading the saved login.

Promoting code to a second workspace

The same CDK code can deploy to multiple workspaces (e.g. staging → production). Two things change per workspace; the code does not:
  1. Which workspace you target — set CARGO_WORKSPACE_UUID (or log in to that workspace), so cargo-ai cdk deploy resolves the right target.
  2. The secret values — provide each environment’s secret() values via its own environment variables. Because secret() resolves from process.env at deploy time, pointing the same code at production keys is just a different set of exported variables.
# Deploy the same repo to the production workspace
export CARGO_WORKSPACE_UUID=<prod-workspace-uuid>
export HUBSPOT_API_KEY=<prod-hubspot-key>
cargo-ai cdk deploy --dir ./prod   # keep prod's cargo.state.json separate
Each workspace needs its own cargo.state.json — it records the workspace uuid, and a deploy refuses to run if the state file belongs to a different workspace than the one selected (it would orphan resources). Keep a separate checkout or --dir per workspace so their state files don’t collide.
Secrets are never copied between environments through Cargo: cargo.state.json records only uuids, hashes, and outputs — never secret values.