Agent policy
Choose which boards agents may flash, erase and reset, and read every call they made.
An agent working through espx mcp can write firmware to real hardware. The [agent] table in a project's espx.toml decides which boards it may touch and what it may do to them. Every flash, erase and reset an agent asks for is checked against it. Commands you run yourself in a terminal are never checked.
The [agent] table
| Key | Default | Meaning |
|---|---|---|
boards | the project's [board] id | Boards agents may touch, by id, name or port. Names are turned into ids when espx reads the file. [] allows none |
flash | true | Agents may flash the listed boards (flash and run) |
erase | false | Agents may erase the listed boards |
Resetting a board with the reset tool needs only the board to be listed. Reading is never checked: devices, monitor_read, and also board_info and monitor_start, even though those two reset the board through the serial lines when they open it.
The defaults mean:
- A project bound with
espx new --board-id(orproject_newwithboard_id) can be flashed and reset by its agent, but not erased. - A project with no
[board] idand noboardslist allows no board at all. - An agent working outside any project may touch no board.
A refused call fails with policy_denied, and the message names the keys to set:
Recordings played through monitor_start with replay are not boards and are never checked.
See the policy
--json prints the resolved policy as {"boards": [..], "flash": true, "erase": false}, with names turned into ids. espx agent works only inside a project and never creates an espx.toml.
Change it
| Flag | Effect |
|---|---|
--boards B,.. | Agents may touch these boards, by id, name or port, comma-separated |
--no-boards | Agents may touch no board |
--bound-board | Go back to the default: only the project's [board] id |
--flash on|off | Whether agents may flash the allowed boards |
--erase on|off | Whether agents may erase the allowed boards |
Pass at least one flag. Keys you leave out stay as they are. A board does not need to be plugged in to be listed; a name is stored as its board's id.
agent set edits espx.toml in place. It replaces the boards, flash and erase lines inside [agent], keeping their indentation and trailing comments, adds the missing ones, and adds an [agent] section when there is none. Every other line stays as it was. If the policy is written as an inline table (agent = { .. }) or with dotted keys, espx cannot edit it safely and stops with policy_not_editable without writing anything.
Allow one thing
agent allow makes the smallest change that lets agents do one thing to one board. It adds the board to boards unless the policy already lists it, and turns flash or erase on for those actions. Without --board it uses the project's board, else the one attached. This is what the desktop app's Allow button does on a denied call.
Both agent set and agent allow print the resulting policy, or, with --json, the same document as espx agent --json.
The audit log
Every tool call an agent makes through espx mcp, allowed or not, is appended to ~/.espx/agent.log as one JSON object per line:
| Field | Meaning |
|---|---|
ts | When the call started, milliseconds since the epoch |
client | The MCP client's name, such as claude-code |
tool | The tool called |
args | Its arguments |
board | The board id the call resolved to, if any |
project | The project directory whose policy was checked, if any |
outcome | ok, denied or failed |
detail | For denied and failed: the error as {"code": .., "message": ..}, the same code the tool result carried, such as build_failed |
denied | For a denied call: the refused action, flash, erase or reset |
needs_human | For a flash only a person can rescue: the action and message |
ms | How long the call took |
A failed call that returned a result rather than an espx error, such as a cancelled job or a rejected run, is logged with the code command_failed. Each entry is written in one append, so several espx mcp processes can log at once without mixing lines.
Read the log
espx log prints one line per call with its time, client, tool, outcome, duration and board, and the error message under a denied or failed call. --tail N keeps the last N entries. --json prints them as one JSON document. The desktop app's AI agents page shows the same log live, grouped by client.