Source: https://docs.cumuluslabs.io/recipes
Content version: ee104312

# Build and test recipes

Follow these workflows with MCP, REST or the SDKs. Read each operation's schema before forming its request; the links below expose the current registry contract.

## Prerequisites {#prerequisites}

Connect [your coding agent](/docs/ai-agents) or [the API](/docs/api#api-key). Use a sandbox member key and verify it with `environments_list`. Read IDs from results. Simulation admission must be open; check `runs_capacity` and ask Cumulus to configure capacity if needed.

## Create and publish without going live {#publish-test-version}

1. [agents.create](/docs/reference/agents.create): create from a template. The response supplies the agent ID and draft identity/revision.
2. [drafts.edit](/docs/reference/drafts.edit): send typed edits with that draft ID and `expected_revision`. Carry the returned revision forward.
3. [drafts.validate](/docs/reference/drafts.validate): fix errors and revalidate. Use its next version; do not guess one.
4. [publications.publish](/docs/reference/publications.publish): pass the draft ID, current revision, validated version and **`live: false`**. Use the actual version returned, including on an idempotent replay.
5. [agents.get](/docs/reference/agents.get): verify the live head did not change.

Expected result: an immutable test publication exists, and live runs still resolve to the previous head. A new agent may have no live head yet.

> **Publishing defaults matter:** leaving out `live: false` can change the live head. Editing a draft does not change an existing publication.

## Import and simulate a phone agent {#import-and-test}

1. [agents.import_inspect](/docs/reference/agents.import_inspect): inspect the Retell export and resolve model-binding and secret diagnostics. See [Import from Retell](/docs/agents#import).
2. [agents.import](/docs/reference/agents.import): import the resolved configuration. This creates a draft.
3. Validate and publish the test version using the workflow above.
4. [test_suites.create](/docs/reference/test_suites.create): define simulated callers and assertions appropriate to the agent. Read the schema for the suite kind and case fields.
5. [test_runs.estimate](/docs/reference/test_runs.estimate): inspect the estimate before starting work.
6. [test_runs.create](/docs/reference/test_runs.create): run the suite against the pinned agent version.
7. Poll [test_runs.get](/docs/reference/test_runs.get) until it completes, then inspect [test_runs.results](/docs/reference/test_runs.results) and failing [test_runs.trial](/docs/reference/test_runs.trial) transcripts.

Expected result: assertions produce a verdict for the pinned version without dialing a phone. A trunk and number are not required for text simulations.

## Promote a tested version {#promote}

Read the current head with `agents_get`. After authorization to go live, call [publications.promote](/docs/reference/publications.promote) with the tested version and `expected_head_version` equal to the head you just read (or `null` for the first head).

Expected result: new runs without an explicit version use that publication. Existing runs keep the version and digest they started with. A conflict requires rereading the head and reconsidering the promotion.

## Start and follow a cloud run {#cloud-run}

Read [runs.create](/docs/reference/runs.create), choose a published version, supply the required input and start a cloud run. Follow [runs.events](/docs/reference/runs.events) or poll [runs.get](/docs/reference/runs.get). Once ended, read [runs.result](/docs/reference/runs.result), the transcript and usage.

Use the [complete curl, TypeScript and Python examples](/docs/api#cloud-run) to carry the run ID from creation into subsequent requests.

Expected result: one run with a fixed publication version reaches a terminal state and exposes its recorded output. After `outcome_unknown`, retry the original command with the same idempotency key.

## Roll back the live head {#rollback}

List [publications](/docs/reference/publications.list), inspect the intended earlier version and read the current head. After authorization, promote the earlier version with the current `expected_head_version`. Verify the new head with `agents_get`.

Expected result: subsequent default-version runs use the earlier publication. Rollback does not rewrite completed or in-flight runs.

## Diagnose a refused call {#refused-call}

Read the error code, `details.reason`, current environment and [runs.capacity](/docs/reference/runs.capacity). Check trunk, imported caller-ID number and required dynamic variables. Follow [Troubleshooting](/docs/troubleshooting#refused-run); change the cause before retrying.

> **Phone tests dial real numbers:** `runs_create` with channel `phone` places a call even when `test: true`. Use simulations for testing without a call.
