Ctrl K
ComunidadGuías…

docs/custom-engines.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Bring your own engine

Two zero-code ways to run OpenMausBot bots on an engine the app doesn't ship.
Both live in `~/.openmausbot/config.json` under `"instances"`; restart the app
after editing (instance entries are read at boot).

## Provider icons

Each instance shows its driver's mark. An OpenAI-compatible server shows the
mark of whoever runs it, read from the host in its address: `api.deepseek.com`
shows DeepSeek, `<resource>.openai.azure.com` Microsoft Azure,
`dashscope-intl.aliyuncs.com` or `<workspace>.<region>.maas.aliyuncs.com` Qwen,
`openrouter.ai` OpenRouter, and so on
(the list is `SERVER_HOSTS` in `server/provider-icon.ts`). A server without a
mark of its own, such as Groq, Together, Ollama or LM Studio, keeps the default.

An icon stored on the instance still wins: add
`"icon": { "kind": "preset", "preset": "azure" }` alongside `driver` and
`displayName`. The presets are OpenAI, Anthropic, Google Gemini, Microsoft
Azure, Amazon Bedrock (AWS), xAI, DeepSeek, Meta, Mistral AI, Qwen, Moonshot
AI, Cohere and OpenRouter. Custom images saved before v0.1.102 keep rendering;
the app never fetches remote icon URLs.

## Any ACP agent (a CLI you spawn)

If an agent CLI speaks [ACP](https://agentclientprotocol.com) over stdio —
`fx acp`, a Zed-style agent server, your own wrapper — point a `customAcp`
instance at it:

```json
{
  "instances": {
    "my-agent": {
      "driver": "customAcp",
      "displayName": "My Agent",
      "environment": { "MY_AGENT_TOKEN": "…" },
      "config": { "cli": "my-agent acp" }
    }
  }
}
```

- **`config.cli`** is the whole command, args included (`"npx -y some-agent acp"`
  works). You can also set it from the app: Settings → Engines → *Set CLI…* on
  the instance's row. An instance without a command shows up with exactly that
  hint instead of failing at first message.
- **Sign in first.** The driver has no auth flow of its own — run the CLI once
  in a terminal and log in there; OpenMausBot spawns it with your login intact.
- **Choose models per bot.** Open the bot's model picker and use **Re-detect**
  to load the models advertised by the agent. Select a model and, when offered,
  its thinking level. Bot defaults and individual conversation overrides are
  saved independently. **Agent default** leaves the native session's model
  unchanged. An agent that does not advertise models still has this option.
- **Choices come from the agent.** Discovery starts a temporary ACP session
  without sending a prompt. Only confirmed, model-specific thinking options
  are shown; a failed refresh keeps the last successful catalog. ZCode,
  CodeBuddy, Qoder and other custom ACP engines use the same mechanism.
- **`environment`** is passed to the CLI child. Foreign provider keys
  (XAI_API_KEY, OPENAI_COMPAT_API_KEY, …) are deliberately stripped so a
  custom CLI can never bill against another engine's login.
- **Permissions** ride ACP's own `session/request_permission` — if your agent
  asks, the request becomes a normal approval card in chat.
- Multiple instances are fine — one per agent.

### Example: Mistral Vibe

[Mistral Vibe](https://github.com/mistralai/mistral-vibe) ships an ACP entry
point, `vibe-acp`, so it runs as a custom ACP engine with your Mistral account's
own sign-in, not a Mistral API key saved in OpenMausBot.

1. Install it: `uv tool install mistral-vibe` (or `pipx install mistral-vibe`).
   This puts `vibe` and `vibe-acp` in `~/.local/bin`.
2. Sign in once from a terminal: run `vibe --setup` and sign in with your
   Mistral account (Vibe offers a browser sign-in through Mistral AI Studio, or
   an API key). Vibe uses the first credential it finds in the shell
   environment, `~/.vibe/.env`, or the OS keyring, and `vibe-acp` uses it too.
3. Add the instance and restart OpenMausBot:

   ```json
   {
     "instances": {
       "mistral-vibe": {
         "driver": "customAcp",
         "displayName": "Mistral Vibe",
         "icon": { "kind": "preset", "preset": "mistral" },
         "config": { "cli": "/home/you/.local/bin/vibe-acp" }
       }
     }
   }
   ```

   Use the full path when `~/.local/bin` is not on the app's `PATH` (a desktop
   app started from the dock often doesn't have it).
4. Pick **Mistral Vibe** for a bot. Its model menu shows **Agent default**,
   which runs the model Vibe itself uses by default.

OpenMausBot never passes its own `MISTRAL_API_KEY` to the CLI, so turns use the
Vibe sign-in from step 2. Without it, the chat shows `Missing API key for
mistral provider`: sign in again from a terminal (step 2).

### Example: Command Code

[Command Code](https://commandcode.ai) has an ACP mode, `cmd acp`, so it runs as
a custom ACP engine with your own Command Code sign-in. (Checked with
`command-code` 1.88.2.)

1. Install it: `npm install -g command-code`. This puts `cmd` on your `PATH`;
   on Windows the command is `cmdc`, because `cmd` is the Windows command
   prompt.
2. Sign in once from a terminal: run `cmd login` (`cmdc login` on Windows).
   On a server without a browser, create an API key in Command Code Studio
   instead and put it in the instance's `environment` as
   `COMMAND_CODE_API_KEY`; OpenMausBot passes it to the CLI.
3. Add the instance and restart OpenMausBot:

   ```json
   {
     "instances": {
       "command-code": {
         "driver": "customAcp",
         "displayName": "Command Code",
         "config": { "cli": "cmd acp" }
       }
     }
   }
   ```

   Use `"cmdc acp"` on Windows, and the full path when the npm global folder
   is not on the app's `PATH`: `which cmd` on macOS or Linux, or
   `where.exe cmdc` on Windows.
4. Pick **Command Code** for a bot. Its model menu shows **Agent default**,
   which runs Command Code's own default model; **Re-detect** lists the models
   it advertises once you're signed in.

Without a sign-in the chat shows ``Not authenticated. Run `cmd login` in a
terminal first.``: sign in from a terminal (step 2). A wrong
`COMMAND_CODE_API_KEY` shows `401 error: Invalid 'Authorization' header or
token.`

## Any OpenAI-compatible endpoint (no process at all)

The built-in `openai-compat` driver supports multiple instances, so a local
vLLM/LM Studio/Ollama-openai endpoint or any hosted compatible API is one
entry:

```json
{
  "instances": {
    "my-endpoint": {
      "driver": "openai-compat",
      "displayName": "My Endpoint",
      "environment": { "MY_ENDPOINT_KEY": "sk-…" },
      "config": {
        "url": "http://127.0.0.1:1234/v1",
        "apiKeyEnv": "MY_ENDPOINT_KEY",
        "model": "my-model"
      }
    }
  }
}
```

- `apiKeyEnv` names which `environment` value carries the key, so several
  instances can hold different keys without colliding.
- The driver lists the endpoint's `/models` when it can and keeps your
  `model` as a custom option either way.
- OpenAI-compatible instances support structured tools and image input. With a
  model that accepts both, the harness can mount the approved host, Local VM,
  VPS, Boat cloud or built-in browser tools and return their screenshots to the model.
  The existing platform, computer-selection and approval checks still apply.
  Boat turns retain the selected API model in direct chats, rooms and cloud
  routines, as they do for every engine with computer tools.
- Set `config.tools` to `false` for a model without tool support. Image support
  also depends on the chosen model; the driver cannot add vision to a text-only
  model. See [tool verification](verification/openai-tools.md) for scope and tests.

### Example: Alibaba Cloud Model Studio (Qwen)

Use the `openai-compat` instance above with your Model Studio API key and a
model ID enabled for your account. Set `config.url` to the base URL from
your Model Studio workspace, including `/compatible-mode/v1`:

| Region | Base URL |
|---|---|
| Beijing | `https://<workspace-id>.cn-beijing.maas.aliyuncs.com/compatible-mode/v1` |
| Virginia | `https://<workspace-id>.us-east-1.maas.aliyuncs.com/compatible-mode/v1` |
| Singapore | `https://<workspace-id>.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1` |
| Tokyo | `https://<workspace-id>.ap-northeast-1.maas.aliyuncs.com/compatible-mode/v1` |

Replace `<workspace-id>` with your workspace ID. The API key must come from
the same region as the endpoint; a mismatch can return HTTP 401 even when
the key is valid. The older `dashscope.aliyuncs.com` and
`dashscope-intl.aliyuncs.com` addresses still work. Both address formats show
the Qwen mark; the mark identifies the service, not the selected model's
capabilities or account access.

See [Alibaba Cloud's OpenAI-compatible API guide](https://help.aliyun.com/zh/model-studio/compatibility-of-openai-with-dashscope)
for current addresses, model availability and region requirements.

## Notes

- `config.json` is written with mode 0600; values in `environment` are stored
  as plaintext in that file. Prefer keys scoped to the one engine.
- A typo'd `driver` or invalid `config` never breaks the app: the instance
  shows as unavailable with the reason, and the rest of the fleet loads.