A remote is a machine you connect to inference with belt remote start. It hosts agent harnesses and, when you opt in, runs agent sessions or shell commands the platform dispatches.
The daemon connects outbound to inference over an authenticated WebSocket. Nothing listens on your machine, and the daemon runs only what the server sends.
In the workspace
After you run belt remote, open Resources → Remotes in the sidebar (/remotes) to see connection status, harness profiles, and whether exec is enabled on each host.
Select a machine to open its page:
- Agents — one card per harness profile on the machine. Launch asks for the folder the harness should work in and opens a chat with the harness-backed agent for that profile. A card cannot launch while the machine is offline, the daemon was started without
--agents, the harness is signed out or too old, or the profile is busy. - Machine — belt version, hostname, OS, CPU, whether agent sessions and command execution are on, and last seen.
- Sessions on this machine — harness sessions inference started and sessions opened locally. Continue on an idle session reopens it in a chat.
When to use a remote
| Use case | What the remote provides |
|---|---|
| Agent harness hosting | Keeps coding agents (Claude Code, Codex, Cursor, and similar) logged in on a machine inference can drive |
| Agent sessions | Runs harness processes for chats the API opens on this host (belt remote start --agents) |
| Command execution | Runs shell commands on a connected host and streams stdout/stderr back (belt remote exec) |
A remote is not a private inference engine. Engines run GPU/CPU workloads from the task queue. Remotes host harnesses and optional shell execution on a machine you control. See Private workers for compute on your hardware.
Security model
- Outbound only. The daemon dials
wss://api.inference.sh/ws/remotes/{id}with your API key. No inbound ports are opened. - Your OS user. Commands and harness sessions run as the user who started
belt remote start. That user is the blast radius. - Exec is opt-in. Command execution is disabled unless you start the daemon with
--exec. Without it the daemon refusesremote_exec_startframes, and the API refuses the dispatch with403 exec_disabled. - Agent sessions are opt-in. Inference may drive harness sessions (Claude Code, Codex, Cursor, and similar) on your machine only when you start the daemon with
--agents. Without it the daemon refusesremote_session_openframes, ignores other session frames, and answers opens withagent sessions are disabled on this remote (start it with --agents). - Permissions stay with you. The daemon never auto-approves harness tool calls. Every approval request is forwarded to inference so a person can allow or deny it.
- Destructive CLI gate.
belt remote execprompts for confirmation, or requires--yesin non-interactive mode.
Run the daemon under a dedicated user or inside a container if you need a smaller blast radius.
Connect a machine
Prerequisites
- Belt CLI installed and logged in (
belt login) - An API key or session with the
remotes:writescope. Thestandardkey preset includes it.
Start the daemon
1belt remote start2belt remote start --name "work-laptop" # custom display name3belt remote start --exec # allow command execution on this host4belt remote start --agents # allow harness agent sessions on this host5belt remote start --exec --agents # both exec and harness sessionsOn start, belt:
- Creates or loads a machine identity key (
remote_ed25519) in~/.inferencesh/. WhenBELT_CONFIG_DIRis set, the key lives in that directory instead. The private key stays on the machine; only the public key is sent. - Probes the machine for installed agent harnesses (see Harness discovery). The CLI shows discovering agent harnesses... as its own step before registration.
- Registers the remote with
POST /remotes, sending the name (default: hostname), public key, belt version, system info, probe results, and opt-in flags (exec_enabled,agents_enabled) - Connects to the remote WebSocket and sends a heartbeat every 5 seconds (every third beat also carries a fresh
system_infosnapshot with live CPU, RAM, and home-disk usage)
Foreground vs background. With no flags, belt remote start holds the terminal open until you stop it:
| Input | Effect |
|---|---|
| d or Ctrl-D | Detach: hand the connection to a background daemon and return your shell. Same as starting with --detach / -d. |
| Ctrl-C | Disconnect and exit; the API marks the remote disconnected when the WebSocket closes, and running again when you start belt remote and the socket reconnects. |
Detaching is only available on an interactive terminal (not when stdin is piped or in CI). Only one belt remote start may run per machine at a time (foreground or detached), keyed on the machine identity in ~/.inferencesh/. That instance holds a lock that belt remote status and belt remote stop use — including foreground sessions, which status labels mode: foreground, in the terminal that started it instead of a log file path.
A second belt remote start with the same --exec and --agents flags exits with a remote is already running on this machine (pid …); run belt remote stop or disconnect that session first. If you start again with different --exec or --agents values, belt offers to restart the running daemon with the new permissions (stopping ends any harness agent sessions on that machine, so it asks for confirmation). Decline the prompt or run in non-interactive mode without --yes, and belt leaves the running remote unchanged — use belt remote stop, then start again with the flags you want. Press d to detach: belt closes the foreground connection, releases the lock, and starts a background daemon with the same flags. If agent sessions are running in the foreground process, they are its children and would end on detach; belt asks you to press d a second time to confirm.
Flags such as --exec, --agents, and --name belong to belt remote start, not the bare belt remote group. Typing belt remote --exec prints an error that names belt remote start --exec instead of a generic unknown-flag message.
To start in the background immediately:
1belt remote start --detach # or -d2belt remote status # pid, remote id, connection state and how long it has held3belt remote logs -f # follow the daemon log4belt remote stop # stop the running remote (foreground or background)Logging. Foreground belt remote start shows harness discovery and registration progress in the terminal and prints connection warnings there. Info-level WebSocket diagnostics are suppressed so they do not interleave with the spinner. When a harness session closes with an error, the daemon logs a warning such as session for chat <id> closed: <reason> — the same reason inference shows on the failed chat turn. A detached daemon writes info and warn logs to the file path shown by belt remote status; use belt remote logs or belt remote logs -f to read them.
With --exec, registration sends exec_enabled: true and the daemon accepts command-dispatch frames. With --agents, registration sends agents_enabled: true and the daemon hosts harness sessions the API opens over the socket (remote_session_* frames). Without each flag, the corresponding frames are refused on the host. Exec and agent sessions are independent opt-ins — you can enable either or both.
Detached daemon. belt remote start --detach keeps the socket open in the background. Use belt remote status, belt remote logs -f, and belt remote stop to manage it. belt remote list shows remotes registered to your team in the API.
Connection state. belt remote status follows the socket for as long as the daemon runs. state is connected or retrying, with how long it has held, for example retrying (for 54m12s). While it is retrying, reason carries the server's answer to the last attempt (server answered 401 Unauthorized) or the transport error, and hint names the fix when retrying alone will not get past it. The daemon logs the same lines on every change.
Logins. The daemon reads belt's credential again before every connection attempt, so it outlives the login it was started with. When a session expires or is replaced, the next reconnect is refused with 401; run belt login and the daemon reconnects with the new login on its next attempt, within 30 seconds, without a restart. The team does not follow: the remote stays in the team that was active when it started, and belt auth switch in another terminal does not move it. On a server, an API key scoped to remotes:read and remotes:write (belt login --key, or INFSH_API_KEY in the daemon's environment) is not tied to a login session's lifetime.
With --agents, registration sends agents_enabled: true and the platform can list harness sessions on the machine and open chats that run the harness in a folder you choose. When a profile reports capabilities.approvals: true, risky tool calls wait for your approval in the workspace; harnesses with approvals: false (Pi today) run tools without asking. Without --agents, the status output shows agents: disabled.
Start at boot
A remote started with belt remote start does not come back after a reboot. On Linux with systemd, belt remote enable installs it as a service instead:
1belt remote enable --name build-box --exec --agents # same flags as start2belt remote status # mode: service, started at boot3belt remote disable # remove the serviceenable writes a systemd user unit (~/.config/systemd/user/belt-remote.service), enables it, and starts it. No root is needed: the service runs as you, with your login and the PATH you enabled it from, so harness discovery finds the same CLIs your shell does. If a remote is already running on the machine, enable asks before restarting it as the service, because stopping it ends its agent sessions; decline and the service takes over at the next boot.
| Behaviour | Detail |
|---|---|
| Boot | Starts when the machine boots. This needs lingering for your user; enable turns it on with loginctl enable-linger, and prints the sudo command to run when it is not allowed to. Without lingering the service starts at your first login. |
| Crash or failed start | Restarted after 15 seconds, for as long as it takes. A boot with no network yet is a failed start. |
belt remote stop | Stops it until the next boot. A clean exit is not restarted. |
belt remote status, logs | Work as for any remote. The service logs to the same file as a detached daemon. |
Changing --name, --exec, --agents | Run belt remote enable again with the flags you want. |
belt remote disable | Removes the unit. A remote running at that moment keeps running until you stop it. |
Stopping or restarting the service ends the commands and agent sessions the daemon was running. A process a command deliberately left behind (a server started with nohup, for example) is not killed, the same as with a remote started by hand.
List and remove remotes
Account-level commands (run from any machine where you are logged in):
1belt remote list # name, host, id, status, exec, last seen, belt version2belt remote rm <id>... # remove stale rows from your account3belt remote rm <id> --yes # skip the confirmation promptbelt remote list marks the row for this machine when a local daemon is running. After a machine has been offline for more than a week, list prints a hint to remove it with belt remote rm.
belt remote rm calls DELETE /remotes/{id}. Use it for retired or reinstalled hosts that left an old registration behind. It is destructive (confirmation prompt, --yes in non-interactive mode). Removing a row does not stop a daemon that is still running on that host — run belt remote stop there first. If a stopped daemon starts again later, registration creates a new remote id (same machine key, fresh account row).
System info
Registration and periodic heartbeats include a best-effort snapshot of the host in system_info (collected with gopsutil, the same approach private engines use):
| Field | Meaning |
|---|---|
hostname | Machine hostname |
os | OS label: the distro PRETTY_NAME on Linux, macOS on macOS, otherwise the Go OS name |
cpus | One aggregate entry with name, cores, optional frequency, and usage (0–100% across all cores) |
ram.total, ram.used, ram.usage | Physical memory in bytes and used percentage (0–100) |
volumes | Optional. One entry for the filesystem that holds your home directory (where harness sessions and opened folders live): path, size, used, free, and usage percent |
A probe that fails reports a zero value. Registration does not fail because of it.
While the daemon stays connected, every third WebSocket heartbeat (~15 seconds at the default 5 second interval) carries an updated system_info. The API stores each snapshot on the remote, so GET /remotes/{id} and the workspace remote page can show live load the way engine cards do. The first heartbeat after connect omits system_info because registration already sent one; CPU usage on later snapshots reflects load since the previous collection. The HTTP heartbeat endpoint does not carry system_info.
Harness discovery
The daemon probes the host using the agentprotocol harness registry and sends the results in the harnesses field of POST /remotes. Each entry describes one registry harness whose binary was resolved on the machine (PATH, known install paths, or global package lists):
| Field | Meaning |
|---|---|
kind | Registry id for the harness (for example claude, codex, cursor). Profiles also expose display_name and vendor for UI. |
command | Resolved path to the harness binary |
version | Harness version from discovery. Best effort, may be empty. |
logged_in | true when the harness looks configured on this machine. It does not prove the harness can serve a run. |
capabilities | What hosted sessions can do with the session driver belt would use for this harness (see below). Omitted when the harness cannot be driven from inference. |
Probes run in parallel for every registry harness. The daemon checks config directories, PATH, known install locations (for example ~/.local/bin), and a cached global npm list -g (10 second timeout for the whole list). When a binary is found, it runs <command> --version with a 3 second timeout per harness. A stalled or slow binary leaves version empty instead of blocking registration. A machine with several CLIs usually finishes discovering agent harnesses... in about a second before registering remote... appears.
Discovery uses the shared harness registry in agentprotocol (harness.DetectInstalled). Every registry entry with a resolvable binary on the host is reported; kind is the registry id (for example claude, codex, gemini, cursor). Examples:
kind | Typical binary | logged_in hint |
|---|---|---|
claude | claude | Harness config directory present (for example ~/.claude/) |
codex | codex | ~/.codex/ config present |
gemini | gemini | ~/.gemini/ config present |
cursor | cursor-agent | Cursor CLI config present |
logged_in means the harness looks configured on this machine (Configured() in the registry). It is not proof the harness can serve a run. Discovery never reads credential files or transmits tokens.
The API exposes harnesses as profiles on each remote (harness_kind, command, status, capabilities). On every POST /remotes the server reconciles the harnesses payload into profiles, one per harness kind. A harness with logged_in: true becomes idle; without it the profile is unavailable. If a harness disappears from the host, its profile stays and becomes unavailable.
capabilities on a profile mirror what the daemon reported at registration. The API branches on these flags instead of hard-coding harness names:
| Field | Meaning |
|---|---|
steer | A prompt sent during a running turn can redirect it |
approvals | The harness can pause on tool permission requests |
interrupt | A turn can be cancelled without ending the session |
resume | A session can be reopened by harness session id after the process exits |
tools | The caller can supply tools for the harness to call |
capabilities is omitted on older daemons or harnesses the session host cannot drive (no session driver in the registry); treat missing values as false.
Registration keys on the machine's public_key within your active team (from your API key or belt auth switch). Restarting belt remote start on the same host updates that team's remote and its profiles; it does not create a duplicate. After you switch teams, the same machine gets a separate remote row for the new team. Remotes for other teams remain in the list until heartbeats go stale and the platform marks them disconnected, then stopped.
Agent harness sessions
When --agents is enabled, the daemon hosts one harness process per chat the API opens on this machine. Inference owns the conversation, run lifecycle, and every permission decision; the daemon launches the harness, forwards events, and applies prompts, interrupts, and permission resolves the API sends.
How harnesses are launched. The session host picks a driver from the agentprotocol registry for each harness id:
| Harness | Driver | What runs on your machine |
|---|---|---|
claude (Claude Code) | Native | Your claude binary over its stream-json control protocol |
codex | Native | Your codex binary via codex app-server |
| Other harnesses with a session driver | ACP | The harness CLI in Agent Client Protocol mode |
Belt passes only the resolved binary path. It does not add registry auto-approve flags, pinned models, or endpoints. Tool permission prompts always reach inference so a person can allow or deny them. The harness uses your vendor login from its own config; credentials never pass through the daemon.
- One chat, one session. Re-opening the same chat attaches to the existing process instead of starting a second writer.
- Open before launch.
remote_session_openreserves the chat slot beforeremote_session_openedis sent; the harness starts in the background so a prompt right behind the open waits on the session instead of racing the launch. - Event position on open.
remote_session_openedincludesseq, the last event number the session has produced (0for a fresh process). Callers use it to tell a restarted harness from a replay after reconnect. - Replay buffer. While the socket is down, the daemon keeps a bounded buffer of session events so the API can
replayafter reconnect. - Host limits. The daemon caps concurrent harness sessions (default 8) even when a profile allows more.
- Local session index. Call
GET /remotes/{id}/sessions(or the WebSocketremote_sessions_listframe) to see harness sessions on disk — metadata only: id, title, cwd, last updated, and whether a process currently holds the session. The daemon returns at most 500 sessions, newest first. When liveness is inferred rather than proven,live.heuristicistrue(the workspace remote page marks those states with?in the UI). - Closing sessions. When inference sends
remote_session_close, or you stop the daemon (Ctrl-C,belt remote stop, or process exit), the daemon asks the harness to end. If the process is still running after a short grace period, belt kills it when the session driver supports that, so a wedged agent cannot hold a slot or block shutdown. Stopping the daemon ends all hosted sessions in parallel. ACP-backed harnesses also report closed when their CLI process exits on its own.
Harnesses without a session driver in the agentprotocol registry are not offered for hosted sessions (capabilities is omitted at registration).
Wire format: Remotes API — WebSocket protocol.
Profile-backed agent chats
When you start the daemon with --agents, registration only exposes harness profiles on the remote. Workspace agents are created when you launch a harness from the app or API — not when the machine connects — so connecting a laptop does not fill your agent list.
Launch from the workspace. Pick a remote, harness profile, and folder; the UI calls POST /remotes/{id}/sessions and opens the returned chat. Optionally pick an existing harness session to resume (from sessions listed for that folder).
Launch from the API. Same endpoint — profile_id, work_dir, and optional resume_session_id. See Launch harness chat.
The first launch for a profile creates one harness agent and reuses it afterward:
| Agent field | Value |
|---|---|
title | {display name} · {remote name} — for example Claude Code · work-laptop |
harness | Agentprotocol registry id for the profile (claude, codex, …). inference is the default for template agents you deploy yourself. |
profile_id / remote_id | Bound to that harness profile and remote |
| Versions | Harness agents do not use editable platform versions — instructions, tools, and skills come from the harness on your machine. |
Each chat carries the folder in work_dir and optional harness_session_id when you resume. Harness sessions are folder-bound; the agent record is not.
Send messages with POST /agents/run, POST /chats/{id}/messages, the SDK, or the workspace. The API opens the harness session on your remote in that folder, streams replies into the chat, forwards permission prompts as approval interrupts, and records harness-side tool calls without re-running them on inference.sh. Harnesses that report capabilities.steer: true (for example Claude Code and Codex) accept follow-up user messages during an in-progress turn; others queue them for the next turn.
Requirements: the remote must stay connected with --agents, the profile must be idle with valid capabilities, and the harness must remain logged in on the host. See Agents API — Remote harness runs for run lifecycle, queueing, stop, and error strings.
Disconnect. If the daemon drops while a harness run is active, the run fails with the remote disconnected and is not retried. Restart belt remote start --agents and send a new message to continue the conversation (the chat keeps harness_session_id when the harness can resume the session).
Run a command
Dispatch a command to a connected remote and stream its output:
1belt remote exec <remote-id> -- ls -la2belt remote exec <remote-id> -- bash -c "echo hi && uname -a"| Flag | Purpose |
|---|---|
--cwd <path> | Working directory on the remote |
--timeout <seconds> | Kill the command after N seconds (0 = no limit) |
--pty | Run under a pseudo-terminal |
The remote must have been started with belt remote start --exec. Otherwise the API returns 403 exec_disabled.
belt remote exec is marked destructive and prompts for confirmation before dispatching. In CI or scripts, pass --yes / -y, or call the REST API directly.
Exit behavior. belt exits with the remote command's exit code when the run status is exited. Runs that end as killed or denied print an error and exit 1.
Stopping a command. Pressing Ctrl-C in belt remote exec kills the command on the remote and waits for the run to end; a second Ctrl-C exits without waiting. To kill a run started elsewhere (by an agent's remote_exec, or through the API), use its run id:
1belt remote kill <run-id>... # confirms first; --yes to skipThe run id is the exec_run_id in a remote_exec result, or the id of a run from the Exec Runs API. belt remote kill reports killed <id> once the remote confirms the run ended, and says so when it does not.
A kill, like a timeout, ends the whole process tree. Each run gets its own process group, and the daemon kills the group, so what sh -c "build && serve" started dies with the shell. This is why a run id is enough: there is no need for pkill -f, which matches on command text and also matches the shell that runs it. A process that left the group on purpose (setsid, a daemonizing server) survives; the run still ends, two seconds after the kill at the latest.
Disconnects. A short network drop marks the remote disconnected but does not kill commands already running on the host. Runs fail when the remote stays disconnected long enough to reach stopped (about 30 seconds) or when you signal them. Start the daemon again before that grace ends if you need long-running execs to survive a laptop sleep or Wi‑Fi outage.
REST API
For automation, use the exec and session APIs:
POST /remotes/{id}/execscreates a runGET /execs/{id}/output?after_seq=Nreturns sequenced stdout/stderr chunksGET /execs/{id}returns the run statusPOST /execs/{id}/signalcancels a running execGET /remotes/{id}/sessionslists harness sessions on a connected remote with--agents(see List harness sessions)POST /remotes/{id}/sessionsopens a new harness chat in a folder (see Launch harness chat)
These calls need the remotes:read and remotes:write scopes; launching a harness chat also needs agents:execute. Full reference: Remotes API and Exec Runs API.
From agents
Agents can run commands on connected remotes when you enable the Remotes internal tool category (internal_tools.remote: true). The runtime exposes remote_list and remote_exec — the same exec-run domain as the REST API and belt remote exec, with the remote's --exec opt-in and API scopes still enforced. remote_list reports each remote's exec_enabled flag (whether the daemon started with --exec).
When inference drives a coding harness on your machine (a chat bound to a remote profile), the remote must be connected with --agents as well. Shell commands from the Remotes internal tools still require --exec only.
remote_exec completes asynchronously: the agent turn waits on the tool invocation until the exec run finishes (like an app tool waiting on its task). The run also appears as an execution node in the chat trace. Stopping the chat signals in-flight exec runs through the same graph sweep that cancels app tasks. If the remote disconnects before the command ends, the run becomes killed with error remote disconnected before the command finished so the turn does not hang.
→ Internal Tools: Remote tools
Troubleshooting
| Symptom | Likely cause |
|---|---|
not logged in | Run belt login or set INFSH_API_KEY |
agents_disabled | Restart the daemon with belt remote start --agents |
exec_disabled | Restart the daemon with belt remote start --exec |
remote_offline | The daemon is not connected. Run belt remote start on the host. |
belt remote status shows retrying with server answered 401 Unauthorized | The login the daemon holds expired or was replaced. Run belt login on that machine; the daemon reconnects on its next attempt (within 30 seconds). |
belt remote status shows retrying with server answered 403 Forbidden or 404 Not Found | The current login may not use this remote (a different account), or the remote was removed with belt remote rm. Log in as the account that started it, or belt remote stop and start again to register it. |
| The remote is gone after a reboot | It was started by hand. Run belt remote enable with the same flags to start it at boot. |
starting at boot needs systemd | belt remote enable supports Linux with systemd. Elsewhere, use belt remote start --detach and your platform's own service manager. |
a remote is already running on this machine | A start with the same --exec / --agents as the running daemon. Run belt remote status, then stop or disconnect that session, or start with different flags to get a restart prompt. |
left the running remote as it is; 'belt remote stop' then start again | You declined restarting to change --exec or --agents, or confirmation failed in non-interactive mode. Run belt remote stop, then belt remote start with the flags you need. |
Unknown flag on belt remote --exec | Pass flags to belt remote start (the error repeats your flags with start in the command). |
a remote daemon is already running | Same as above when starting with --detach directly. |
harness_not_drivable | The harness is installed but the daemon cannot drive it (no capabilities on the profile) |
| Launcher card shows too old | The harness CLI on the host is below the session driver's minimum. Run support.upgrade_cmd on the machine (shown on the card), then restart belt remote start so discovery picks up the new version. |
| Launcher card is ready with a yellow version warning | The installed build is outside inference's tested range or could not be matched to the registry. You can still launch; upgrade when convenient if you hit issues. |
| Harness profile shows idle but launch or chat fails with a sign-in error | The harness CLI on the host is signed out. Sign in there (for example claude login), then restart belt remote start so enrollment re-runs discovery. Keyring-only harnesses can look idle when only the config directory exists; file-based harnesses need the registry login file (for example ~/.codex/auth.json). Cursor: export CURSOR_API_KEY in the same environment as the remote daemon (systemd unit, container env, or shell) so discovery sees key-only auth; a bad or revoked key can still fail on the first turn. |
| Chat on thinking for ~1 minute, then a failed turn | The harness did not finish opening within 60 seconds — often blocked on sign-in or an update in the terminal. Run the same CLI locally in the project folder, complete any prompts, then send again. |
| Turn failed: did not start a session within | Same as above: the harness CLI on the host must reach a drivable state within 60 seconds of open. |
Turn failed after ~2 minutes with no message, tool call, permission request or response / no_response | The harness accepted the prompt but never showed a sign of work (stuck starting MCP servers, waiting on a backend, or wedged). Read the agent stderr tail in the error or belt remote logs, fix the CLI on the host, then send again. |
| Long coding turn used to stop around 10 minutes | Older belt builds capped whole ACP prompts at 10 minutes. Current belt (agentprotocol v0.12.1+) only bounds time until the first sign of work (2 minutes); after that the turn runs until the harness finishes. Upgrade belt on the machine running belt remote start. |
| Turn failed: no session for chat / session ended / failed to open | The daemon no longer holds that chat's session (restart, crash, concurrent session limit, or a prior open failure). Start a new session from the remote page or launch a fresh chat. |
remote_timeout on session list | The daemon did not answer within 10 seconds — check connectivity |
Session list error right after belt remote restart | Heartbeat can mark the remote running before the WebSocket is back. Wait a few seconds or click refresh; the page retries listing automatically. |
| discovering agent harnesses... for more than ~15 seconds | A hung npm list -g or many harnesses timing out on --version. Upgrade belt (agentprotocol v0.10.2+), or run npm list -g manually to fix npm. |
Harness session closes with agent sessions are disabled on this remote | Restart the daemon with belt remote start --agents |
Run ends as denied | The API could not deliver the command to the daemon |
Run ends as killed with command execution is disabled on this remote | The daemon refused the run. Restart it with --exec. |
Run ends as killed with remote disconnected before the command finished | The remote missed heartbeats long enough to go disconnected or stopped while the command was still running. Restart belt remote start and dispatch again. |
Agent run fails with the remote disconnected | Same disconnect sweep while a profile-backed harness turn was in progress. The turn is not retried; send a new message after the daemon reconnects. |
Agent run fails with this remote does not run agent sessions | Start the daemon with belt remote start --agents. |
Agent run fails with the harness this agent runs on is not available | Harness logged out, profile unavailable, or missing session capabilities — fix login on the host and reconnect the daemon. |
| No output | Poll /execs/{id}/output with an increasing after_seq cursor |
Next
→ CLI setup: command table and automation notes
→ Remotes API: register, list, update, and delete remotes
→ Exec Runs API: dispatch commands and read output