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

# Register your agent

> Write a descriptor for your AI agent and register it with firedrill register.

A **descriptor** tells Firedrill what your agent is made of: its services, how to talk to it, what state it keeps and which external services it calls. It holds names and hashes only. It never contains source code, file paths, commands or secret values.

## Register

```bash theme={null}
firedrill register --descriptor descriptor.json --name "Support agent"
```

The command prints the agent ID, the descriptor revision and a digest. Copy the digest into your [local plan](https://docs.firedrill.run/connect/local-plan.md) as `descriptor_sha256`. Nothing is uploaded or started.

To register a new revision of the same agent:

```bash theme={null}
firedrill register --descriptor descriptor.json --agent <agent-id> --expected-revision 1
```

`--expected-revision` is the revision you are replacing. Use `firedrill descriptors --agent <agent-id>` to list revisions.

## Example

An HTTP agent with no external dependencies:

```json descriptor.json theme={null}
{
  "schema": "firedrill.local-descriptor.v1",
  "source_roots": [
    { "alias": "app", "identity_sha256": "<root identity>" }
  ],
  "services": [
    {
      "alias": "agent",
      "root_alias": "app",
      "role": "agent",
      "depends_on": [],
      "configuration": [
        { "name": "OPENAI_API_KEY", "phase": "runtime", "secret": true, "required": true }
      ]
    }
  ],
  "entry_service": "agent",
  "driver": {
    "profile": "http.v1",
    "adapter_sha256": "<64 hex characters>",
    "authentication": "anonymous",
    "state_domains": ["proc"]
  },
  "state_domains": [
    {
      "alias": "proc",
      "service_alias": "agent",
      "kind": "process",
      "location": "local",
      "reset": "fresh-process",
      "concurrency": "independent",
      "hook_sha256": null
    }
  ],
  "dependencies": []
}
```

## Get the hashes

Two fields need hashes that you compute on your machine.

**`source_roots[].identity_sha256`** identifies a folder on your machine without sending its path. Run this in the folder:

```bash theme={null}
node -e 'const c=require("crypto"),f=require("fs");const p=f.realpathSync(process.argv[1]);const s=f.statSync(p,{bigint:true});console.log(c.createHash("sha256").update("firedrill.root-identity.v1\0").update(p).update("\0").update(`${s.dev}:${s.ino}`).digest("hex"))' .
```

The folder must exist and belong to you. Moving or recreating it changes the identity.

**`driver.adapter_sha256`** is the SHA-256 of a file:

| Driver | File to hash |
| - | - |
| `function-wrapper.v1` | The wrapper file. Firedrill checks it before every launch. |
| `playwright.v1` | The flow file. Firedrill checks it before every launch. |
| `http.v1`, `jsonl-process.v1`, `signed-http-event.v1` | Your agent's entry file. Any 64-character hex value is accepted. |

```bash theme={null}
shasum -a 256 wrapper.py
```

## Fields

All top-level fields are required. Extra fields are refused.

| Field | Description |
| - | - |
| `schema` | Always `firedrill.local-descriptor.v1`. |
| `source_roots` | The folders your agent runs from. Each has an `alias` and an `identity_sha256`. |
| `services` | Each process your agent needs. See below. |
| `entry_service` | The alias of the service that users talk to. |
| `driver` | How Firedrill talks to the entry service. See [Drivers](https://docs.firedrill.run/connect/drivers.md). |
| `state_domains` | The state your agent keeps and how it is reset between drills. |
| `dependencies` | External services your agent calls that Firedrill should simulate. |

Aliases use lowercase letters, digits, `_` and `-`, start with a letter and have at most 64 characters.

### Services

| Field | Description |
| - | - |
| `alias` | A name for the service. |
| `root_alias` | The source root it runs from. |
| `role` | `agent`, `frontend`, `worker`, `database`, `queue` or `service`. |
| `depends_on` | Aliases of services that must start first. Cycles are refused. |
| `configuration` | Environment variable names the service reads. Each has `name`, `phase` (`build`, `runtime` or `both`), `secret` and `required`. |

### Driver

| Field | Description |
| - | - |
| `profile` | `http.v1`, `jsonl-process.v1`, `function-wrapper.v1`, `playwright.v1` or `signed-http-event.v1`. |
| `adapter_sha256` | See [Get the hashes](#get-the-hashes). |
| `authentication` | `anonymous`, or `synthetic-session` when your agent needs a signed-in test user. |
| `state_domains` | Every state domain alias in the descriptor. |

### State domains

A state domain is a piece of state your agent keeps, such as a process, a database or a browser session. It tells Firedrill whether drills can run side by side.

| Field | Values |
| - | - |
| `kind` | `process`, `browser`, `files`, `database`, `vector`, `cache`, `queue`, `scheduler`, `session` |
| `location` | `local`, `cloud-disposable`, `observation-only` |
| `reset` | `fresh-process`, `fresh-session`, `approved-hook`, `unavailable` |
| `concurrency` | `independent` or `serial` |
| `hook_sha256` | The reset script's SHA-256 when `reset` is `approved-hook`, otherwise `null` |

Rules:

* `fresh-process` only resets a `process`. `fresh-session` only resets a `browser` or `session`.
* `observation-only` state must use `reset: unavailable`.
* State that cannot be reset must use `concurrency: serial`.
* If any state domain is `serial`, or there are none, drills run one at a time.

### Dependencies

| Field | Description |
| - | - |
| `alias` | A name for the dependency. The world uses the same alias. |
| `service_alias` | The service that calls it. |
| `protocol` | `http` or `mcp`. |
| `mode` | `synthetic` for a synthetic tool. |
| `operations` | The operations your agent uses, such as `messages.send`. |

See [Connect synthetic tools](https://docs.firedrill.run/connect/tools.md) for how calls reach the simulated service.

## Common errors

All descriptor errors use the code `local_descriptor_invalid`. The message says what to fix.

| Message | Fix |
| - | - |
| Remove credentials from declaration metadata. | A value looks like a secret. Keep only names in the descriptor. |
| Choose an entry service from the declared services. | Set `entry_service` to a service alias. |
| Startup dependencies contain a cycle. | Remove the loop in `depends_on`. |
| The driver must account for every declared state domain. | List every state domain alias in `driver.state_domains`. |
| State without a reset boundary requires serial execution. | Set `concurrency: serial`. |

> [card] [Write the local plan](https://docs.firedrill.run/connect/local-plan.md)
>
> Tell the CLI how to start your agent.

> [card] [Choose a driver](https://docs.firedrill.run/connect/drivers.md)
>
> HTTP, process, function, browser or webhook.


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