# AgentSpec schema
URL: /docs/cli/registry/schema

Complete field reference for the AgentSpec JSON fetched by alineo add and run by alineo's Alineo.start().



An agent spec is a JSON object — the same `AgentSpec` type `alineo` exports. Only `name` and `harness` are required; `alineo add` and `Alineo.start()` both use the same [`validateAgentSpec()`](https://github.com/DrejT/alineo/blob/main/packages/agent/src/schema.ts) function.

## Full example [#full-example]

```json
{
  "name": "code-reviewer",
  "title": "Code Reviewer Agent",
  "description": "A Node.js sandbox pre-loaded with TypeScript tooling for code review tasks.",
  "author": "acme <https://github.com/acme>",
  "categories": ["agent", "typescript"],

  "harness": "pi",
  "provider": "google",
  "model": "gemini-flash-latest",
  "packages": ["git"],
  "env": { "GEMINI_API_KEY": "${GEMINI_API_KEY}" },
  "resources": { "cpu": "500m", "memory": "512Mi" },

  "setup": [
    { "name": "install tools", "run": "npm install -g typescript eslint" },
    { "name": "make workspace", "run": "mkdir -p /workspace" }
  ],

  "registryDependencies": ["https://example.com/agents/base-node.json"]
}
```

There's no `image` field — every spec runs in a fixed `node:22` sandbox — and no `ports` field.

## Fields [#fields]

### Required [#required]

| Field     | Type     | Description                                                                                                      |
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
| `name`    | `string` | Unique identifier. Used as the saved filename (`<name>.json`) and the sandbox session name.                      |
| `harness` | `"pi"`   | Agent-loop driver to run inside the sandbox. Currently only `"pi"` is accepted — anything else fails validation. |

### Optional [#optional]

| Field                  | Type                                            | Description                                                                                                                                                                                                                                                                                                  |
| ---------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `title`                | `string`                                        | Human-readable display name.                                                                                                                                                                                                                                                                                 |
| `description`          | `string`                                        | Shown by `alineo list`, falling back from `title` if `description` is unset.                                                                                                                                                                                                                                 |
| `author`               | `string`                                        | Author name and optional URL.                                                                                                                                                                                                                                                                                |
| `categories`           | `string[]`                                      | Tags for discovery. Not currently used by any command — informational only.                                                                                                                                                                                                                                  |
| `harnessVersion`       | `string`                                        | npm version specifier for the Pi CLI (e.g. `"1.2.3"`, `"^1.2.0"`, or a dist-tag like `"latest"`). Passed to `npm install -g @earendil-works/pi-coding-agent@<harnessVersion>`. Omit to install whatever npm resolves as latest. Included in the setup-hash cache key, so changing it forces a fresh install. |
| `provider`             | `string`                                        | AI provider passed to Pi via `--provider`. Omit for a direct Google API key (Pi's default).                                                                                                                                                                                                                  |
| `model`                | `string`                                        | Model ID passed to Pi via `--model`.                                                                                                                                                                                                                                                                         |
| `packages`             | `string[]`                                      | APT packages installed before the CLI starts. `nodejs`/`nodejs_22` are silently ignored (the base image already has Node).                                                                                                                                                                                   |
| `env`                  | `Record<string, string>`                        | Environment variables available inside the sandbox. Values may reference host env vars: `"${MY_API_KEY}"` → `process.env.MY_API_KEY` at load time.                                                                                                                                                           |
| `resources`            | `{ cpu: string; memory: string; gpu?: string }` | Falls back to `defaults.resources` in `alineo.config.json` if omitted (`1000m` / `1Gi` by default).                                                                                                                                                                                                          |
| `metadata`             | `Record<string, string>`                        | Not read anywhere in `alineo`; has no effect on the sandbox.                                                                                                                                                                                                                                                 |
| `registryDependencies` | `string[]`                                      | URLs of other agent specs. `alineo add` fetches and saves each one first, depth-first, before saving this spec. No cycle detection.                                                                                                                                                                          |
| `setup`                | `SetupStep[]`                                   | Steps run inside the sandbox after CLI install, before the checkpoint. Each is `{ name, run, cwd? }` — `run` is a bash command, `cwd` optionally changes directory first. Any change here invalidates the setup-hash cache, forcing a fresh install+setup on the next `Alineo.start()`.                      |

## Validation [#validation]

Both `alineo add` and `Alineo.start()` call the same `validateAgentSpec()`. It checks four things:

* `name` is present and is a string.
* `harness` is exactly `"pi"`.
* If `spawnDepth` is set, it must be a non-negative integer.
* If `maxAgents` is set, it must be a non-negative integer.

Every other field is unchecked at validation time — a malformed `resources`, `setup` entry, or `env` value won't be caught until it's actually used (typically inside the sandbox, at load/run time).
