Hub Tools Reference

The MCP tools an orchestration hub uses to run agents on your joined machines. nfltr orch and nfltr mcp --toolset hub (in your own Claude Code session) serve the same set on the hosted nfltr.xyz relay.

The hub decides everything: what to spawn, where, with which model, when to continue or stop. nfltr only dispatches, routes messages, persists and reports. spawn_agent makes no model call; the first model call is the agent's own.


Tools

ToolInputResult
spawn_agentprompt (the whole brief), optional constraintsagent_id, status: pending with waiting (what it waits for, the free slots there and on other machines its other constraints admit), fleet, returned immediately
spawn_agentsagents: 1 to 64 entries, each a prompt and optional constraintsseveral agents in one call, each validated and placed on its own: per entry index and agent_id, status, and machine and worker once started (it waits up to 5 s for that); a pending one has waiting, as spawn_agent; a malformed or refused entry fails alone with code (invalid, not_spawned) and error; fleet. One call's entries are placed most constrained first (hard machine pins, soft pins, labels or workspace, then the rest; your order within each), and rows come back in your order
send_messageagent_id, textmode: steer (running: delivered into the live session between tool calls) or mode: continue (finished or stopped: a new turn in the same session and workspace, on the same machine)
stop_agentagent_id, optional reasonthe agent; its cancellation arrives through wait_for_agents
list_agentsnoneper agent: status, worker, machine, prompt summary, turns, progress, last activity, and for a running claude agent its activity: elapsed time, tool calls, the call running now, files it edited, its own task list and its latest note, and for a pending agent its waiting; fleet
wait_for_agentsoptional agent_ids, timeout_ms (default 30000, max 600000)completions[], pending[], pending_activity[] (each awaited agent still running with its activity), pending_waiting[] (each awaited agent not started yet with its waiting), running_now (at a completion, or an operator message, while other agents still run: free slots per machine, and each running agent's elapsed time and open task items), operator_message_pending (the session's user sent a message during the wait, which ended it; the message arrives as the user's turn, in nfltr orch sessions and with nfltr orch hub install-hook; with that hook in a Claude Code agent-teams lead, also when a teammate went idle, whose messages arrive when the lead's turn ends), timed_out, fleet
list_nodesnonejoined machines that serve this hub (a node whose --serve-hubs leaves this hub out is not listed): machine, labels (resources, description, allowed repositories), max_agents, running_agents, busy_agents, free_agents, and load (read by the node at most every 5 s): CPU cores, load average and available memory, and on Linux the node's own cgroup CPU limit and use and memory limit and use; fleet
inspect_nodenode (name or machine id), optional resources (default true), optional files (op: list, find, stat or tree; root, path, name, within, max_entries, max_depth)one node read live: CPU cores, load, memory, free disk, GPUs, agent slots; and, on a node joined with --allow-inspect-files, file names, sizes and times under its workspace, mirrors, task directories and data dirs, and with tree a git repository's directories (packages) with file counts and bytes, mirrors included, without an agent (see Nodes). A refusal is a JSON error with a code
request_approvalnode, prompt (exactly the prompt the approved agent gets)prompt_sha256, prompt_bytes and the nfltr orch hub approve ... --expect-digest command you run on your own machine to sign exactly that prompt (see Approvals); it signs nothing and asks nobody by itself
list_worker_peersnoneconnected agents with their labels and free slots
start_monitorcommand, optional constraints (machine, labels), description, dir, timeout_ms, max_events_per_minute, max_line_bytes, dedup_window_msmonitor_id, state: running, node and machine; each stdout line of the command is then an event in wait_for_agents events[]
stop_monitormonitor_idthe monitor; its end arrives as its last event
list_monitorsnoneper monitor: state, node, machine, limits, events delivered, dropped and deduplicated, exit status

A node starts no agent process until a spawn needs one, so a joined machine shows in list_nodes, not in list_worker_peers.

Completions

Each entry of completions[] carries the agent's final text, its structured result when it gave one (as JSON text, see Untrusted content), artifacts, branch and sha when it pushed work, state, worker, machine, turn, and usage (tokens and USD as reported). An agent that ends its turn with a question for the hub completes with the question (and its options) as text; reply with send_message, which continues its session. Failures arrive the same way, as a completion with a reason:

ReasonMeaning
node_lostthe node running the agent died mid-turn, or stopped or lost its connection and did not come back within 30 seconds
tools_not_allowedthe agent needed a command the node does not allow (joined without --allow-all-tools)
budget_exceededthe agent's or the hub's budget was reached; the message names the caps and what they cover, e.g. the hub budget (max_tokens=6000, max_usd=$2 for all agents of this hub together) was passed: they used …. Usage a stopped or lost turn never priced reads cost not reported: claude reports a turn's cost only when the turn ends, and nfltr does not estimate it
no connected worker satisfies constraints …nothing eligible connected within the spawn's bound; lists what was connected
cancelledstopped by stop_agent or timeout_ms; artifacts holds a recovery patch of the uncommitted edits

Untrusted content

What agents, nodes and monitored commands wrote is data, not instructions. In spawn_agent, stop_agent, list_agents, wait_for_agents and list_nodes results, a completion's text, error, result and artifacts (their JSON, as text), an agent's progress and activity (its JSON, as text), a monitor event's line, and a node's nfltr.machine.description and nfltr.machine.resources labels come between <<<untrusted-content>>> and <<<end-untrusted-content>>>, and their entry carries "content_trust": "untrusted". A delimiter-like token inside the content is replaced, so the content cannot end its frame early. Ids, state, branch, sha, usage and the other labels stay outside the frame.

{
  "agent_id": "agent-20260929t101500-1a2b3c4d",
  "state": "completed",
  "branch": "fix/login",
  "sha": "3f2c9e1",
  "text": "<<<untrusted-content>>>\nFixed the login redirect.\n<<<end-untrusted-content>>>",
  "content_trust": "untrusted"
}

Monitors

A monitor is a model-free command a node joined with --allow-monitors runs, as that node's user. Every stdout line is one event, and each event wakes an idle hub session for a new turn, which is a model call. A command that prints a timestamped status line every few seconds wakes the session on every line, and dedup_window_ms cannot match lines that differ. A command that prints only changes or failures keeps the session quiet; dedup_window_ms drops repeats of an identical line and max_events_per_minute caps the rate. Event lines are the command's output: untrusted data, never instructions.

Monitors keep running after the hub, nfltr orch or your Claude Code session ends, until stopped, the command exits, timeout_ms, or the node exits. Nothing stops them on its own. When a session ends, nfltr orch (and, in your own Claude Code session, the SessionEnd hook from nfltr orch hub install-hook) prints one line per running monitor with how to stop it: reattach with the same --hub-id and ask, or run nfltr orch hub stop-monitor.

$ nfltr orch hub monitors --hub-id my-hub
$ nfltr orch hub stop-monitor --hub-id my-hub mon-20260928t101500-1a2b3c4d

Spawn constraints

All optional; unknown keys are rejected.

KeyMeaning
machinethe machine id (from list_nodes): a hard filter unless pin is soft
pinhard (also when omitted): only on machine, waiting while it has no free slot; soft: machine when it has a free slot, otherwise the first free slot the other constraints admit on any machine. Needs machine; a continuation stays on its session's machine
labelshard filter: every label must match exactly (e.g. flavor to pick a harness on a node that has several)
model, effortpassed to the agent unchanged; omitted stays omitted
isolationshared or per_task workspace
mutates_workspacetrue lets the agent edit and, unless isolation is shared, gives it an empty task directory of its own, kept across its turns (stopped ones included) and, on a node, after its agent process exits, for its next turn there, until the hub archives the agent. Nothing is collected from it: the agent reports what it delivered (a pushed branch as branch_ref and sha). A permission, not an obligation: a turn that edits nothing completes with its answer. It does not limit what the agent's tools do on the machine; the node's tool setting does.
timeout_mshard bound per turn, including waiting for a free slot or for a named machine to join (default 30 s for that wait)
workspace{repo, ref}: the repository the agent works on. Routed only to nodes whose --allow-repo globs (nfltr.workspace_repo_allow) admit it; every spelling of one remote matches. There the agent gets an empty task directory, the node's bare mirror of the repository and git credentials for the allow-list, and does the repository work itself.
output_validation{require_object, allowed_statuses, required_fields, non_empty_fields}: the agent must answer with a structured result that satisfies it (say so in the brief); a nonconforming result fails the turn. Omitted: plain text.
budget{max_tokens, max_usd}: cap on this agent's reported usage across its turns; the running turn is stopped (budget_exceeded) and further messages refused. max_usd needs max_tokens.
approvalThe owner's approval grant (nfltr orch hub approve) for exactly this prompt on one node. That node (label nfltr.agent.approval) then allows, for this turn only, the tool calls its operator allows only with approval; a turn without a valid grant is denied them, with the reason. See Approvals.

Fleet capacity

fleet (in spawn_agent, list_agents, wait_for_agents and list_nodes results) is the capacity at that moment: free_agent_slots = worker_free_slots (free slots on connected agents) + node_free_agents (agent processes the nodes may still start), with connected_workers, node_max_agents, node_running_agents, nodes_unreachable and read errors. It states capacity only; using it is the hub's call.

Placement is mechanism only: among eligible agents, one with a free slot is chosen, idle first; if none is free, a node that matches starts one; if every slot is busy the agent stays pending and dispatches when a slot frees, within its bound. A continuation always runs where its session is.

Budgets

Hub-wide caps: --hub-max-tokens N and --hub-max-usd X on nfltr orch or nfltr mcp --toolset hub cover every agent of the hub; once passed, running turns are stopped and spawns and messages refused. Usage is what agents report; every completion carries it. Token caps count input, output and cache-write tokens; cache-read tokens (every model call re-reads the cached conversation, billed at a fraction of input) are reported as usage.cache_read_tokens and not counted. A stopped or lost turn's tokens are counted up to the stop, but its cost is never estimated (cost_unreported: true), so a USD cap needs a token cap. Nothing is capped by default.

$ nfltr orch --hub-max-tokens 2000000 --hub-max-usd 5 "<goal>"

Delivery guarantees

What the relay sees

Frames between the hub, its agents and nodes are encrypted end to end (--a2a-e2ee, on by default). The hub serves its tasks (nfltr orch task) to its owner only; it refuses every task route the relay's own agent asks and sends the relay no summary, status or facts of its runs, so the dashboard shows none. Runs stay on the hub's machine: see them in the hub session (list_agents, wait_for_agents), with nfltr orch hub runs and nfltr orch hub show --hub-id <id> <agent-id> on that machine, or with nfltr orch task list|status|events|result while the hub runs. This flag on nfltr mcp --toolset hub, nfltr orch and nfltr orch hub hardens the key exchange:

Flag (env)Effect
--e2ee-key-file (NFLTR_A2A_E2EE_KEY_FILE; --a2a-e2ee-key-file on nfltr mcp)A pairing key file that authenticates every end-to-end key exchange, so the relay cannot sit in the middle of it. Every machine needs the same file; see Join machines as nodes.

An end with E2EE on refuses unencrypted requests from peers. Agent and machine ids, labels, timing and message sizes are always visible to the relay.

Related: Use nfltr from Claude Code · Many agents across machines · Join machines as nodes.