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

# Quickstart: build and deploy an agent

> Go from an empty folder to a deployed agent that runs on Helix Cloud: one tool, one skill, one file, a local run, a deploy, a new revision and a rollback.

<Note>
  **Early access.** Cloud sessions and managed agent runs are not open to every account yet: we are
  letting accounts in gradually while we test. They run in a cloud sandbox operated by Mutagent, so
  there is nothing to host. A sandbox with nothing to do for 15 minutes stops; send the session a
  message and it wakes up, delivers your message and carries on in the same conversation.
</Note>

In this tutorial you build the invoice-pricing agent. It prices an invoice from a product catalog and
a pricing policy. You write it, run it on your machine, deploy it to an Environment, run it on Helix
Cloud, deploy a change, and roll the change back. It takes about 10 minutes.

The agent has:

| Part | File | Declared in |
| - | - | - |
| Instructions | `agent.md` | The body of `agent.md` |
| A tool that calculates the invoice | `tools/calculate-invoice.ts` | `harness.tools.modules` |
| A skill with the pricing policy | `skills/invoice-pricing/SKILL.md`, `policy.json` | `harness.skills` |
| A file with the product catalog | `assets/catalog.json` | `harness.files` |

## Before you start

Check each item. The command after it is the check.

| You need | Check | If it is missing |
| - | - | - |
| The `mutagent` CLI | `mutagent --version` | [Install the CLI](/cli/installation). |
| A sign-in and a selected workspace | `mutagent workspaces current --json` exits 0 | [Sign in](/cli/commands/login#sign-in-from-a-coding-agent-or-ci). A coding agent runs `MUTAGENT_API_KEY=<key> mutagent login --json`, or `mutagent login --browser --json` and shows the printed URL to the user. Then `mutagent workspaces use <name>`. |
| Bun 1.3.14, which the agent compiler runs on | `bun --version` prints `1.3.14` | Install Bun 1.3.14, or set `MUTAGENT_BUN_BIN` to its path. `check`, `pack`, `run` and `deploy` all need it. |
| An LLM provider in the workspace | `mutagent providers list --json` lists one | [Add an LLM provider](/platform/providers/setup). |
| A model for the agent | `mutagent helix models --json`: pick an id from `models[].id` | This tutorial uses `zai/glm-5.3`. Replace it with an id from your own list, or `deploy` refuses it. |
| Helix on your machine, for the local run in step 7 only | `~/.mutagent/bin/helix --version` | `mutagent install helix`. It writes `~/.mutagent/bin/helix`. |
| The LLM provider's API key on your machine, for step 7 only | — | Put it in your local Helix login or an environment variable. Runs on Helix Cloud use the workspace's key instead. |

Steps 7 and 8 are optional. Without Helix on your machine, skip step 7; you can still deploy and run
the agent on Helix Cloud.

<Tip>
  **For coding agents.** Run every command from the folder that will contain `invoice/`. Add `--json` to
  every `mutagent agent` and `mutagent env` command: each prints one JSON object on stdout, and
  `success` is `true` exactly when the exit code is 0. `mutagent helix agent` is the exception: its
  output is Helix's own, so read its exit code and stderr instead. Exit codes: 0 success, 1 failure
  (usage errors included), 2 key expired or invalid, 3 not signed in or no workspace.
</Tip>

<Steps>
  <Step title="Create the folder">
    ```bash theme={null}
    mkdir -p invoice/tools invoice/skills/invoice-pricing invoice/assets
    ```

    Write `invoice/package.json`. An agent with tool modules needs it. It has no dependencies.

    ```json invoice/package.json theme={null}
    {
      "name": "invoice-pricing-agent-source",
      "private": true,
      "type": "module"
    }
    ```
  </Step>

  <Step title="Write agent.md">
    `agent.md` holds the settings in YAML frontmatter and the agent's instructions in the Markdown
    body. Write `invoice/agent.md`:

    ```markdown invoice/agent.md theme={null}
    ---
    name: invoice-pricing
    description: Calculates invoices from a packaged pricing skill and catalog.
    model: zai/glm-5.3
    thinking: low
    harness:
      tools:
        builtin: [read]
        modules:
          - path: tools/calculate-invoice.ts
            name: calculate_invoice
      skills:
        - skills/invoice-pricing
      files:
        - assets/catalog.json
      runtime:
        mode: headless
    ---
    You are the invoice pricing agent. Every invoice request must follow the invoice-pricing skill.
    Read its SKILL.md and policy.json before calling calculate_invoice. Supply the calculator with
    the policy values and the requested SKU and quantity. Never calculate the total yourself.
    Report the tool's exact totalCents and catalogVersion, followed by the policy receiptWord.
    Do not claim success if a skill file or tool is unavailable.
    ```

    * `name` is the agent's slug. You run it as `@invoice-pricing`.
    * `model` is the model the agent always uses. Replace `zai/glm-5.3` with an id from
      `mutagent helix models`.
    * `harness.tools.builtin: [read]` gives the agent the `read` tool. It reads the skill with it.
    * `harness.tools.modules`, `harness.skills` and `harness.files` declare the three files you write
      next. Only declared files are packaged.
    * `harness.runtime.mode: headless` means a run needs a task.
  </Step>

  <Step title="Add the catalog file">
    Write `invoice/assets/catalog.json`. The tool reads prices from it.

    ```json invoice/assets/catalog.json theme={null}
    {
      "version": "catalog-v1",
      "products": {
        "widget": 1379,
        "gadget": 2683
      }
    }
    ```
  </Step>

  <Step title="Write the tool">
    Write `invoice/tools/calculate-invoice.ts`:

    ```typescript invoice/tools/calculate-invoice.ts theme={null}
    import { readFile } from "node:fs/promises";
    import { join } from "node:path";
    import { defineTool, Type } from "@mutagent/agents/tools";

    interface InvoiceInput {
      sku: string;
      quantity: number;
      discountPercent: number;
      taxBasisPoints: number;
    }

    export default defineTool<InvoiceInput>({
      name: "calculate_invoice",
      label: "Calculate invoice",
      description: "Calculate exact invoice cents from the packaged product catalog and skill policy.",
      parameters: Type.Object({
        sku: Type.String(),
        quantity: Type.Integer({ minimum: 1, maximum: 100 }),
        discountPercent: Type.Integer({ minimum: 0, maximum: 100 }),
        taxBasisPoints: Type.Integer({ minimum: 0, maximum: 10_000 }),
      }, { additionalProperties: false }),
      async execute(_id, params, _signal, _onUpdate, context) {
        const catalogPath = join(context.paths.assetRoot, "assets/catalog.json");
        const catalog = JSON.parse(await readFile(catalogPath, "utf8")) as {
          version: string;
          products: Record<string, number>;
        };
        const unitCents = catalog.products[params.sku];
        if (unitCents === undefined) throw new Error(`Unknown product: ${params.sku}`);
        const subtotalCents = unitCents * params.quantity;
        const discountCents = Math.round(subtotalCents * params.discountPercent / 100);
        const netCents = subtotalCents - discountCents;
        const taxCents = Math.round(netCents * params.taxBasisPoints / 10_000);
        const result = {
          subtotalCents,
          discountCents,
          taxCents,
          totalCents: netCents + taxCents,
          catalogVersion: catalog.version,
          contextVersion: context.agent.contextVersion,
        };
        return { content: [{ type: "text", text: JSON.stringify(result) }], details: result };
      },
    });
    ```

    * `name` equals the `name` under `harness.tools.modules`.
    * `parameters` is the input the model must send.
    * The tool reads the catalog under `context.paths.assetRoot`, where the packaged files are.
    * You do not install `@mutagent/agents`. The compiler supplies it.

    [Tools, skills and files](/platform/managed-agents/tools-and-skills#write-a-tool) explains every
    field.
  </Step>

  <Step title="Write the skill">
    Write `invoice/skills/invoice-pricing/SKILL.md`:

    ```markdown invoice/skills/invoice-pricing/SKILL.md theme={null}
    ---
    name: invoice-pricing
    description: Required policy for invoice pricing requests; read its policy before using the calculator.
    ---

    Read `policy.json` in this skill directory. Supply its `discountPercent` and `taxBasisPoints`
    to `calculate_invoice` together with the requested SKU and quantity. The tool reads the catalog
    from the packaged agent assets, so do not invent a unit price. Include the exact `receiptWord`
    from this skill asset after the returned cents total and catalog version.
    ```

    Write the policy next to it, in `invoice/skills/invoice-pricing/policy.json`:

    ```json invoice/skills/invoice-pricing/policy.json theme={null}
    {
      "discountPercent": 7,
      "taxBasisPoints": 825,
      "receiptWord": "cobalt-orchard"
    }
    ```

    The model sees the skill's name and description. It reads `SKILL.md` and `policy.json` with
    `read`. The folder now holds:

    ```text theme={null}
    invoice/
    ├── agent.md
    ├── package.json
    ├── tools/calculate-invoice.ts
    ├── skills/invoice-pricing/SKILL.md
    ├── skills/invoice-pricing/policy.json
    └── assets/catalog.json
    ```
  </Step>

  <Step title="Check the folder">
    ```bash theme={null}
    mutagent agent check invoice/agent.md
    ```

    `check` compiles the folder and validates it. It sends no request and runs no tool code.

    ```text theme={null}
    success         true
    status          valid
    name            invoice-pricing
    sourceDigest    sha256:510b…6832
    artifactDigest  sha256:0633…48e25
    archiveDigest   sha256:08d6…47a2
    archiveSize     30654
    manifest        {
      "formatVersion": 1,
      …
    ```

    **Success:** exit code 0, and with `--json` the result has `"status": "valid"` and
    `"name": "invoice-pricing"`.

    If `check` refuses the folder, it exits 1 and the message names the problem. Add `--json` to see
    the code and `diagnostics`, which name the file. Fix every diagnostic before you go on.
    [Common refusals](/platform/managed-agents/tools-and-skills#common-refusals) lists the frequent
    ones.
  </Step>

  <Step title="Run it on your machine">
    ```bash theme={null}
    mutagent agent run invoice/agent.md "Price three widget units."
    ```

    `run` builds the package and runs the task with Helix on your machine. It creates nothing in the
    workspace.

    ```text theme={null}
    ┌─ ✓ Agent run: completed ──────────────────────────────────┐
    │                                                           │
    │   status          completed                               │
    │   artifactDigest  sha256:0633…48e25                       │
    │   exitCode        0                                       │
    │                                                           │
    │ ─────────────────────────────────────────────────────────│
    │                                                           │
    │   Next                                                    │
    │   → mutagent agent --help                                 │
    │                                                           │
    └────────────────────────────────────────────────────────────┘
    Priced per the invoice-pricing policy (7% discount, 825 bps tax):

    - **Total: 4164 cents** ($41.64)
    - Catalog version: **catalog-v1**
    - Receipt word: **cobalt-orchard**

    Breakdown: subtotal 4137¢, discount −290¢, tax 317¢.
    ```

    The wording of the answer changes between runs. The total is `4164` cents, the catalog is
    `catalog-v1`, and the answer includes `cobalt-orchard`.

    **Success:** exit code 0, and with `--json` the result has `"status": "completed"`,
    `"exitCode": 0`, and the answer in `text`. If the card shows `status failed`, the command exits
    non-zero: run it again with `--json` and read `diagnostics`. A missing model key reads, for
    example, `No API key found for zai.`
  </Step>

  <Step title="Pack the agent (optional)">
    ```bash theme={null}
    mutagent agent pack invoice/agent.md --output invoice.tgz
    ```

    `pack` writes the package archive that `deploy` uploads. It uploads nothing. `--output` must be
    outside the agent folder.

    ```text theme={null}
    ┌─ ✓ Agent pack: packed ────────────────────────────────────┐
    │                                                           │
    │   status          packed                                  │
    │   artifactDigest  sha256:0633…48e25                       │
    │                                                           │
    │ ─────────────────────────────────────────────────────────│
    │                                                           │
    │   Next                                                    │
    │   → mutagent agent --help                                 │
    │                                                           │
    └────────────────────────────────────────────────────────────┘
    ```

    You do not need `pack` to deploy. `deploy` builds the same package.
  </Step>

  <Step title="Create an Environment">
    A deploy targets a slot: the agent in one Environment. Create the Environment `prod`:

    ```bash theme={null}
    mutagent env set prod INVOICE_CURRENCY=USD
    ```

    On every run in `prod`, the Environment's variables and secrets are environment variables in the
    sandbox. This agent's tool does not read any, so one variable is enough. A tool that needs a
    token reads it from here. See [Secrets](/platform/managed-agents/tools-and-skills#secrets).

    **Success:** exit code 0, and with `--json` the result has `"success": true` and `"created": true`.
    If `prod` already exists, `set` adds the variable to it and keeps its other entries;
    `created` is then `false`.
  </Step>

  <Step title="Deploy">
    ```bash theme={null}
    mutagent agent deploy invoice/agent.md --env prod
    ```

    `deploy` builds the package, uploads it as revision `v1`, checks the model and the Environment,
    and makes `v1` the active revision in `prod`.

    ```text theme={null}
    ┌─ ✓ Agent deploy: active ──────────────────────────────────────────┐
    │                                                                   │
    │   slug            invoice-pricing                                 │
    │   revision        v1                                              │
    │   environment     prod                                            │
    │   activeRevision  v1                                              │
    │   status          active                                          │
    │   activated       true                                            │
    │   enabled         true                                            │
    │   artifactDigest  sha256:0633…48e25                               │
    │   operationId     op_…                                            │
    │                                                                   │
    │ ─────────────────────────────────────────────────────────────────│
    │                                                                   │
    │   operation       <operation link>                                │
    │                                                                   │
    │ ─────────────────────────────────────────────────────────────────│
    │                                                                   │
    │   Next                                                            │
    │   → mutagent agent inspect invoice-pricing --env prod --json      │
    │   → mutagent helix agent @invoice-pricing --env prod -p "<task>"  │
    │                                                                   │
    └────────────────────────────────────────────────────────────────────┘
    Managed agent invoice-pricing v1 is active in Environment "prod".
    ```

    **Success:** exit code 0. With `--json`, stdout holds one result with `"slug": "invoice-pricing"`,
    `"revision": 1`, `"activated": true`, `"environment": "prod"`, `"activeRevision": 1` and an
    `operationId`; the status card goes to stderr. Revisions are numbers in JSON and `v1` in
    messages. Keep the slug and the revision.

    A model that is not in the workspace model list is refused with `MODEL_NOT_IN_LIST`. An
    Environment that does not exist is refused with `ENVIRONMENT_NOT_FOUND`. A refused deploy writes
    nothing. See [If it fails](#if-it-fails).
  </Step>

  <Step title="Run it on Helix Cloud">
    ```bash theme={null}
    mutagent helix agent @invoice-pricing --env prod -p "Price three widget units."
    ```

    The platform starts a sandbox, copies revision `v1` into it, and runs the task. The answer is
    printed on stdout:

    ```text theme={null}
    Total: **4164 cents ($41.64)** — catalog `catalog-v1`.

    Breakdown for 3× widget (discount 7%, tax 825 bps):
    - Subtotal: 4137¢
    - Discount: −290¢
    - Tax: +317¢
    - **Total: 4164¢**

    Receipt word: cobalt-orchard
    ```

    The run's receipt and progress are printed on stderr:

    ```text theme={null}
    [mutagent] {"reference":"hs1_…","agent":{"slug":"invoice-pricing","revision":1},"mode":"headless"}
    [mutagent] Session hs1_…. Ctrl-C stops the session (SIGINT).
    [mutagent] Session <session-id> started.
    [helix <version>] agent invoice-pricing · …/generated/agent.md · glm-5.3
    [mutagent:agent-package] {"type":"mutagent.agent.registration.v1","launchAbiVersion":1,"status":"verified","registeredTools":["calculate_invoice"],"activeTools":["calculate_invoice","read"],"expectedTools":["calculate_invoice","read"],"bindings":{"status":"verified","required":[],"optional":[],"available":[],"missing":[]},"artifactDigest":"sha256:0633…48e25","revisionId":"rev_…"}
    ```

    * The first line is the receipt. `reference` is the session reference, which starts with `hs1_`.
      Every session command takes it. `agent.revision` is the revision that runs.
    * The `[mutagent:agent-package]` line is the registration receipt. `status` is `verified`: the
      tools that started equal the tools `agent.md` declares. See
      [The registration receipt](/platform/managed-agents/tools-and-skills#the-registration-receipt).

    **Success:** the command exits with the session's exit code, 0 when the task completed, and the
    answer is on stdout. A refusal before the sandbox starts is printed on stderr with the fix to run.
  </Step>

  <Step title="List the session">
    ```bash theme={null}
    mutagent helix session ls
    ```

    ```text theme={null}
    REFERENCE  SANDBOX  AGENT               ARM    MODE      STATUS  LAST ACTIVITY
    ---------  -------  ------------------  -----  --------  ------  ------------------------
    hs1_…      sbx_…    invoice-pricing:v1  agent  headless  ended   2026-09-16T20:30:51.175Z

    1 result(s)
    ```

    `AGENT` shows the slug and the revision. `STATUS` is `ended` because a headless run ends after its
    task.
  </Step>

  <Step title="Attach to the session">
    Replace `<reference>` with the `hs1_` reference from the receipt or from `session ls`:

    ```bash theme={null}
    mutagent helix session attach <reference>
    ```

    `attach` prints the session's output from the start, then follows it until it ends. It is
    read-only. Ctrl-C detaches.

    ```text theme={null}
    [mutagent] Session hs1_…. Ctrl-C detaches.
    [mutagent] Session <session-id> started.
    [helix <version>] agent invoice-pricing · …/generated/agent.md · glm-5.3
    [mutagent:agent-package] {"type":"mutagent.agent.registration.v1",…,"status":"verified",…}
    Total: **4164 cents ($41.64)** — catalog `catalog-v1`.
    …
    Receipt word: cobalt-orchard
    ```
  </Step>

  <Step title="Change the agent and deploy revision v2">
    Change the discount in `invoice/skills/invoice-pricing/policy.json` from `7` to `10`:

    ```json invoice/skills/invoice-pricing/policy.json theme={null}
    {
      "discountPercent": 10,
      "taxBasisPoints": 825,
      "receiptWord": "cobalt-orchard"
    }
    ```

    Check, then deploy again:

    ```bash theme={null}
    mutagent agent check invoice/agent.md
    mutagent agent deploy invoice/agent.md --env prod
    ```

    The content changed, so `deploy` stores revision `v2` and makes it active in `prod`:

    ```text theme={null}
    ┌─ ✓ Agent deploy: active ──────────────────────────────────────────┐
    │                                                                   │
    │   slug            invoice-pricing                                 │
    │   revision        v2                                              │
    │   environment     prod                                            │
    │   activeRevision  v2                                              │
    │   …                                                               │
    └────────────────────────────────────────────────────────────────────┘
    Managed agent invoice-pricing v2 is active in Environment "prod".
    ```

    Run the same task:

    ```bash theme={null}
    mutagent helix agent @invoice-pricing --env prod -p "Price three widget units."
    ```

    The receipt shows `"revision":2`. The total is now `4030` cents: subtotal 4137, discount 414,
    tax 307.

    * Deploying unchanged content does not create a revision. It reuses the existing one.
    * A session that is still running keeps the revision it started with.
  </Step>

  <Step title="Roll back to v1">
    Make `v1` the active revision in `prod` again:

    ```bash theme={null}
    mutagent agent activate invoice-pricing --revision v1 --env prod
    ```

    ```text theme={null}
    ┌─ ✓ Agent activate: active ────────────────────────────────────────┐
    │                                                                   │
    │   slug            invoice-pricing                                 │
    │   revision        v1                                              │
    │   environment     prod                                            │
    │   activeRevision  v1                                              │
    │   status          active                                          │
    │   activated       true                                            │
    │   enabled         true                                            │
    │   operationId     op_…                                            │
    │                                                                   │
    │ ─────────────────────────────────────────────────────────────────│
    │                                                                   │
    │   operation       <operation link>                                │
    │                                                                   │
    │ ─────────────────────────────────────────────────────────────────│
    │                                                                   │
    │   Next                                                            │
    │   → mutagent agent inspect invoice-pricing --env prod --json      │
    │   → mutagent helix agent @invoice-pricing --env prod -p "<task>"  │
    │                                                                   │
    └────────────────────────────────────────────────────────────────────┘
    Managed agent invoice-pricing v1 is active in Environment "prod".
    ```

    **Success:** exit code 0, and with `--json` the result has `"revision": 1` and
    `"activeRevision": 1`.

    `activate` checks the model and the Environment again, as `deploy` does. New runs in `prod` use
    `v1` and return `4164` cents. Revision `v2` still exists:

    * `mutagent helix agent @invoice-pricing:v2 --env prod -p "…"` runs `v2` without activating it.
    * `mutagent agent inspect invoice-pricing --env prod --json` lists both revisions. In its
      `deployment`, `activeRevision` is `1`.
    * To go forward again, run `mutagent agent activate invoice-pricing --revision v2 --env prod`.
  </Step>
</Steps>

## If it fails

With `--json`, a failure is an object with `"success": false`, a `code` and a `suggestedAction`.
Branch on the code. [Errors and exit codes](/cli/errors) has the full list.

| Code (exit code) | Command | Fix |
| - | - | - |
| `AUTH_REQUIRED`, `WORKSPACE_REQUIRED` (3) | `deploy`, `activate`, `env`, `helix agent` | Sign in ([login](/cli/commands/login)), then `mutagent workspaces use <name>`. `check`, `pack` and `run` need no sign-in. |
| `AUTH_EXPIRED`, `INVALID_API_KEY` (2) | Any command that calls the platform | Sign in again, or set a valid `MUTAGENT_API_KEY`. |
| `BUN_NOT_FOUND`, `BUN_VERSION` (1) | `check`, `pack`, `run`, `deploy` | Install Bun 1.3.14, or set `MUTAGENT_BUN_BIN` to it. |
| A check diagnostic, such as `SOURCE_NOT_FOUND` (1) | `check`, `pack`, `run`, `deploy` | Fix the file the diagnostic names. See [Common refusals](/platform/managed-agents/tools-and-skills#common-refusals). |
| `AGENT_LOCAL_START_FAILED` (1) | `run` | Helix is not on this machine: `mutagent install helix`, or set `MUTAGENT_HELIX_BIN`. |
| `status` `failed` (non-zero) | `run` | Read `diagnostics` in the `--json` result. `No API key found for <provider>` means the local key is missing. |
| `MODEL_NOT_IN_LIST` (1) | `deploy`, `activate` | Set `model` in `agent.md` to an id from `mutagent helix models`, then deploy again. |
| `NO_PROVIDER_CONFIGURED` (1) | `deploy`, `activate` | The workspace has no LLM provider for that model. [Add one](/platform/providers/setup). |
| `ENVIRONMENT_NOT_FOUND` (1) | `deploy`, `activate` | Create it: `mutagent env set prod INVOICE_CURRENCY=USD`. |
| A network error or 5xx (1) | `deploy`, `activate` | Retry with the same `--idempotency-key` the error names. A new key is a new request. |
| `MANAGED_AGENT_SLOT_RETIRED` | `helix agent` | The slot was retired. `mutagent agent activate invoice-pricing --revision v1 --env prod` enables it again. |

## What you built

| Step | Command | Result |
| - | - | - |
| Validate | `mutagent agent check invoice/agent.md` | The package builds. Nothing is sent. |
| Try | `mutagent agent run invoice/agent.md "<task>"` | The task runs with Helix on your machine. |
| Ship | `mutagent agent deploy invoice/agent.md --env prod` | A revision, active in the `prod` slot. |
| Use | `mutagent helix agent @invoice-pricing --env prod -p "<task>"` | A session on Helix Cloud, with an `hs1_` reference. |
| Watch | `mutagent helix session ls`, `session attach <reference>` | The session list and its output. |
| Change | Edit, then `deploy` again | The next revision, active in the slot. |
| Undo | `mutagent agent activate invoice-pricing --revision v1 --env prod` | The earlier revision, active again. |

<CardGroup cols={2}>
  <Card title="Tools, skills and files" icon="wrench" href="/platform/managed-agents/tools-and-skills">
    Write more tools, use built-in tools, add skills, files and secrets.
  </Card>

  <Card title="Deployment" icon="arrows-rotate" href="/platform/managed-agents/deployment">
    Deploy, activate, run, retire and archive, with what each step checks.
  </Card>

  <Card title="agent.md reference" icon="file-code" href="/platform/managed-agents/agent-md">
    Every field and every rule.
  </Card>

  <Card title="Sessions" icon="comments" href="/helix/cloud/sessions">
    Attach to, send to, signal and checkpoint a session.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.