Skip to main content
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.
This page shows how to give a managed agent its own tools, skills and files. Every sample comes from the invoice-pricing agent that the agent.md reference shows in full. To build that agent step by step, see the Quickstart. A managed agent gets only what agent.md declares under harness::

The folder you start from

package.json has no dependencies:
package.json
  • Only paths that agent.md declares are packaged. Other files in the folder are ignored.
  • Every path in agent.md is relative to the folder.
  • package.json must not list dependencies, devDependencies, optionalDependencies or peerDependencies. Third-party npm packages are not installed.

Write a tool

A tool is a TypeScript or JavaScript file that exports one tool definition. The compiler bundles it into the package and Helix registers it when the agent starts. You do not write a Helix extension.

The import

  • defineTool takes the tool definition and returns it unchanged. It types the definition.
  • Type builds the parameter schema. It is the TypeBox builder, so Type.Object, Type.String, Type.Integer, Type.Optional and the other TypeBox functions work.
  • You do not install @mutagent/agents. mutagent agent check, run, pack and deploy supply it when they bundle the tool. An editor without the package reports the import as unresolved; the commands still build the tool.

The definition

execute receives five arguments: context holds:

What execute returns

  • content is a list of text parts. The model reads them as the tool’s result.
  • details is optional. It is stored with the tool result in the session’s events, so you can read structured data there. Put anything the model must read into content.

How errors reach the agent

The invoice tool throws for an SKU the catalog does not have:
With the task “Call calculate_invoice with sku sprocket …”, the tool result is Unknown product: sprocket, and the model reports that the SKU is not in the catalog.

What a tool module can import

check reads the imports without running any tool code.

A tool with input

tools/calculate-invoice.ts takes four fields. additionalProperties: false refuses any other field.
tools/calculate-invoice.ts
The model sends JSON that matches the schema:

A tool with no input

tools/list-products.ts takes no input. Its schema is an empty object. It is a named export, so agent.md names the export.
tools/list-products.ts
The model calls it with {}. The result is:

Register the tools

agent.md
What name does:
  • It is the name the model calls, and the name in the agent’s allowed tools.
  • It must equal the name inside defineTool. check does not compare them. When the agent starts, a different name stops the run.
  • It must be unique across modules (DUPLICATE_TOOL) and must not also be in harness.tools.builtin (TOOL_COLLISION).

Built-in tools

harness.tools.builtin lists the Helix built-in tools the agent gets. The agent gets no other built-in tool.
  • Each entry is a Helix built-in tool name. check does not validate the names.
  • These names start on a managed agent: read, bash, edit, write, grep, find and ls.
  • A name Helix does not start passes check and stops the run when the agent starts: the active tools differ from the declared ones. See The registration receipt.
  • A name in the top-level disallowed_tools is removed from the list.
When to use them: Grant the fewest tools the task needs. For work on your own data, write a tool module: it runs your code and returns only what you choose.

Write a skill

A skill is a folder with a SKILL.md file and the files it uses. The model reads the skill when the task matches its description.
skills/invoice-pricing/SKILL.md
skills/invoice-pricing/policy.json

SKILL.md frontmatter

Helix reads these fields: The body after the frontmatter is the skill’s instructions. Write them for the model: what to read, which tool to call, and what to report.

Files next to SKILL.md

  • Every file in the skill folder is packaged, except node_modules and .git folders.
  • The model reads them with read. Paths written in SKILL.md are relative to the skill folder.
  • A tool cannot find a skill’s files through context. Data a tool reads goes in harness.files.

How the agent uses a skill

  1. When the agent starts, Helix loads each folder in harness.skills.
  2. The model’s instructions list each skill’s name, description and the location of its SKILL.md.
  3. When a task matches a description, the model reads SKILL.md with read, then the files it names.
  4. A task that starts with /skill:<name> loads that skill’s instructions directly, including a skill with disable-model-invocation: true.
The model decides when to read a skill. To make a skill mandatory, say so in the body of agent.md, as the invoice agent does: “Every invoice request must follow the invoice-pricing skill.”

Register the skill

agent.md
  • Each path is a folder (SOURCE_NOT_DIRECTORY) that contains a SKILL.md (SKILL_MANIFEST).
  • read must be in harness.tools.builtin (SKILL_REQUIRES_READ).
  • A path that does not start with skills/ is placed under skills/ in the package.

Files

harness.files packages data the agent’s tools read.
agent.md
assets/catalog.json
  • Each path is a file or a folder. A folder is packaged with every file in it, except node_modules and .git folders.
  • The files are placed under files/ in the package. context.paths.assetRoot is that folder, on your machine and on Helix Cloud.
  • A tool reads a file at join(context.paths.assetRoot, "<declared path>"): join(context.paths.assetRoot, "assets/catalog.json").
  • A declared path that already starts with files/ is not placed under files/ again. Read files/catalog.json at join(context.paths.assetRoot, "catalog.json").
  • Never read a packaged file through a path on your machine. The package runs in a temporary folder locally and in a sandbox on Helix Cloud.
Credential-like files, such as .env, .mutagentrc, *.pem or *.key, are refused (CREDENTIAL_PATH). Put secrets in an Environment.

Secrets

harness.bindings.secrets declares the secret names the agent’s tools read through context.bindings.
agent.md
What happens today: The platform does not yet add declared bindings to the sandbox by name. To give a tool a secret now:
  1. Store it in an Environment: mutagent env set prod --secret PRICING_API_TOKEN=<token>.
  2. Deploy and run the agent with --env prod. The Environment’s variables and secrets are environment variables in the sandbox.
  3. Read it in the tool with process.env.PRICING_API_TOKEN.
In mutagent agent run, Helix gets the environment variables of your shell, so process.env reads your local values. See Environments.

The local loop

Check and run the agent on your machine before you deploy it. Neither needs a sign-in. Both need Bun 1.3.14, on PATH or named by MUTAGENT_BUN_BIN. run also needs Helix installed (mutagent install helix, or MUTAGENT_HELIX_BIN for another binary) and the API key of the LLM provider in model, in your local Helix login or your environment variables.

mutagent agent check

check compiles the folder and applies every rule. It sends no request, makes no model call and runs no tool code. A valid folder prints the digests, the package manifest and the launch settings:

mutagent agent run

run compiles the folder, unpacks the package into a temporary folder, and runs the task with Helix on your machine. It creates nothing in the workspace. It prints a card, then the answer:
The answer is the model’s text, so its wording changes between runs. The numbers come from the tool.
  • The command exits with the run’s exit code: 0 when status is completed.
  • A failed run prints the card with status failed and no reason. Run it again with --json and read diagnostics. For example, a missing model key reads No API key found for zai.
  • --json also prints registration (the registration receipt) and messages, which hold every tool call and tool result.

Common refusals

Without --json, the CLI prints the message. With --json, it also prints code and diagnostics, which name the file. The full list of check rules is in the agent.md reference.

Pack and deploy

  • pack writes the package archive outside the folder. Nothing is uploaded. It prints a card with the artifact digest; --json prints the source, artifact and archive digests. You do not need pack to deploy.
  • deploy builds the same package, uploads it, and activates the revision in the slot. It checks the model, the Environment, the secret bindings and the sandbox provider. See Deployment.

The registration receipt

When the agent starts, the bundled tools register and print one registration receipt. On Helix Cloud it appears in the session’s output:
On Helix Cloud, the platform waits up to 15 seconds for the receipt and checks that:
  • status is verified.
  • artifactDigest and revisionId are the revision’s.
  • activeTools and expectedTools equal harness.tools.builtin plus the module names.
  • registeredTools equals the module names.
  • The bindings are verified and match the declared required and optional names.
If a check fails, the run is refused with 422 AGENT_REGISTRATION_POLICY_MISMATCH, or with 422 AGENT_REGISTRATION_RECEIPT_TIMEOUT when no receipt arrives in 15 seconds. The sandbox the run started is stopped. mutagent agent run applies the same checks on your machine and fails with the codes in Common refusals.

Quickstart

From an empty folder to a deployed agent, a new revision and a rollback.

agent.md reference

Every field, every rule and the package format.