# Deploy from CI

Validate an agent locally in CI and deploy it to a selected tenant with an organization-owned credential.

Create an [automation client](/guides/deploy/automation-credentials) with the `deploy` profile.
Store its client ID and secret in your CI secret store, and set the platform API origin as a CI
variable. The job needs no interactive login.

- **Pull request:** `tanomis agent deploy --dry-run` validates the manifest and lock policy and
  uploads nothing.
- **Merge:** deploy to the sandbox tenant.
- **Gate:** the evaluation verdict decides whether a rollout job may run.
- **Customers:** `tanomis agent rollout` to named tenants with a canary share, behind an approval.

## Pipeline example

This GitHub Actions example uses a runner labeled `tanomis` with `tanomis` and your agent's build and
test tools installed. Configure that runner for your repository before using the workflow. Run
your agent's own tests in the validation job as well.

```yaml title=".github/workflows/agent.yml"
name: support-copilot
on:
  pull_request:
    paths: ["agents/support-copilot/**"]
  push:
    branches: [main]
    paths: ["agents/support-copilot/**"]

jobs:
  validate:
    runs-on: [self-hosted, tanomis]
    steps:
      - uses: actions/checkout@v4
      - run: tanomis agent deploy agents/support-copilot --tenant "$TANOMIS_TENANT" --dry-run
        env:
          TANOMIS_TENANT: northwind-sandbox

  deploy-sandbox:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    needs: validate
    runs-on: [self-hosted, tanomis]
    environment: sandbox
    steps:
      - uses: actions/checkout@v4
      - run: tanomis agent deploy agents/support-copilot --tenant "$TANOMIS_TENANT"
        env:
          TANOMIS_API_URL: ${{ vars.TANOMIS_API_URL }}
          TANOMIS_CLIENT_ID: ${{ secrets.TANOMIS_CLIENT_ID }}
          TANOMIS_CLIENT_SECRET: ${{ secrets.TANOMIS_CLIENT_SECRET }}
          TANOMIS_TENANT: northwind-sandbox
```

Set `TANOMIS_API_URL` to `https://api.tanomis.com` for hosted Tanomis, or your self-hosted API origin.
The tenant IDs are examples; substitute the IDs from your organization. Keep deployment
credentials out of pull-request validation jobs, and use a runner policy appropriate for the code
you allow to execute.

To test a version before anyone is served it, deploy it with `--stage`: it is built, registered,
and able to start sessions, and the tenant keeps the version it serves. Then run `tanomis eval ci`
against it; see [Evaluate a version](/guides/evaluate/evaluate-a-version).

`--dry-run` validates the local package and manifest without API calls or uploads. It does not
check live tenant permissions, quotas, or build availability. The authenticated deployment checks
those and builds and enables the version in the selected tenant.

## Deploy to a customer tenant

Use a protected customer deployment job to deploy the reviewed source revision with
`--tenant bluewater-bank`. Configure your CI environment's approval rules before enabling
that job. An organization M2M client registers tenant-owned agents, so deployment to another
tenant creates or updates that tenant's registration. Do not use `--scope global`, `--tenants all`,
or assume a sandbox tenant's version can be promoted into another tenant's registration.

The `deploy` profile cannot invoke agents or use the evaluation API. Keep any evaluation or
runtime acceptance gate in a separately authorized process; use an `invoke` client when the
check needs to run an agent, including `tanomis eval ci`. A deploy credential reaches all ready tenants in its organization,
so a CI environment name alone is not a platform permission boundary.

After deployment, inspect the enabled version in the target tenant:

```bash
tanomis agent versions support-copilot --tenant "$TANOMIS_TENANT" --by-tenant
```

## Where to go next

- [Automation credentials](/guides/deploy/automation-credentials): rotation and immediate disable.
- [`tanomis agent deploy`](/cli/agent/deploy): deployment flags and output.
- [Customer tenants](/guides/manage/tenants-and-environments)
