Source: https://cli.nylas.com/guides/deploy-agent-accounts-docker

# Deploy Agent Accounts in Docker & CI

An agent account has no OAuth browser flow, which is exactly why it runs cleanly in a container or a CI job — there's no consent screen to click. This guide packages the CLI into a Docker image, authenticates headlessly with an API key pulled from a secret at runtime (never baked into a layer), runs the agent's account commands as the entrypoint, and shows the GitHub Actions equivalent. The result is a reproducible, headless agent identity you deploy like any other service.

Written by [Caleb Geene](https://cli.nylas.com/authors/caleb-geene) Director, Site Reliability Engineering

Updated June 8, 2026

> **TL;DR:** Install the CLI in your image with `install.sh`, authenticate at runtime with `nylas auth config --api-key` from a secret — never an OAuth flow, never a key baked into a layer — then run `nylas agent` commands as the entrypoint.

## What does deploying an agent account in a container involve?

Deploying an agent account in a container means packaging the CLI and your agent script into an image, then giving the container an API key at runtime so it can authenticate without a human. There's no browser step: an agent account authenticates with an API key, not an OAuth consent flow, so the whole thing runs headless. The container installs the CLI, configures credentials from an injected secret, and runs the agent.

That headless property is what makes agent accounts a natural fit for containers and CI. A user-mailbox integration needs an interactive OAuth grant that can't happen inside a build job; an agent account needs only a key. The three steps below — install, authenticate, run — are the whole deployment.

Container flow: install the CLI in the image, authenticate headlessly with a secret, run the agentInstall CLIinstall.sh in imageAuth headless--api-key from secretRun agentnylas agent...

## Why run an agent-account agent in Docker or CI?

Containers give an agent the same thing they give any service: a reproducible environment and a clean deploy path. Baking the CLI into the image means the agent behaves identically wherever the image runs — and you can pin a specific tagged release instead of the latest when you need strict version stability. CI adds a schedule and a trigger — a cron-driven workflow or a step in a pipeline — without standing up a server to host the agent.

The alternative, running the agent on a long-lived box you maintain, carries the same operational tax this whole product avoids. A container is built once and run anywhere; a CI job runs on infrastructure you don't patch. For an autonomous email agent, that's the right deployment shape — ephemeral, reproducible, and credentialed from a secret store.

## How do I install the CLI in a Docker image?

Install the CLI in the image with the same script used on a workstation. The [install script](https://cli.nylas.com/install.sh) auto-detects architecture, downloads the latest release, and verifies its SHA-256 checksum. Add the install directory to `PATH` so later layers and the entrypoint can call `nylas`:

```dockerfile
FROM debian:bookworm-slim

RUN apt-get update \
  && apt-get install -y --no-install-recommends curl ca-certificates jq \
  && rm -rf /var/lib/apt/lists/*

# Install the Nylas CLI (checksum-verified by the script)
RUN curl -fsSL https://cli.nylas.com/install.sh | bash
ENV PATH="/root/.config/nylas/bin:${PATH}"

COPY agent.sh /app/agent.sh
RUN chmod +x /app/agent.sh
ENTRYPOINT ["/app/agent.sh"]
```

The CLI installs to `~/.config/nylas/bin` by default, which is `/root/.config/nylas/bin` for the root user — the path the `ENV PATH` line adds. Installing `jq` in the same layer gives the agent script its JSON tooling. For all install methods, see [getting started with the CLI](https://cli.nylas.com/guides/getting-started).

## How do I authenticate headlessly?

Authenticate at runtime, not at build time, so the key never lands in an image layer. The container reads the API key from an injected environment variable and runs `nylas auth config --api-key` as the first thing the entrypoint does. Use `nylas auth config --api-key`, not `nylas auth login` — the latter opens a browser flow that can't complete in a container:

```bash
#!/usr/bin/env bash
set -euo pipefail

# Fail fast if the key wasn't injected
: "${NYLAS_API_KEY:?NYLAS_API_KEY is required}"

# Headless auth from the injected secret (no browser, no OAuth)
nylas auth config --api-key "$NYLAS_API_KEY" --region "${NYLAS_REGION:-us}"

# Now the agent account commands work
nylas agent status --json
nylas agent account list --json | jq -r '.[].email'
```

The `:?` guard aborts the entrypoint immediately if the key is missing, so the container fails loudly instead of running unauthenticated. Default the region to `us` and override with `NYLAS_REGION=eu` for the EU data region. Authentication completes in one call, and the agent's account commands run from there.

## How do I run the agent in the container?

Pass the key at `docker run` time from your host's environment or a secret manager — never with `--build-arg`, which would bake it into the image. The entrypoint authenticates and runs the agent:

```bash
docker build -t my-email-agent .

# Inject the key at run time, not build time
docker run --rm -e NYLAS_API_KEY="$NYLAS_API_KEY" my-email-agent
```

Because the key arrives as a runtime environment variable, it never appears in `docker history` or an image layer. In production, source it from your orchestrator's secret store — [Docker secrets](https://docs.docker.com/engine/swarm/secrets/), a Kubernetes Secret, or a cloud secret manager — rather than a plain host variable.

## How do I deploy to CI with GitHub Actions?

In CI, the same three steps become workflow steps, with the API key coming from an encrypted repository secret. The job installs the CLI, adds it to the path, authenticates from `secrets.NYLAS_API_KEY`, and runs the agent on a schedule:

```yaml
name: agent-email-task
on:
  schedule:
    - cron: "*/15 * * * *"   # every 15 minutes
jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - run: curl -fsSL https://cli.nylas.com/install.sh | bash
      - run: echo "$HOME/.config/nylas/bin" >> "$GITHUB_PATH"
      - run: nylas auth config --api-key "$NYLAS_API_KEY"
        env:
          NYLAS_API_KEY: ${{ secrets.NYLAS_API_KEY }}
      - run: nylas agent account list --json | jq -r '.[].email'
        env:
          NYLAS_API_KEY: ${{ secrets.NYLAS_API_KEY }}
```

The key lives in [GitHub Actions encrypted secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions) and is injected per step via `env`, so it's never written to the workflow file or the logs. This is the same pattern as the Docker entrypoint, expressed in YAML.

## How do I keep the API key safe in containers?

An agent account's API key is the credential for every account in the application, so protecting it is the security priority of the whole deployment. Three rules cover it: never bake the key into an image, never log it, and scope it to what the agent needs.

- **Runtime, not build time** — inject the key with `-e` or a mounted secret, never `ENV` or `--build-arg`. Anything in the Dockerfile is permanent and inspectable in the image history.
- **Secret store, not plaintext** — source the key from Docker secrets, a Kubernetes Secret, or a cloud secret manager, not a committed `.env` file.
- **Fail closed** — the `:?` guard makes a missing key stop the container rather than run it in a broken, unauthenticated state.

Pair these with the workspace-level controls — a policy send cap, outbound rules — so even a leaked key runs into the containment described in [Stop Your AI Agent From Going Rogue](https://cli.nylas.com/guides/stop-ai-agent-going-rogue). The container protects the key; the workspace bounds the damage if it ever leaks.

## Next steps

- [Getting Started with Nylas CLI](https://cli.nylas.com/guides/getting-started) — all install methods and the headless auth flow
- [Getting Started with Agent Accounts](https://cli.nylas.com/guides/getting-started-agent-accounts) — the identity you deploy in the container
- [Provision Agent Accounts at Scale](https://cli.nylas.com/guides/provision-agent-accounts-at-scale) — run these commands across a fleet from CI
- [Monitor Agent Account Health](https://cli.nylas.com/guides/monitor-agent-account-health) — health probes that run as their own scheduled job
- [Stop Your AI Agent From Going Rogue](https://cli.nylas.com/guides/stop-ai-agent-going-rogue) — the workspace controls that bound a leaked key
- [Full command reference](https://cli.nylas.com/docs/commands) — every `nylas auth` and `nylas agent` flag
- [Nylas v3 API documentation](https://developer.nylas.com/) — the API the CLI authenticates against
