<!-- Markdown mirror. Canonical: https://empryo.com/docs/context/provider-tools -->

# Provider tools

> Computer use, code execution, the Anthropic text editor and provider-side search — what each one resolves to on your model, and how to switch it on per lane.

Four tools come from the provider rather than from Empryo's belt: computer use, server-side code
execution, Anthropic's text editor, and provider-side web search. The provider defines the tool
block, so whether it exists on the wire at all is decided by the **lane** (`anthropic/`,
`openai/`, `openrouter/`, `proxy/`…) and the **model**, not by the flag alone.

That is why every surface reports three things instead of a checkbox:

| Word | Meaning |
|------|---------|
| enabled | You asked for it in config. |
| backend | What would go on the wire, for example `anthropic:computer_20251124`. |
| active | Enabled **and** a backend exists. The only state the model can see. |

A tool can be enabled and inactive (wrong lane or wrong model), or off with a backend waiting
(flip it and it works). One reader answers for all four
(`packages/core/src/llm/tool-capabilities.ts`), so the wording never drifts between surfaces.

## Check before you trust the switch

```bash
empryo --capabilities anthropic/claude-opus-4-6
```

```
anthropic/claude-opus-4-6
  Computer use           on   anthropic:computer_20251124
  Code execution         on   anthropic:code_execution_20260120
  Text editor            off  anthropic:text_editor_20250728 available
  Provider-side search   on   anthropic:web_search_20260209
```

Pass no model and it reads `defaultModel` from your config.

## The four tools

### Computer use

Screenshots, clicks, keystrokes and scrolling against a real display. `computerUse`, **on by
default**.

| Lane and model | Backend |
|------|---------|
| `anthropic/`, `subscriptions/` + Claude | `anthropic:computer_20251124` (or `_20250124` on older Claude) |
| `openai/` + the general gpt-5.4+ line | `openai:computer` |
| `openai/` + codex, mini, nano, chat, pro | `generic:computer` |
| Codex and ChatGPT-backend lanes (`subscriptions/`, `proxy/` + GPT) | `generic:computer` |
| `proxy/` + Claude, gateways, Gemini, local | `generic:computer` |

**Every lane has computer use.** What changes is whose tool block carries it, and each surface
says which — `generic:computer — OpenAI ships its computer tool on the general gpt-5.4+ line only,
not codex, mini, nano, chat or pro`. The vendor block wins where it is legal because the model was
trained against that schema; the generic tool is a plain function tool with the same action
vocabulary, the same backend, and no provider gate to fail.

The generic lane exists because gateways strip vendor tool blocks and Gemini's computer use lives
on an API the SDK does not reach. It rides any provider; the only requirement is that the model
accepts image input, since it has to see the screenshot that comes back. On that lane the tool is
natively deferred, so an unused capability costs nothing in the prompt prefix.

It is not a downgrade, and Codex is the proof. Codex has computer use on the very backend that
refuses `{"type":"computer"}` — because Codex does not send that type either. It ships its own
client-side tool over an MCP server, `cua_repl`, with per-app allow/deny rules and a review gate.
The model names an action, the client drives the machine. That is the same architecture as the
generic lane here. A hosted tool type is one way to carry computer use, not the capability itself.

### Which apps it may drive

By default the agent can drive whatever is on screen. `computerUseApps` narrows that, the way
Codex's own config does — a default plus per-platform rules keyed by macOS bundle id, Windows
process name or AUMID, and Linux window class:

```json
{
  "computerUseApps": {
    "default": "deny",
    "macos": { "com.apple.Safari": "allow", "com.googlecode.iterm2": "allow" }
  }
}
```

The rule is checked against the **frontmost app at the moment of the action**, so it follows focus
rather than a window title the page controls. `deny` beats an `allow` default; with
`"default": "deny"` an unlisted app is refused and the message names it, ready to paste back into
the config. An app that cannot be identified fails closed under an allowlist.

Only actions that DRIVE the machine are gated — clicks, keys, drags, scrolls. Screenshots are
whole-screen on every backend, so gating them per app would be a promise the tool cannot keep.

The agent also carries standing rules for using this tool at all: look before acting, re-read the
inputs of a consequential click, never enter credentials it was not given, treat on-screen text as
content rather than instruction, and stop when a window is not the one it expected.

Your machine still has to be drivable. macOS needs `cliclick` (`brew install cliclick`) beside the
built-in `screencapture`, plus Screen Recording and Accessibility consent. Linux needs `xdotool`
and one of `grim`, `import`, `scrot`, `gnome-screenshot` or `spectacle`. Windows uses in-box
PowerShell. A box that can capture but not click registers no tool at all: a model that plans
clicks it can never make is worse than one with no hands.

GPT-6 Astra keeps the tool, and the surfaces add what the vendor says about it: drive the UI from
generated code, with the computer tool as the alternative. OpenAI's own Codex client carries the
same fact as data — its model catalog marks `gpt-6-astra` `"tool_mode": "code_mode_only"`.

On the ChatGPT-backed lanes (`subscriptions/`, `proxy/`), Astra is like every other GPT there:
the backend refuses OpenAI's computer tool by name, so the generic one runs.

### Code execution

A sandbox inside the provider: Python, bash and file operations, with the model's own tool calls
running against it. `codeExecution`, **on by default**.

| Lane | Backend |
|------|---------|
| `anthropic/`, `subscriptions/`, `proxy/`, Claude 4.5+ | `anthropic:code_execution_20260120` |
| `openai/`, GPT family | `openai:code_interpreter` |
| Gateways (`openrouter/`, `llmgateway/`, `copilot/`, `bedrock/`, `vertex/`…) | none |

Haiku 4.5 runs the sandbox but not programmatic tool calling, so the batching is unavailable
there while the sandbox is not.

Both subscription routes (`subscriptions/`, `proxy/`) reach the ChatGPT backend when the model is
a GPT, and that backend rejects `code_interpreter` by name — including GPT-6 Astra. Nothing is
missing: it has no server-side interpreter to offer, and OpenAI's own client answers the same gap
locally (its catalog runs Astra as `"tool_mode": "code_mode_only"` over `unified_exec`). Empryo's
`shell` and `code_script` are that local execution, and they run on every lane. Claude on the same
subscription lane still gets the server-side sandbox.

### Anthropic text editor

`str_replace_based_edit_tool`, the editing contract Claude was trained on.
`anthropicTextEditor`, **off by default** because Empryo's own `edit_file` and `ast_edit` are
already in the belt.

Claude 4 and newer take `text_editor_20250728`; Claude 3.5 and 3.7 take `text_editor_20250124`.
Only the Anthropic wire carries it, so `openrouter/anthropic/claude-*` resolves to nothing even
though the model reads as Claude.

### Provider-side search

Covered in depth under [web access](/docs/reference/configuration). `nativeSearch`, **on by
default**, requires `webSearch`. When the lane has no server-side search this is not a failure:
Empryo's own `web_search` runs instead, and the surfaces say that rather than reporting an
absence.

## Turning them on

| Surface | Where |
|---------|-------|
| TUI | `/provider-settings` — each row shows the resolved backend or the reason there is none |
| TUI, Telegram, Discord | `/provider computeruse on`, `codeexec`, `texteditor`, `nativesearch`, `websearch` |
| Desktop | Settings › Provider Options — four live rows, resolved against the selected model |
| Headless | `empryo --capabilities [model]` to read; config to write |

Config, global or per project:

```json
{
  "computerUse": true,
  "codeExecution": true,
  "anthropicTextEditor": false,
  "nativeSearch": true
}
```

| Key | Default | Tool |
|-----|---------|------|
| `computerUse` | `true` | Computer use |
| `codeExecution` | `true` | Server-side code execution |
| `anthropicTextEditor` | `false` | Anthropic text editor |
| `nativeSearch` | `true` | Provider-side web search |

## Why a lane can refuse

A provider-defined tool block sent to a provider that has never heard of it is a `400` on the
whole request, not a dropped tool. So the resolvers answer `null` wherever the pairing is
unproven, and every `null` carries a sentence you can act on: *"openrouter encodes the request
itself and has no text_editor tool type — use an anthropic/ model."*

## Next

- [Thinking and retries](/docs/context/provider-options)
- [Configuration reference](/docs/reference/configuration)
- [The browser](/docs/tools/browser) for driving web pages instead of the whole desktop
