{% extends "admin/_layout.html" %} {% from "_macros.html" import icon %} {% set section = "agents" %} {% block title %}Agents - {{ brand.name }}{% endblock %} {% block heading %}Agents{% endblock %} {% block admin_content %}

An Agent chat can read files, write files and run commands on a machine reached over SSH. Nothing runs on this server. People add their own connections under Connections; what you decide here is whether the feature exists and what one reply may spend.

{{ icon("shield", "icon--sm") }} There is no sandbox to configure, and that is deliberate: containment is whatever host somebody points a connection at. A container built for the job is a very different thing from a key to a live server, and {{ brand.name }} cannot tell them apart. What a model reads — a web page, a file, the output of the last command — is untrusted, and in Auto mode nothing stands between that and a command running.
{% if problem %}
{{ icon("warning", "icon--sm") }} {{ problem }}
{% endif %} {% if saved %}
{{ icon("check", "icon--sm") }} Saved.
{% endif %}

Switch

Off, nobody can start one and no agent tool is offered, whatever permissions they hold. {{ profile_count }} connection{{ '' if profile_count == 1 else 's' }} saved across all accounts.

People also need the Run commands permission, a model flagged Agent execution, and a connection of their own.

Connections to this machine

Agent chats reach a machine over SSH, and the point of that is that it is not this one — nothing runs on the host holding the database and the encryption key. A connection pointed at 127.0.0.1 walks past that, and from the SSH layer's point of view it looks like any other host. {% if loopback_count %} {{ loopback_count }} saved connection{{ '' if loopback_count == 1 else 's' }} point{{ 's' if loopback_count == 1 else '' }} here. {% endif %}

{% for value, label, hint in loopback_modes %} {% endfor %}

Only read when the position above is Only on one port. Port 22 is refused whatever is typed here — that one is this host's own sshd, not a container that published its port on the loopback interface.

The modes

Set per chat and switchable at any time. This is what each one means; the two lists below adjust them.

{% for value, label, hint in modes %}
{{ label }}
{{ hint }}
{% endfor %}

What never needs asking

One per line: a tool name like file_read, or a command with wildcards like git *. A command containing anything that joins two commands together — a semicolon, a pipe, backticks — can never match one of these, so git * does not quietly also mean git status; curl … | sh.

What always needs asking

Checked before everything, including Auto. Treat it as a guard against an accident rather than against an adversary: rm -rf /* here does not stop /bin/rm -rf /, and nothing pattern-shaped could. The same limit as above applies, and it cuts the other way here: a command line that runs more than one thing matches none of these, so in Auto shutdown -h now asks and shutdown -h now & runs. Anything that must never happen belongs on the far side, in that account’s own permissions.

What one command may spend

Characters. The rest is cut off and the model is told so.

Background commands

A command that would outlast its timeout can be left running instead of killed — detached on the far side, checked on later. It is how a long install, build or download becomes possible at all.

Off means byte-for-byte the old behaviour: a command that hits its timeout is killed. On, a command can be launched detached (or kept running when it times out), writing to a file under /tmp on the machine, and the model gets tools to read and stop it. A detached command's log can grow without bound on the host — that is the host's to contain, as with everything an agent runs there.

Off leaves the timeout a hard stop; the model can still choose to background a command up front.

On, a finished job starts (or joins) a reply carrying its result. Off, the model only sees it the next time it runs of its own accord.

Each is a periodic reconnect to the machine. Jobs past this still run; they are simply not watched, and the model is not woken for them.

What one reply may spend

Four separate bounds, because they fail differently: the clock stops one slow command eating an afternoon, tool output stops a model filling its own context with build logs and having no room to answer, written tokens stop one that keeps going, and the step count is a backstop against a runaway.

In tokens, across every round of one reply. This is the bound that normally ends a long piece of work. Zero means no ceiling.

Time spent waiting for you to answer does not count.

Only ever against a plan, and only while tasks on it are still open — that is the one thing there is to be objectively wrong about. A reply with no plan that says it has finished is believed. It is asked at most twice in a row, and if it stops a third time that is recorded in the transcript rather than argued with.

A backstop, not a working budget. An agent reply is meant to run until the task is done, so a number low enough to be what stops it is a number that stops it halfway. Use the token ceiling above for a real limit.

Asking you things

Seconds. After this the reply carries on without an answer and says so. At least a minute, whatever is typed here.

When a model asks a question it can offer answers to pick from, and by default a box to write something else. Turn this off if you would rather nobody typed free text into a prompt a model composed.

The terminal

A panel beside an agent chat holding an interactive shell on that chat's own connection. What somebody types there is theirs: the modes and the two lists above govern the model, not the person at the keyboard, who could open the same shell with an ssh client. The model cannot see the panel; sending it something is a button they press.

People also need the Open a terminal permission. {{ terminal_count }} shell{{ '' if terminal_count == 1 else 's' }} open right now.

Seconds with nobody watching and nothing typed. Closing the panel does not end the session — a build carries on and is still there on the way back — so this is what eventually ends one.

One per chat. Each holds an SSH connection open on the far machine.

Gives bash and zsh the same invisible markers VS Code and WezTerm use, so Copy, Send and the automatic toggle know which output belongs to which command. Written by the shell into a temporary file it deletes itself, and any other shell is started exactly as it was before. Off means those buttons fall back to copying the last of the screen as it appeared, wraps and all.

The project directory

A listing of the directory a chat works in, so a reply does not spend its first rounds finding out what is there — and so files can be attached by name with @. Built by one read-only command (git ls-files where it works, otherwise find), cached briefly, and shared by every chat pointed at the same directory.

Off means no listing is built at all, and the file picker offers only what is in the library.

This is spent on every request in an agent chat, so it is a budget rather than a limit: directories that will not fit are shown as a count and the model is told to look inside them itself. 0 keeps the listing for the file picker and puts none of it in the prompt.

Looks for AGENTS.md or CLAUDE.md in the root of the project directory and puts it in the prompt, so a model follows the conventions of the project it is working in. The file is written by whoever works on that project, so it is treated as untrusted: it can say how to work, and cannot grant permission for anything. The exact wording around it is the The project's own instructions fragment on Prompts, and clearing that fragment removes the only path by which the file reaches a model.

Cut at a line boundary past this. 0 is the same as switching it off.

{# A second form, and a second settings group. Subagents are not an agent-chat feature — an ordinary chat can delegate as well — but this is the page somebody comes to when they want to know what one reply may set going on its own, and a nav entry for a single card would be worse than the near-miss. A form cannot nest inside another, so this sits *after* the one above rather than as a card inside it. Two forms means the browser posts only the one whose button was pressed, which is what keeps each group's save handler writing one key. #}

Helpers

A reply can hand a self-contained piece of work to a second model that runs on its own and reports back — several at once, which is what makes research fan out instead of queueing. This applies to ordinary chats as much as agent ones.

{{ icon("shield", "icon--sm") }} A helper cannot ask anybody anything, so nothing in its chat can stop for approval. It therefore gets only what this chat could already do without asking: it reads, it searches, and on a machine it runs a short fixed list of read-only commands and nothing else, in every mode including Auto. It cannot send helpers of its own.

People also need the Delegate to a helper permission, and the model needs the Tools capability. Off by default: a reply that spawns helpers spends model time multiplicatively, and on one local endpoint four at once is four times the queue rather than four times the speed.

Fanning out across a handful of independent questions is what this is for. A reply that wants twenty has misread the tool.

Each is a whole generation against the same endpoint the reply that asked for it is waiting on. Past this a model is told to do the work itself rather than made to wait.

In tokens, across every round. A helper answers one question, so this should run out well before the reply that asked does. Zero means no ceiling.

Seconds. Past it the helper is stopped, not abandoned: what it had written is kept and handed back with a note saying it is partial.

A backstop, as it is above. The clock and the token ceiling are what normally end one.

Off means it is deleted once its answer has been handed over, which is what keeps this cheap to use. Turn it on to work out why one came back with something odd. Kept chats are temporary either way and are swept a day later, and neither appears in anybody's sidebar.

{% endblock %}