# Factory Droid

Factory Droid is a terminal coding agent. It reads custom models from `~/.factory/settings.json` and does not get the model list itself. The block in step 1 reads the live model list and adds each text model as a custom model.

## Start with the Liquid CLI

The [Liquid CLI](https://inference.ai.exchange/docs/cli.md) can start Droid with your key. Droid keeps its settings in a file, so set it up one time first.

1. Run `liquid connect factory-droid`. It prints the setup below with your model filled in.
2. Start Droid with `liquid factory-droid`.

```bash
curl -fsSL https://inference.ai.exchange/cli/install.sh | bash
liquid login
liquid connect factory-droid
liquid factory-droid
```

## Before you start

- A workspace with a balance and a `spend` key. See [API keys](https://inference.ai.exchange/docs/keys.md).
- A Factory account. Droid asks you to sign in to Factory before it starts, even when you use only custom models. Your Liquid key still pays for each request.
- `jq`.
- Droid installed:

```bash
# installer
curl -fsSL https://app.factory.ai/cli | sh

# or with npm
npm install -g droid
```

## 1. Write the custom models

This block:

- Reads the text models of the book. Droid sends each model to the chat endpoint, so it cannot use an image, speech or video model.
- Keeps your other settings and your other custom models. It replaces only the models whose name starts with `Liquid: `.
- Writes `maxOutputTokens` from each model, because some offers register a lower limit than Droid asks for. The limit is at most 32,768, because the price cap of each request must hold the full limit.
- Sets the provider to `generic-chat-completion-api`, which is the OpenAI Chat Completions format.

`apiKey` is the literal `${LIQUID_API_KEY}`, which Droid expands at run time. The block sends the key on the models request, so the list includes your presets.

```bash
export LIQUID_API_KEY=sk-liquid-...
mkdir -p ~/.factory && touch ~/.factory/settings.json
curl -fsSL "https://router.inference.ai.exchange/v1/models?kind=text" -H "Authorization: Bearer $LIQUID_API_KEY" | jq --slurpfile cur ~/.factory/settings.json '
  .data as $book | ($cur[0] // {}) | .customModels = (
    [(.customModels // [])[] | select((.displayName // "") | startswith("Liquid: ") | not)] +
    [$book[] | {
      model: .id,
      displayName: ("Liquid: " + .id),
      baseUrl: "https://router.inference.ai.exchange/v1",
      apiKey: "${LIQUID_API_KEY}",
      provider: "generic-chat-completion-api",
      maxOutputTokens: ([.max_tokens // 16384, 32768] | min),
      noImageSupport: ((.liquid_supported_parameters // []) | index("input.image") == null),
      extraHeaders: { "X-Title": "Factory Droid", "x-liquid-cap-usd": "1.00" }
    }]
  )' > ~/.factory/settings.json.new && mv ~/.factory/settings.json.new ~/.factory/settings.json
```

Run the block again when the book changes.

## 2. Run it

```bash
droid
```

In a session, run `/model` and choose a model whose name starts with `Liquid: `. To get the current names, see the **Market** page or use `GET /v1/models`. See [Market data](https://inference.ai.exchange/docs/market.md). The exchange refuses a name that is not on the book. It never uses another model.

## Control the cost

Each model sends `x-liquid-cap-usd` in `extraHeaders`. To change it, edit the header in `~/.factory/settings.json`.

- The cap applies to each request, not the session.
- The block resets this value each time you run it.
- The exchange fixes the cap before the first token and returns it in the `x-liquid-cap-usd` response header.

To limit the total spend, set a spending limit on the key. See [API keys](https://inference.ai.exchange/docs/keys.md) and [Purchasing rules](https://inference.ai.exchange/docs/rules.md).

## Troubleshooting

| Symptom                                               | Cause and fix                                                                                                                          |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Droid shows "Please login with your Factory account". | Droid needs a Factory sign-in before it starts. Choose **Login**, finish the sign-in, then run `/model`. Liquid cannot skip this step. |
| The model is not listed.                              | The book changed after the file was written. Run the block again.                                                                      |
| `401`                                                 | The key variable is not set in the shell that starts Droid. Export `LIQUID_API_KEY` and start Droid again.                             |
| `output_bound_unsupported`                            | `maxOutputTokens` is higher than the offer allows. Run the block again so each model takes its limit from the book.                    |
| `jq` reports a parse error                            | `settings.json` contains comments, which JSON does not allow. Edit the `customModels` entries by hand, or remove them.                 |

## Next steps

- [Pi](https://inference.ai.exchange/docs/connect-pi.md): the same idea for another terminal agent.
- [API keys](https://inference.ai.exchange/docs/keys.md): scopes and spending limits.
- [Purchasing rules](https://inference.ai.exchange/docs/rules.md): cost caps and service floors.
