# Deploy an Agent

> Build and update an Agent from an archive or pinned Git commit.

## Before you begin {#before-you-begin}

Prepare a project directory, ZIP or TAR.GZ package, or a public HTTPS Git repository with a full 40-character commit SHA. Native Constal packages declare an Agent manifest. Existing Mastra, LangGraph, OpenAI SDK, and Claude Managed Agents SDK projects use their normal entrypoints and do not add a Constal manifest or replace framework imports. See [Deploy a Mastra project](/docs/agents/mastra/deploy.md), [Deploy OpenAI Agents SDK projects](/docs/agents/openai-agents.md), and [Deploy Claude Managed Agents SDK projects](/docs/agents/claude-managed-agents.md).

## Steps {#steps}

1. For a native package, [author and type-check the Agent](/docs/agents/author.md). For Mastra, retain the existing `package.json`, lockfile, and exported `Mastra` instance; do not install `@constal/sdk` merely to deploy it.
2. Open **Agents** and choose **Deploy Agent**.
3. Select **Package archive** or **Git repository**. Supply the ZIP or TAR.GZ archive, or enter a public repository URL and immutable 40-character commit.
4. Review the expected Resource kind and deployment guidance, then choose **Deploy**.
5. The equivalent Platform API operation is `POST /v1/deployments` with the raw archive, Bearer deployment authority, correct content type, and a caller-stable `Idempotency-Key`.
6. Poll `GET /v1/deployments/:deploymentId` while Constal validates the archive, type-checks the SDK contract, builds and verifies the immutable executable artifact, and safely activates the requested revision.
7. Open the resulting Agent detail page.

```sh
curl https://platform.constal.ai/v1/deployments \
  -H "Authorization: Bearer $CONSTAL_DEPLOYMENT_KEY" \
  -H "Idempotency-Key: support-agent-1.0.0" \
  -H "Content-Type: application/zip" \
  --data-binary @support-agent.zip
```

Redeploy the same Agent id whenever its code or configuration changes. You can omit `version` or reuse its label; changed content does not require a version bump. By default, an immediate deployment updates the Agent without an expected revision. Supply `expectedCurrentDeploymentRevision` only when you want a deployment precondition. Historical deployment records remain available, and running Sessions continue using their accepted code.

## Deploy an Agent with a UI {#ui}

A native Agent manifest may declare its web interface inline with a `ui` block (`id`, `displayName`, `source`, `channel`, and optional `access`, `execution`, `limits`, `labels`). The same deployment builds the Agent, packages the `source` directory as a `constal.ui.v1` bundle, stores it as an immutable artifact, and publishes a `ui` Resource whose `target.agent` is exactly the Agent revision that deployment produced. The Agent and its UI are promoted together or not at all: a UI failure fails the deployment before the Agent current pointer moves, and a stale UI current pointer fails the deployment without moving either pointer.

The deployment record lists both Resources under `outputs`: ordinal `0` is the Agent and ordinal `1` is the UI, whose `resource.url` is the public address. Top-level `resourceCrn` and `resourceHash` remain the Agent's.

```sh
constal deploy . --wait --output json | jq -r '.outputs[] | select(.resourceKind == "ui") | .resource.url'
```

Redeploying re-pins the UI to the new Agent revision while its route and URL stay stable. Removing the block leaves the published UI untouched; delete it explicitly through the Resource API. Manifests with a `ui` block support only immediate rollouts: `--rollout canary` and candidate builds are rejected, so publish such a UI through the standalone Resource API instead. See [Dynamic UIs](/docs/resources/dynamic-uis.md) for the bundle layout.

## Canary a revision {#canary}

Use a canary when production evidence should precede activation. The deployment builds and runs every declared Replay gate normally, but keeps the current Agent pointer unchanged. Eligible new Sessions are assigned deterministically to the candidate or control revision; an existing Session remains pinned to the revision it started with.

```sh
constal deployments create support-agent.zip \
  --rollout canary \
  --fraction 0.05 \
  --tags '{"plan":"enterprise"}'
```

A canary is rejected for an Agent manifest that declares a `ui` block; publish that UI through the standalone Resource API instead. `fraction` must be greater than zero and less than one. `tags` is an optional exact-match selector over invocation tags. The eval door receives immutable `constal.rollout.id` and `constal.rollout.cohort` tags, allowing the same live Scorers to sample candidate and control traffic without delaying either cohort.

Read the rollout, review its evaluation evidence, then make an explicit idempotent decision:

```sh
constal agents rollout get support
constal agents rollout promote support \
  --deployment 123e4567-e89b-42d3-a456-426614174000 \
  --reason "paired quality scores improved"
```

Use `agents rollout rollback` with the same arguments when the candidate regresses. Promotion atomically moves the current pointer from the exact control hash to the candidate hash. Rollback leaves the control pointer untouched. A stale control pointer, concurrent deployment, reused event ID with different intent, or unavailable candidate fails closed.

## Verify {#verify}

Confirm the deployment reports an immutable revision, executable artifact, code digest, successful probe, and rollout state. The detail page should show the expected canonical CRN, Agent version, execution mode, Resource bindings, Policies, Tool catalog, and limits. Start a small Run and check that its journal records the assigned deployment revision and rollout cohort.

## Next steps {#next-steps}

Continue with [Operate Agents](/docs/agents/operate.md), or [Start a Run](/docs/runs/start.md) to test the deployment.
