# Agents

URL: https://tuios.dev/docs/agents

> Track what coding agents in your panes are doing, get alerted when one needs you, and let agents drive TUIOS.

TUIOS keeps an agent state for every pane. When a pane runs a coding agent such as Claude Code, Codex or Gemini CLI, the state says whether it is working, waiting for you, or done. The state is drawn on the pane's title bar and in the rail, it can raise an alert, and scripts can read it and wait on it. Everything an agent waits on you for collects in the [Inbox](https://tuios.dev/docs/agent-inbox).

To keep only the multiplexer, turn every agent feature off with `[agents] enabled = false`. See [Turn Off Agent Features](https://tuios.dev/docs/agents-off).

**Try it live:** the [Agents track](https://tuios.dev/learn?t=agents) runs a pretend agent in your browser so you can watch its state change.

## States

| State         | Glyph | ASCII | Meaning                                                                           |
| ------------- | ----- | ----- | --------------------------------------------------------------------------------- |
| `none`        |       |       | Not an agent, or not reporting. The default                                       |
| `working`     | `●`   | `*`   | Working on a task                                                                 |
| `needs_input` | `▲`   | `!`   | Blocked, waiting for a person                                                     |
| `idle`        | `○`   | `o`   | Not working and not blocked                                                       |
| `done`        | `■`   | `#`   | Finished its task, and you have not looked at it yet. Once you have, it draws `○` |
| `errored`     | `×`   | `x`   | Stopped on an error                                                               |
| `unknown`     | `□`   | `?`   | An agent is there and nothing says what it is doing                               |

The glyphs are different shapes, not the same shape in different colours, so they still read in a monochrome screenshot. The ASCII column is what `--ascii-only` draws.

`needs_input` and `errored` are the two states where a person has to act. `get-agent-state` and `list-agents` report that as `needs_you: true`, so a script does not need to know which states mean it.

The state is held by the daemon, per pane. Every attached client sees it, and it survives a detach. It does not survive a daemon restart.

## Where it shows

- **Title bar:** the glyph sits in each pane's title.
- **Rail:** the agents section lists every agent pane, sorted by what each needs from you, with what it is doing or asking. Each session row carries the loudest state among its panes. See [Session Rail](https://tuios.dev/docs/session-rail#agent-rows).
- **Inbox:** Ctrl+B i lists every approval, question, error and finished turn waiting for you, in every session. See [Inbox and Review](https://tuios.dev/docs/agent-inbox).
- **Alerts:** a state change can raise a notification, a sound and a dock message. See [Alerts](https://tuios.dev/docs/agents#alerts).

## How TUIOS learns the state

Several sources can report on a pane. From most to least trusted:

| Source       | What it is                                                                                          |
| ------------ | --------------------------------------------------------------------------------------------------- |
| `report`     | The agent reports for itself with `tuios set-agent-state`                                           |
| `program`    | The program printed an OSC 7501 report. See [Program Status](https://tuios.dev/docs/program-status) |
| `transcript` | The daemon reads the record file the agent's harness writes                                         |
| `osc`        | An escape sequence the agent printed: OSC 9;4 progress, or its window title                         |
| `screen`     | A rule matched text on the pane's screen                                                            |
| `detect`     | The daemon saw an agent CLI in the pane's foreground                                                |
| `stall`      | The pane was `working` and then went quiet                                                          |

A source can overwrite a claim from its own rank or lower, never from a higher one. So a screen rule cannot overwrite what an agent said about itself. There is one exception: a screen rule that sees a permission prompt can mark a pane `needs_input` over a stale `working` claim, and the old claim comes back as soon as the prompt is gone.

### The agent reports for itself

This is the most accurate source, and the only one that can reliably say `needs_input`. The usual way to report is to let TUIOS wire the agent's hooks for you:

```bash
tuios integration install claude-code    # or codex, gemini-cli, opencode, kilo, amp, ...
tuios integration install --all          # every supported harness whose config directory exists
tuios integration status                 # installed and current, per harness
tuios doctor agents                      # PATH, install state, and agent panes missing an integration or out of date
```

You can do the same from inside TUIOS. See [The Agents tab](https://tuios.dev/docs/agents#the-agents-tab).

The installer adds its hook entries to the harness's own settings file, keeps everything else in it, and saves the file as it was the first time as `<file>.tuios.bak`. It refuses a file it cannot parse rather than rewrite it. Each entry runs `tuios agent-hook`, which never blocks the harness for long and prints nothing a harness could read as an answer. `tuios integration uninstall <harness>` removes exactly what it wrote.

Twelve integrations report the pane's state: Claude Code, Codex, Copilot, Cursor Agent, Gemini CLI, opencode, Kilo, Amp, Kimi Code CLI, Pi, oh-my-pi and Qwen Code. Seven more (Antigravity, Crush, Devin, Droid, Grok, Hermes and Qoder) report only the conversation id, so the pane can be [resumed after a restart](https://tuios.dev/docs/agent-inbox#resuming-after-a-restart), and leave the state to the screen rules. The Claude Code and Codex hooks also feed the rail what the agent is doing now and the Inbox its [activity log](https://tuios.dev/docs/agent-inbox#what-the-agent-has-been-doing). The Claude Code hooks also count the subagents the agent runs, and the rail shows the count, such as `3 subagents`. This needs version 3 of the Claude Code integration. `tuios integration status` shows an older install as out of date, and `tuios integration install claude-code` updates it. `tuios integration install claude-code --statusline` also feeds the model, context use and cost from Claude Code's status line. It never replaces a status line of your own: `--then` chains to it.

The opencode integration works with opencode V1 (1.18.29 or later) and V2. On V2, the plugin runs in the opencode terminal client, so it reports the state of the session that pane shows. Events from other sessions and subagents do not change the pane. A V2 server that several panes share does not report pane state. After you update TUIOS, run `tuios integration install opencode` again and restart opencode. Headless V2 clients, such as `opencode run`, do not load the plugin.

You can also report by hand, or from a script of your own:

```bash
tuios set-agent-state working -m "running the test suite"
tuios set-agent-state needs_input -m "waiting for approval to push"
tuios set-agent-state done
tuios set-agent-state none        # clear it
```

From inside a pane, name the pane and the harness, since the focused pane may be a different one:

```bash
tuios set-agent-state working -s "$TUIOS_SESSION" -w "$TUIOS_PANE_ID" --harness claude-code
```

A report that loses to a higher-ranked source still exits 0 and prints `Not applied: ...` on stderr.

The old shell shim in `integrations/claude-code/` of the repository now just runs `tuios agent-hook claude-code`. Settings that still point at it keep working, but alongside an installed integration every event is reported twice. `tuios doctor agents` says so.

#### The Agents tab

The settings page has an Agents tab with the same report as `tuios doctor agents`. Press Ctrl+B A to open it. You can also type `Agents: settings, install and update integrations` in the command palette.

Each row is one harness. It shows whether the harness is on `PATH`, and one of these states:

| State          | What it means                                                                                                                                          |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| installed      | The integration is installed and current. An install made with `--command` is current too, and the line under the row names the program its hooks run. |
| out of date    | An older TUIOS installed it. Update it.                                                                                                                |
| not installed  | The integration is not installed. If the harness has not run on this machine, run it once first.                                                       |
| no integration | TUIOS has no integration for this harness. The line under the row gives the reason.                                                                    |
| cannot read    | TUIOS cannot read or parse the integration's file. The line under the row names the file.                                                              |

Press Enter or click a row to see its actions:

- **Install** writes the hook entries.
- **Update** replaces an older install. It keeps the program the hooks already run, so an install made with `--command /path/to/tuios` keeps that path.
- **Uninstall** removes what TUIOS wrote: the hooks, the MCP server and the status line, each only if it is there. Your own entries stay.

Each action names the files it changes. Press Enter on the action to do it, or Esc to go back. The actions run the same code as `tuios integration install` and `tuios integration uninstall`. The result or the error shows in the dock. If the harness saves its settings file while TUIOS edits it, TUIOS tries once more. If the file changes again, TUIOS does not write it and asks you to try again.

The tab is only there for a terminal on this machine. It is not there when [agent features are off](https://tuios.dev/docs/agents-off), or on a client that `tuios ssh` or `tuios-web` serves, because the integrations on the server are not the remote person's to change.

#### The integration notice

When a pane runs a harness whose integration is out of date, or not installed where it could be, the dock shows one notice for that harness. An example:

> Claude Code integration is out of date. Open Settings, Agents to update it.

The notice comes once per harness each time the client starts. To dismiss it for good, click the right end of the notice. It then stays away until the state or the version changes. Esc and a click on the text clear it for this session of the client only, so the notice comes back the next time you attach.

Panes on other machines get no notice, because their harness uses that machine's integration.

### Agents that report to herdr

Some agents report their state to [herdr](https://herdr.dev/), another multiplexer for coding agents, by themselves: Crush, Kiro CLI, Command Code, Muse Code and Prime Agent. TUIOS accepts the same reports, so these agents need no install step.

Every pane starts with herdr's variables: `HERDR_ENV=1`, `HERDR_SOCKET_PATH` naming a socket of TUIOS's own, `HERDR_PANE_ID` and `HERDR_WORKSPACE_ID` naming the pane and its session in herdr's form, and `HERDR_BIN_PATH` naming `tuios`. So a Crush that you start from a shell prompt reports `working`, `needs_input` on a permission prompt or a question, and `done` when its turn ends. Its session title and model show as [agent metadata](https://tuios.dev/docs/agents#where-it-shows). Several Crush panes report side by side, and each pane follows only its own reports.

- A pane may report only about itself.
- A report older than the last one from the same agent is dropped.
- An agent that exits without saying so, for example after a crash, does not keep its state. When the pane is back at its shell prompt, the state clears after two seconds.
- An agent that reports through herdr's commands, `"$HERDR_BIN_PATH" pane report-agent`, reaches TUIOS the same way.

Crush sends no detail with a permission prompt, so TUIOS also reads Crush's permission dialog from the screen. The pane goes to `needs_input` with a message such as `approve bash: touch hello.txt`, and you can answer it from the Inbox. See [Crush permission prompts](https://tuios.dev/docs/agent-inbox#crush-permission-prompts).

The same socket answers herdr's socket API, so tools built for herdr work with TUIOS. See [herdr Compatibility](https://tuios.dev/docs/herdr-compatibility).

TUIOS never uses herdr's own socket. A herdr that you start inside a TUIOS pane stops with a message about nesting. To run herdr there, give herdr's variables only to panes that start a known reporter:

```toml
[agents]
herdr_protocol = "agents"   # always (default), agents, off
```

### Program status

Any program can report its own state with one escape sequence, OSC 7501, or with `tuios status`. The report can say what the program waits for: an approval, an answer or a login. See [Program Status](https://tuios.dev/docs/program-status).

```sh
tuios status blocked --kind permission --app deploy --msg 'Approve deploy to production?'
```

### Progress sequences

An agent that prints OSC 9;4 progress sequences needs no wiring. Setting a progress bar maps to `working`, clearing it to `idle`, the error state to `errored`, and the warning state to `needs_input`. After a pane sends an OSC 7501 report, TUIOS stops reading OSC 9;4 as the pane's state until the next full reset.

### Process detection

With no report at all, the daemon checks each pane's foreground process every two seconds. If it is a known agent CLI, the pane is marked `working`. It reads the process name, its executable, and for an interpreter such as `node` or `python3`, the script it runs. It also looks behind wrappers such as `sh -c`, `timeout`, `npx`, `uvx` and `mise exec`. A directory named after an agent is never counted.

TUIOS ships manifests for 24 agent CLIs, including Claude Code, Codex, Gemini CLI, Cursor Agent, Aider, OpenCode, Crush, Amp and Copilot. Add your own manifest as a TOML file in `~/.config/tuios/harnesses/` (or `$TUIOS_HARNESS_DIR`). It is picked up on the next daemon start.

| Key                           | Default | Meaning                                                                |
| ----------------------------- | ------- | ---------------------------------------------------------------------- |
| `daemon.agent_autodetect`     | `true`  | Detect agent CLIs in the foreground                                    |
| `daemon.agent_detect_seconds` | `0`     | Seconds between checks. `0` uses 2. A negative number turns checks off |

Detection alone can say that an agent is present. It cannot say the agent is waiting for you.

### Screen and title rules

An agent sitting on a permission prompt often prints nothing more: no output, no title, no progress. The only evidence is the text on the screen. A manifest can carry screen rules that match the bottom of the pane and report `needs_input`, and title rules that match the window title. The Codex manifest, for example, reads `Action Required` from the title.

A rule with `show = "dialog"` reads a prompt drawn as a bordered box over the transcript. It matches only when one box holds all its strings, so the same words quoted in the transcript do not count. `tool_field` and `what_fields` build the message `approve <tool>: <what>` from the box's fields, the form the [risk rules](https://tuios.dev/docs/agent-inbox#risk-rules) read. The Crush manifest uses this for its permission dialog.

Rules only run on a pane already attributed to a harness, and only when the pane writes, so a quiet pane costs nothing.

### The stall timer

If a pane reported `working` and then prints nothing for 30 seconds, the daemon looks at its screen one last time. If no rule matches, the pane becomes `unknown`. The timer only ever moves a pane out of `working`, so it never overrides `needs_input`, `done` or `errored`.

Set `TUIOS_AGENT_STALL_SECONDS` in the daemon's environment to change the window. `0` or a negative value turns the timer off.

## Reading the state

```bash
# One pane
tuios get-agent-state -w build
tuios get-agent-state -w build --json

# Every agent pane in the session
tuios list-agents
tuios list-agents --all          # every pane, including ones not seen as agents
tuios list-agents --all-hosts    # every machine in [hosts]

# Block until an agent needs a person
tuios wait-for agent-state -s work --until needs_input
tuios wait-for agent-state -w build --until idle,done --timeout 600000
```

`get-agent-state --json` includes `state`, `message`, `needs_you`, the winning `source`, the `harness_id`, and `identity` and `confidence` saying how the harness was recognised. `list-agents` rows and `explain-agent-detect` carry `identity` and `confidence` too. `list-windows --json` carries each pane's `agent_state`.

The same three commands report `evidence_age_ms`: the milliseconds since the last evidence about the state arrived. Confidence says how TUIOS learned the state, and the age says how long ago.

- A report from the agent, a detector change and the stall timer reset the age.
- A title or screen rule that reads the same claim again does not reset it.
- For a state that the detector or the stall timer inferred (`source` `detect` or `stall`), new output from the pane also resets it. A pane that keeps printing reads fresh.
- The value is `null` for a pane that never had a state.

## When a pane is marked wrong

Two commands show exactly what the daemon saw.

```bash
tuios explain-agent-detect -w build
```

This starts with a verdict in plain words, then the process name, arguments and executable the daemon read, any wrapper it looked behind, and what every manifest made of it:

```
This pane runs claude-code behind timeout.
  The foreground process timeout is a wrapper, so tuios read the processes behind it.
  The process claude matched the manifest claude-code on comm=claude.
  A process name is strong evidence.
```

```bash
tuios explain-agent-screen -w build
tuios explain-agent-screen -w build --harness codex --lines 20
```

This prints the pane's screen tail exactly as the rules read it, then each rule, which one fired, and for each rule that did not, which string was the reason. Use it when writing a rule.

## Alerts

A state change can raise a desktop notification, a sound or terminal bell, a dock message you can click to go to the pane, and a shell command. The `[notifications.agent]` table controls all of it:

```toml
[notifications.agent]
enabled = true
notify = true              # notification in the terminal you are using
dock = true                # clickable message in the dock
sound = false
sound_mode = "audio"       # audio, bell or both
suppress_focused = true    # nothing for the pane you are looking at
settle_seconds = 2         # drop the alert if the state changes within this time
quiet_hours = "22:00-07:00"
command = ""               # shell command to run on an alert

[notifications.agent.states]
needs_input = true
errored = true
done = true
idle = false
working = false
```

The notification is written into the stream your terminal draws, so it reaches the terminal in front of you even when the session runs on another machine. Alerts are raised by an attached client, so a detached session tracks state without announcing it. To reach your phone when no client is attached, see [Push Notifications](https://tuios.dev/docs/push-notifications). See [Configuration](https://tuios.dev/docs/configuration#notifications) and [Hooks](https://tuios.dev/docs/hooks) for the command contract.

### Hear an alert

Alerts make no sound by default. To hear them, turn on `sound`:

```toml
[notifications.agent]
sound = true
sound_mode = "audio"       # audio, bell or both
```

You can also run `tuios set-config notifications.agent.sound true`, or use the Alerts tab of the settings page (, in window mode).

| `sound_mode` | What you hear                                                                                  |
| ------------ | ---------------------------------------------------------------------------------------------- |
| `audio`      | A short cue from the audio player of the machine that runs TUIOS. This is the default          |
| `bell`       | Your terminal's bell. TUIOS sends a BEL character, and the terminal decides what to do with it |
| `both`       | The cue and the bell                                                                           |

- **`audio`** uses `paplay`, `pw-play` or `aplay` on Linux, `afplay` on macOS and PowerShell on Windows. If the machine has none of them, the alert is silent and TUIOS shows no message.
- **`bell`** depends on your terminal's own bell setting. Some terminals make no sound for a bell, or only flash the window. In kitty, check that `enable_audio_bell` is `yes`. Other terminals have a similar setting.
- **Over SSH or in the browser**, `audio` plays on the server, not on the machine in front of you. Use `bell` there.

TUIOS plays at most one cue every `sound_cooldown_seconds` (3 by default), across all panes. `[notifications.agent.sounds]` sets your own files for the cues. See [Configuration](https://tuios.dev/docs/configuration#agent-alerts).

## Environment in a pane

Every daemon pane gets these variables, which is how a shim or an agent finds TUIOS:

| Variable                                                                                  | Value                                                                                                           |
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `TUIOS_ENV`                                                                               | `1` inside TUIOS                                                                                                |
| `TUIOS_SOCKET`                                                                            | The daemon socket                                                                                               |
| `TUIOS_PANE_ID`                                                                           | The pane's window id                                                                                            |
| `TUIOS_WINDOW_ID`                                                                         | The same id                                                                                                     |
| `TUIOS_SESSION`                                                                           | The session name                                                                                                |
| `TUIOS_HOST`                                                                              | The hostname of the machine the pane's process runs on                                                          |
| `TUIOS_RESTORED`                                                                          | `1` in a shell started again after a restore                                                                    |
| `TUIOS_PANE_GRANTS`                                                                       | What the pane may do through TUIOS as it starts, such as `admin` or `read,write,fan`                            |
| `TUIOS_PANE_TOKEN`                                                                        | Proves `TUIOS_PANE_ID` to the daemon where the kernel cannot name the caller's pane                             |
| `HERDR_ENV`, `HERDR_SOCKET_PATH`, `HERDR_PANE_ID`, `HERDR_WORKSPACE_ID`, `HERDR_BIN_PATH` | herdr's variables, for [agents that report to herdr](https://tuios.dev/docs/agents#agents-that-report-to-herdr) |

A pane whose process runs on another machine has a different set. See [Remote Hosts](https://tuios.dev/docs/remote-hosts#panes-on-another-machine).

## What a pane may do

Every pane holds grants that say what a program in it may do through TUIOS:

| Grant     | Allows                                                                                                         |
| --------- | -------------------------------------------------------------------------------------------------------------- |
| `read`    | Read its own session and its fan group: listings, captures, agent state, waits and events                      |
| `write`   | Type into the panes of its own session, and leave mail there                                                   |
| `fan`     | Write in its fan group, and start agents with `fan` and `start-agent`                                          |
| `respond` | Answer another pane's prompt without you, and type into a pane that waits on a prompt                          |
| `admin`   | Everything else, as every pane could before grants existed. Implies `read`, `write` and `fan`, never `respond` |

A pane holds the grants it was started with (`--grants` on `start-agent`, `fan` and `new-window`), or else the default of `[agents.permissions]`: `admin` under `mode = "open"`, the default, and the `grants` list under `mode = "strict"`. A pane without `admin` types only into panes that hold nothing it does not, and never gives more than it holds.

```bash
tuios pane-grants                                   # from inside a pane: what this pane may do
tuios start-agent claude --name reviewer --grants read
tuios set-pane-grants -w reviewer --grants read,write
tuios set-pane-grants -w reviewer --reset           # back to the default
```

```toml
[agents.permissions]
mode = "strict"
grants = ["read", "write", "fan"]
```

The daemon checks the grants on every way into a pane: the control socket, the link sockets, the tmux shim's pane holder, prompts, `send-keys`, `run-command` and typing through the client protocol.

- **Prompts.** A pane without `respond` cannot type into another pane that waits on a prompt. This applies to a pane with `admin` too. To give `respond` to one pane, use `tuios set-pane-grants` or `--grants`.
- **`run-command`.** From a pane without `respond`, `run-command` cannot type or press keys. Use `send-keys` or `send-text` with `-w`.
- **`send-keys` with `PREFIX`.** `send-keys` with `PREFIX` from a pane is refused. Use the TUIOS command for the action, such as `focus-window`, `new-window` or `split-window`.
- **`send-keys` with no window.** From a pane, `send-keys` with no `-w` types into the focused pane. TUIOS does not read these keys as key bindings.
- **Link sockets.** A process inside a pane, or a process that the daemon started, cannot connect to a link socket.
- **Other machines.** Grants do not travel over a link. A pane on another machine that types into a pane here is held to the same prompt rule. It types into a pane that waits on a prompt only when this machine's link policy allows `respond`. See [Remote Hosts](https://tuios.dev/docs/remote-hosts).

Some acts are yours alone whatever a pane holds: answering a held approval, answering an `ask-human` question, dismissing or snoozing an Inbox item, and writing a review note or queued reply that reads as yours. They need the nonce your attached client got when it attached, and the daemon refuses a caller inside a pane even with a copy of it. The Inbox also refuses an answer that `send-keys` typed. This covers the digit keys, the second press of a risky allow, question answers and the release of held mail.

### Changes that wait

A change to `config.toml` that gives panes or other machines more waits for you:

- A change that narrows `[agents.permissions]`, `[hosts]` or a link policy applies at once.
- A change that widens them waits. An example is `mode = "strict"` to `mode = "open"`. A new host, or a host that dials another way, waits too.
- To apply a change that waits, run `tuios config apply` from a terminal outside TUIOS. A daemon restart also applies it.

```bash
tuios config apply
```

While a change waits, the Inbox shows an item, and `tuios pane-grants` and the daemon log say so. `tuios hosts add` from a pane also waits. A host that you add with "Add a host" on the settings page applies at once.

When the daemon starts and finds wider grants than at the last run, it says so in the log, in `tuios pane-grants` and in the Inbox.

> **Upgrading from v0.8.0**
>
> - A pane that types into another pane's prompt needs the `respond` grant. `admin` does not include it.
> - A script in a pane that sends `PREFIX` with `send-keys` fails now. Use the TUIOS command for the action.
> - A config change that widens grants or hosts waits for `tuios config apply`.

## Starting agents

```bash
tuios start-agent claude --name reviewer               # one agent in a new pane, returns once it is ready
tuios start-agent codex --name tests --prompt 'Run the tests and fix what fails.'
tuios start-agent --protocol acp 'opencode acp' --name helper
```

`start-agent` opens a pane in the session `-s` names (creating it if needed), starts the agent, and returns once the agent shows it is at its prompt. With `--prompt`, it types the first prompt then. `--protocol acp` or `--protocol codex` runs the agent headless over the Agent Client Protocol or the Codex app-server: the pane shows the conversation as a transcript you type into, and reports the agent's state itself. In that pane, Ctrl+C cancels the running turn and every permission request it still waits on. Ctrl+D on an empty line quits. To start the same prompt in several agents at once, each in its own git worktree, see [Worktrees](https://tuios.dev/docs/worktrees#fan-out-one-prompt-several-agents).

## Letting an agent drive TUIOS

TUIOS ships a skill: a guide written for an agent running inside a pane. It covers addressing panes, reading and writing them, opening panes to run work in, waiting on conditions instead of polling, reporting state, and working with other agents. It is built into the binary, so it always matches the version you run.

```bash
tuios --skill              # the core
tuios --skill fleet        # one topic
tuios --skill all          # everything
```

The topics are `panes`, `state`, `mail`, `inbox`, `fleet`, `hosts`, `grants`, `events`, `mcp`, `tmux`, `config`, `errors` and `recipes`.

To install it for Claude Code:

```bash
mkdir -p ~/.claude/skills/tuios
tuios --skill > ~/.claude/skills/tuios/SKILL.md
```

Run it again after you update TUIOS.

An agent can also drive TUIOS as Model Context Protocol tools. `tuios integration install claude-code --mcp` registers `tuios mcp` as a server for Claude Code, Codex, Gemini CLI or opencode.

- By default the server types into no pane, and reaches only the session of the pane it runs in. Its tools list and read panes, wait for states, report the agent's own state and send and read mail.
- `--mcp-write` adds the tools that type into panes: `send_text`, `send_keys`, `ask_agent`, `respond` and `fan`.
- Each tool says whether it changes something. A tool that sends mail, reports state or types is not marked read-only, so a client that approves read-only tools by itself still asks before it runs one. The tools that type into panes are marked destructive.
- The server speaks MCP protocol versions 2024-11-05 to 2025-11-25, and the stateless 2026-07-28 version.

> Everything an agent does goes through the same `tuios` commands and [control protocol](https://tuios.dev/docs/control-protocol) you can use from a shell. There is no separate agent API.

## Related

*[An interactive figure goes here. Open the page to use it.](https://tuios.dev/docs/agents)*
