> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Run the go-live checklist

> Check credentials, configuration, behavior, integrations, and the release path before you promote an agent version to production

After this checklist, the agent version you promote has no missing secret, no unpinned model, no unsigned webhook, no untested workflow, and a rollback you have rehearsed. Run it before the first release and before any that touches credentials, channels, or workflows; the release itself is [Release an agent to production](/ship/releasing).

*Verified against lua-cli 3.33.0.*

**Before you begin**

* A project that compiles (`lua compile --ci` exits 0) and passes [Test an agent before you release](/ship/testing).
* A credential for the agent, and its ID in `lua.skill.yaml`.

<Steps>
  <Step title="Lock down credentials">
    - CI authenticates with a scoped [API key](/concepts/credentials) stored as a CI secret and read from `LUA_API_KEY`; nobody's personal user session runs the release.
    - No key or secret appears in code: tools read `env('KEY')`, and each value is stored with `lua env production -k <KEY> -v <value>` ([Call your API](/build/call-your-api)).
    - `.env` is listed in `.gitignore` (the scaffold's `.gitignore` holds only `dist-v2/`; copy `.npmignore` over it) and holds values for local `lua test` runs only.

    ```bash theme={null}
    lua env production --list
    ```

    Every key a tool reads is listed; values print masked.
  </Step>

  <Step title="Pin the agent configuration">
    * `src/index.ts` names a `model` (or a model resolver). Pushing a `LuaAgent` with neither clears the server's model, including one chosen in the admin dashboard; pick a code from `lua models list --json --ci` ([About models](/concepts/models)).
    * The [persona](/concepts/persona) has been reviewed in the sandbox with `lua persona sandbox view`.
  </Step>

  <Step title="Lock down controls">
    * [Governance](/concepts/governance) is pushed: `src/governance.ts` names the tools that never run (`rules.blockTools`), the ones a person confirms (`rules.requireToolApproval`), and an `injection` threshold; `lua push agent` applies it at once.
    * `lua sync --check` exits 0: no drift in name, persona, model, or governance between your checkout and the server.
    * `lua auth sessions` lists only devices you recognize; `lua auth sessions revoke <id>` signs out any other.
    * The CI key holds `agents:read`, `agents:write`, `automations:read`, and `automations:write`, plus `workflows:read` and `workflows:write` only when it pushes workflows, and no `knowledge:*` or `agents:manage` ([Automate releases in CI](/ship/ci-and-automation)).
    * Telemetry is decided: `lua telemetry off` on any machine that must send nothing.
  </Step>

  <Step title="Check knowledge, features, and channels">
    * Knowledge documents are uploaded and `lua resources list` shows them; Knowledge Search is on with `lua features enable --feature-name rag` ([Add knowledge](/build/add-knowledge)).
    * `lua features list` shows only the [features](/concepts/knowledge-and-features) you want; Web Search is on by default for agents created in the admin dashboard.
    * `lua channels list` shows every channel end users will use, and you have sent one message on each ([quick testing](/channels/quick-testing) tries a channel before you connect your own number or page).
    * Outbound sends outside WhatsApp's 24-hour window use an approved WhatsApp message template ([Send proactive messages](/build/send-proactive-messages)).
  </Step>

  <Step title="Verify webhooks, jobs, workflows, and MCP servers">
    * Every [webhook](/concepts/webhooks) sets `secret` as a string literal, so calls without a valid `x-lua-signature: sha256=<hex>` are refused; vendors with their own signature scheme are verified inside `execute`. Test against `https://webhook.heylua.ai/<agent-id>/<webhook-name>` ([Handle a webhook](/build/handle-a-webhook)).
    * Every [job](/concepts/jobs) sets `timeout` (1 to 600 seconds, default 300) and `retry: { maxAttempts, backoffSeconds }`, and `lua test job --name <name>` ran clean ([Schedule a job](/build/schedule-a-job)).
    * Every [workflow](/concepts/workflows) was pushed on its own, because `lua push all` skips workflows, and `lua test workflow --name <name>` covered both sides of each predicate and each approval ([Test a workflow offline](/build/workflows/test-offline)).
    * `lua mcp list` shows each [MCP server](/concepts/mcp-servers) you rely on as active.

    ```bash theme={null}
    lua push workflow --ci --force --name <workflow-name>
    lua workflows deploy <workflow-name> -v latest
    ```
  </Step>

  <Step title="Rehearse the release and the rollback">
    * The numbers on [Limits](/ship/limits) hold for your traffic, and `lua logs --type agent_error --limit 5 --json` returns an empty `logs` array in the sandbox ([Read logs and debug an agent](/ship/logs-and-debugging)).
    * `lua status --json --ci` shows no primitive as `behind` and no orphan with `critical: true`.
    * The candidate is a staged [agent version](/concepts/releases-and-versions), diffed against the active one and previewed in production.
    * The rollback is `lua version promote <previous>`, the same command as the release and immediate; it restores every code primitive version and the model and touches nothing else: not the persona (`lua deploy persona --set-version <n> --force`), environment variables, knowledge, features, channels, MCP activation, governance and model settings, devices, data the bad version wrote, or runs in flight ([what a version snapshots](/concepts/releases-and-versions#what-an-agent-version-snapshots)).
    * If you release through the Claude Code plugin, it blocks production commands until you confirm once; `--auto-deploy` is never used ([Claude Code plugin](/build-with-ai/claude-code-plugin)).

    ```bash theme={null}
    lua push all --ci --force
    lua version create --ci -m "Go-live candidate"
    lua version diff <active> <staged>
    lua chat --agent-version <staged> -m "What is the status of my tickets? My email is user@example.com" -t --clear
    lua version promote <staged>
    ```
  </Step>

  <Step title="Verify">
    Confirm the active marker moved, send one production message on a fresh thread, and check for agent errors.

    ```bash theme={null}
    lua version list --limit 3
    lua chat -e production -m "What is the status of my tickets? My email is user@example.com" -t --clear
    lua logs --type agent_error --limit 5 --json
    ```

    ```text Output theme={null}
    {
      "logs": [],
      "pagination": {
        "currentPage": 1,
        "totalPages": 0,
        "totalCount": 0,
        "limit": 5,
        "hasNextPage": false,
        "hasPrevPage": false,
        "nextPage": null,
        "prevPage": null
      }
    }
    ```

    The `*` marks the active version. An empty `logs` array is the pass condition; otherwise roll back with `lua version promote <previous>` and read the entries.
  </Step>
</Steps>

## If it isn't working

<Accordion title="Model configuration cleared appears in the push output">
  `src/index.ts` has no `model` and no resolver, so the push sent `null` and the agent fell back to the platform default. Add `model: '<code>'`, push again, and create a new version.
</Accordion>

<Accordion title="A webhook answers 401 Invalid webhook signature to the vendor">
  The vendor doesn't send `x-lua-signature`; it signs with its own header. Remove `secret` from that webhook, verify the vendor's header inside `execute`, then push and deploy the webhook.
</Accordion>

<Accordion title="lua status --json shows a primitive as behind">
  The server has a newer version than your checkout. Run `lua sync --pull`, review the changes, and restart the checklist from the push.
</Accordion>

## Next steps

<Columns cols={2}>
  <Card title="Release an agent to production" href="/ship/releasing">Push, snapshot, promote, verify, and roll back.</Card>
  <Card title="Automate releases in CI" href="/ship/ci-and-automation">The same commands behind a GitHub approval gate.</Card>
  <Card title="Limits" href="/ship/limits">Timeouts, sizes, and quotas in one place.</Card>
  <Card title="About releases and versions" href="/concepts/releases-and-versions">What a version snapshots and what it doesn't.</Card>
</Columns>
