Set up WorkerKit in Hermes.

Written for the agent doing the setup and the person approving it. Hermes reaches a remote MCP server by URL and sends whatever request headers you declare beside it, so the whole connection is two entries in one YAML file and a manager key in the env file next to it. The person creates the key and pastes it once. Their part is about a minute.

Before you start

What you need.

A Hermes Agent install you control: the gateway on Linux, macOS, WSL2, native Windows, Nix or NixOS, Docker, or Android under Termux. This guide documents that install, because it is the one whose MCP configuration Nous Research publishes.

The ability to edit files on that machine, over a shell or in an editor. The credential goes into ~/.hermes/.env and the two server entries go into ~/.hermes/config.yaml beside it, so neither is entered in a form.

A WorkerKit account with admin access: creating the manager key is an admin-only action. The Free plan is enough, and no card is needed.

About a minute of the human's time. The agent can write the YAML, install the skill, verify the scopes and run the test; only the key has to be created and pasted by a person.

WhatAddressWhy
Directory MCPhttps://mcp.workerkit.ai/directoryThe public kit catalog and the authoring guides. No credential at all, so its config entry carries no headers block and it can be wired first.
Workers MCPhttps://mcp.workerkit.ai/workersFleet operations, behind a bearer manager key on an Authorization header. This is the mount that runs and configures workers.
Hermes MCP config referencehttps://hermes-agent.nousresearch.com/docs/reference/mcp-config-reference/Nous Research's key reference for mcp_servers: url, headers, transport, the timeouts and the tools filter. The authority for every YAML key below.
Hermes config file~/.hermes/config.yamlWhere both mounts are declared. `hermes config edit` opens it.
Hermes env file~/.hermes/.envWhere the manager key belongs, so config.yaml carries a variable reference instead of a secret.
Fleet accesshttps://workerkit.ai/fleet-accessWhere an account admin creates the manager key. Admin only.
Skill filehttps://workerkit.ai/hermes/SKILL.mdThe tool reference and the operating rules the agent keeps after setup.
This guide as markdownhttps://workerkit.ai/hermes/setup.mdThe same steps, for an agent that reads markdown rather than a page.

Why this route: Hermes is a full MCP client, and a server entry carrying a url is a remote HTTP connection over streamable HTTP unless transport is set to sse. Beside it, headers is an ordinary mapping of request headers, so a WorkerKit manager key goes on an Authorization header and there is nothing else to arrange: no client to register, no redirect address, no refresh cycle. They are the same WorkerKit MCP mounts every other client takes.

Hermes can run an OAuth 2.1 flow instead, and the WorkerKit fleet mount is itself an OAuth authorization server, so that combination exists. Nous Research recommends against it for a remote gateway in as many words: "always prefer headers.Authorization: 'Bearer <token>' when the user is willing. Simpler, no refresh dance." Its reasons are practical: Hermes registers a 127.0.0.1 callback, which resolves to the browser you are sitting at rather than to the box the gateway runs on, and an expired refresh token on a remote gateway can need a restart rather than a reload. A static header has neither failure, so this guide takes the vendor at its word.

One honest limit, worth reading before you start. Nous Research also runs Hermes Cloud, managed hosting in the Nous Portal, and a cloud agent is a real Hermes agent. How an MCP server is configured on a cloud deployment is not something the vendor documents today: the guide whose title sounds like it would answer this describes the reverse, a Hermes on your own machine managing cloud instances through MCP. So this procedure is written for an install you control, and the cloud path waits on the vendor rather than on our guess.

One address is worth reading twice: workerkit.ai/mcp is the documentation page, and the live mounts are on mcp.workerkit.ai. The table above has both in full.

The case for connecting at all is on the Hermes page.

Step 0. Human, minutes if Hermes is not installed yet

Put Hermes on a machine you control.

The connection is a file on the machine the gateway runs on, so the first decision is which machine that is.

Nous Research puts macOS on Apple Silicon, Windows 10 and 11, Linux and WSL2, and Docker containers in its first tier, with Nix and Android under Termux supported on a best-effort footing. A few features are unavailable on Windows and on Android and the vendor does not enumerate which; a Docker install cannot use hermes update; macOS on Intel is unsupported.

  • Confirm the gateway answers, then open the file this guide edits hermes config path hermes config check hermes config edit

A laptop is fine for trying this. A small server or a container is the better home, because a Hermes agent answers only while its process is up, and that is the difference a hosted fleet beside it makes: a WorkerKit worker keeps its schedule whether or not Hermes is running.

The local Hermes Web Dashboard (hermes dashboard, port 9119) and Hermes Desktop both register MCP servers, and neither is the path here. The vendor documents their MCP form as taking a name, a URL, a command, arguments and KEY=VALUE environment variables; custom HTTP headers are not among the documented fields, so the Authorization header goes in config.yaml. The dashboard binds to 127.0.0.1 with no authentication on loopback, and a non-loopback bind engages its own auth gate, which is worth knowing before putting it on a server.

Step 1. Human, about 60 seconds

Create a manager key.

One key, named for this Hermes install, scoped to what the agent should be able to do. It is shown once.

  1. 01

    Sign in as the account that owns the fleet

    At workerkit.ai. Someone who belongs to several accounts confirms the active one first: a key created in the wrong account shows up later as an empty fleet, and checking now saves that round trip.

  2. 02

    Open Fleet access

    workerkit.ai/fleet-access is an admin-only page. A member sees a notice saying so rather than a broken page.

  3. 03

    Create a manager key named for its purpose

    Name it for the assistant that will hold it. A purpose-specific name makes the key easy to audit, and easy to revoke later without touching anything else.

  4. 04

    Pick its scopes

    The tables below say what each one grants. Start with the reads and add only the scopes needed for the approved task. Choose an expiry and request fresh approval when more access is needed.

  5. 05

    Copy the key once

    It is shown at creation and never again, so keep it to hand for the wiring step. It reaches the fleet only: no scope on it reads a mailbox, a calendar or a CRM.

KeyScopesWhat the assistant can then do
ObserverreadWorkers, readRunsDescribe the fleet and everything it has done, and change nothing. Most of the first session's value is here.
Operatoradd runWorkers, manageState, manageDeliveriesRun workers now, start and stop them, and route their reports.
Full automationadd manageSchedules, manageMemory, manageInstructions, manageBudgets, createWorkersSchedule, teach, rewrite, cap and clone. manageInstructions rewrites a worker's tested method, so it is the one to add last.
Builderadd installKits, publishKits, manageConnections, manageDeployments, deleteWorkersInstall directory kits as new workers, author and publish kits, connect apps by credential and register your own MCP servers. installKits is the one a brand-new account wants first, because it is what puts a worker in an empty fleet. manageDeployments is what puts an installed worker on the hosted runtime: without it the worker exists but never runs, and a run answers not_deployed.

A client that cannot run an OAuth flow takes the same fleet on one header instead. An account admin creates a key at https://workerkit.ai/fleet-access, copies it once, and it becomes the value of an Authorization header on the fleet mount. That header is the whole of the authentication: there is nothing to register and nothing to pre-approve.

A key carries the scopes it was granted when it was created. Granting a scope later never reaches an existing key: if a call answers 403 OPERATION_NOT_ALLOWED, an admin re-scopes the key at Fleet access or creates a new one, and the new key drops into the same place. Read key_info rather than assuming.

Step 2. Agent, or a person with an editor

Declare both mounts in config.yaml.

Two entries under mcp_servers: the catalog with no credential, the fleet with one Authorization header whose value comes from the env file.

Leave transport unset. An entry carrying a url is streamable HTTP by default, which is what both WorkerKit mounts speak; sse is the opt-out, not the setting.

  • Both entries under one mcp_servers key (~/.hermes/config.yaml) mcp_servers: workerkit_directory: url: "https://mcp.workerkit.ai/directory" workerkit_workers: url: "https://mcp.workerkit.ai/workers" headers: Authorization: "Bearer ${WORKERKIT_MANAGER_KEY}"
  • The key itself, kept out of config.yaml (~/.hermes/.env) WORKERKIT_MANAGER_KEY=pe_mgr_...
  • The CLI registers a server too, and the header value then goes in the YAML hermes mcp add workerkit_workers --url https://mcp.workerkit.ai/workers --auth header

The catalog mount takes no credential at all, on either path. It is the fastest proof that the client can reach WorkerKit, and it is worth adding first for exactly that reason: if it connects and the fleet mount does not, the problem is the credential rather than the wiring.

The headers key is optional, which is what makes the catalog entry a one-liner: no headers block means no credential is sent, and the public mount wants none. The fleet entry is that same entry with the header added. mcp_servers is one top-level key holding both, so a file that already has it takes the two entries underneath rather than a second copy of the key.

Put the key in ~/.hermes/.env and reference it rather than typing it into config.yaml. Hermes resolves ${VAR} and ${env:VAR} in any string of a server entry, so the config file stays safe to copy, paste into a support thread or commit. One warning goes with that: an undefined variable is left verbatim with a warning in the log, so a mistyped name ships the literal text as the bearer token and WorkerKit answers 401. The ${file:...} and ${vault:...} prefixes are not resolved inline.

The CLI line above is real and it is the documented way to register a server without an editor. The vendor documents --auth header as a value it accepts but documents no flag for the header value itself, so finish in config.yaml rather than guessing at a syntax.

Step 3. Agent

Reload, and confirm the tools arrived.

A config edit is not live until it is applied. Reload, test each server, then trim the tool list if it is noisy.

  • 1. Apply the edit immediately, from the chat /reload-mcp
  • 2. Test each server on its own, and list what is registered hermes mcp test workerkit_directory hermes mcp test workerkit_workers hermes mcp list
  • 3. Choose which tools the agent sees, per server hermes mcp configure workerkit_workers

A running gateway watches config.yaml and picks an edit up within about a minute, so /reload-mcp is the impatient path rather than the required one. If neither takes effect, restart the gateway.

Then prove it from the agent side rather than the CLI side: ask Hermes to call one of the WorkerKit tools and report what came back. Tools arrive under a prefix derived from the server name you chose, and the vendor's pages spell that prefix two different ways, so match on the WorkerKit tool name (key_info, workers_list) rather than on the prefix, and do not expect the bare name in the tool list.

If the combined list crowds the context, narrow it with tools.include or tools.exclude under the server entry: both take fnmatch globs, include wins when both are present, and an entry with no glob characters matches exactly. resources: false and prompts: false drop the resource and prompt wrappers. Leave the fleet mount whole on a first setup, because the operating rules below assume key_info, fleet_health and account_usage are all reachable.

Step 4. Agent

Verify the scopes.

Call key_info on the fleet mount. The scope list it returns is the truth, whatever was intended in step 2.

  • Ask the key what it can do (no arguments) key_info

It returns the account title, the key name, the key's scopes and expiry, and serverTimeUtc; any valid key may ask. A missing scope was either never granted or granted after the key was created, and the fix is an admin re-scoping the key or creating a new one: the new value drops into the same line of the env file and one reload picks it up. This call is also the cleanest proof the header is being sent, because a 401 with auth_required means the header never arrived, which is a YAML or env fault, while auth_failed means the key itself is unknown or revoked.

Step 5. Agent, one command

Install the WorkerKit skill.

Hermes takes a skill from a direct HTTPS address, so keeping the operating rules is a single line.

  • Install it, then confirm it landed hermes skills install https://workerkit.ai/hermes/SKILL.md hermes skills list

Hermes follows the open agentskills.io standard: a skill is a SKILL.md with YAML front matter (name, description, version, platforms, metadata) and optional references, templates, scripts, assets and examples beside it, loaded when it is relevant rather than held in context. The source of truth is ~/.hermes/skills/, and the WorkerKit file is a plain SKILL.md, so the address above is the whole install.

A skill installed from an address is security-scanned on the way in: a non-dangerous finding can be overridden with --force and a dangerous verdict cannot, by design. hermes skills update refreshes it later, which matters because the tool reference changes when the wire does. The skill stays a convenience rather than a dependency: an agent that reads the same URL at the start of a session has identical content.

Step 6. Agent

Run the smoke test.

List the fleet and read recent runs, which alone prove the setup. If the account has workers, read one before running it, run it with approval, and report the receipt.

If the fleet is empty, stop after step 3 and say so: a new account has no workers yet, and the steps above have already proved the setup, because the key authenticated and both read scopes answered. Do not read it as a fault, and do not invent a worker to run. Go to the first-worker step and give the fleet something to do.

If the fleet has workers, pick one whose effects are reads. Judge it from the instruction and the permissions, never from the name: a worker whose apps are all read-level and whose instruction only gathers, summarises or reports is safe to run; one that sends, posts, writes, orders or pays is not, whatever it is called. If none is clearly read-only, run one with an explicit prompt for that run bounding it to a read.

  • 1. The directory is alive: confirm a kit count comes back directory_overview
  • 2. The fleet list: report how many workers the assistant can see workers_list
  • 3. Recent runs across the fleet: confirms readRuns runs_feed { "limit": 5 }
  • 4. Before running anything, read what that worker does and what it may touch. Both ride on readWorkers, and this is the step that decides whether the run is safe instruction_get worker_permissions_get
  • 5. Run it with the person's approval, then poll every 3 to 5 seconds until a terminal event arrives: run.succeeded, run.failed, run.blocked or run.awaiting_input worker_run run_events { "afterSeq": <lastSeq> }
  • 6. Read the receipt: costAuthority first, then modelCostUsd run_get

Read costAuthority first, then modelCostUsd beside it, and report both. A null finalDigest is not a failure: a run produces one only when its harness wrote a report. A costAuthority of unbilled_estimate, none or in_flight is not a failure either; it says how far to trust the number, and the operating rules below say what each value means.

A Skipped run is also a pass, and it is the cost brake working: the gate refused the run before any money moved. Report the skipReason rather than retrying. Then report the fleet size, the active scopes, and what the test cost, and the fleet is live.

Step 7. Human and agent

Give the fleet its first worker.

A new account starts empty. Install a kit from its page in one click, or let Hermes preview and install one with kit_install_preview and kit_install once the person approves.

A new WorkerKit account starts with no workers, so the last step of setup is getting one. A kit is a ready-made worker: its instruction, its exact app permissions and its schedule, written and reviewed in advance, so installing one is how a fleet usually starts rather than a shortcut. There are two paths, and either ends with something to operate.

  1. 01

    The one-click path: install a kit from its page

    Browse the catalog at workerkit.ai/kits, open a kit whose job you recognise, and install it. It arrives pre-instructed, pre-permissioned and pre-scheduled, and asks for whatever it needs to connect. This path needs no scope on the manager key at all, so it works on the first session whatever the key can do.

  2. 02

    The agent path: shortlist, preview, approve, install

    With installKits on the key, the assistant can do the whole thing in chat: shortlist with kits_search, read the candidate with kit_get, then call kit_install_preview to surface its setup questions and exactly what the new worker would be allowed to touch. Put that in front of the person in plain words, and call kit_install once they approve, with deploy set to true so the new worker is actually able to run (that half needs manageDeployments on the key; without it the worker is installed but inert until worker_deploy). The new worker's key is shown once in the response.

  3. 03

    Then run it once and read the receipt

    A worker earns its place on the first run. Trigger it with worker_run, follow run_events until a terminal event arrives, and report the digest and the settled cost from run_get. Set a schedule with schedule_create when the person is happy with what it did, and the fleet is not just connected, it is working.

The catalog mount needs no credential, so Hermes can read the whole directory before the fleet mount is even wired: it shortlists candidates and explains what each would do while the person decides. That is also why step 3 declares it first.

Step 8. Agent, optional

The second door: the wk CLI.

Hermes runs on a machine you control and carries terminal tools, so the same fleet is reachable by running commands as well as by speaking MCP. Either door is complete; wire the one this runtime is already holding.

The commands are generated from the same tool definitions the MCP server serves to agents, so the CLI is not a cut-down view of the fleet: what an agent can do over MCP, a shell can do. Which one a runtime reaches for is a question of what it is already holding, not of what it can reach.

  1. 01

    The catalog needs no account at all

    wk about, wk kit search and the rest of the directory side read the public catalog exactly as a visitor does. Run wk about first in any session: it is what WorkerKit is and when to use it, written for an agent, and it needs no key.

  2. 02

    Headless: put a manager key in the environment

    An account admin creates a key at https://workerkit.ai/fleet-access and it travels as the WK_MANAGER_KEY environment variable, which is the path written for scripts and agents. It touches no profile and no keychain, so a container or a restarted process picks it up from its own environment rather than from state on a disk.

  3. 03

    Start headless, approve on any device

    wk auth login --start --no-browser --json returns an approval URL and code. Add --email when the person requests email delivery. They sign up or sign in, choose their account, scopes and expiry, and approve. Run wk auth login --resume --json after at least five seconds to collect the approved key into local credential storage. No raw key appears in output. Interactive wk auth login opens a browser and waits.

  4. 04

    Read the output as data

    --json is a stable machine contract rather than a pretty-printer, --plain strips the chrome for a narrow terminal, and exit codes are documented. Parse --json; never scrape the human output, which is free to change.

CommandsWhat they cover
wk auth login / wk onboarding / wk walletStart or resume browser-approved account signup and login from a headless machine, inspect funding requirements, and request a Stripe checkout for the person to pay. JSON output never contains a login credential.
wk aboutWhat WorkerKit is and when to use it, written for an agent: the request shapes that call for a worker, how a fleet is operated, the access model, the money rules, and how to connect. No sign-in needed; the first command an agent should run.
wk workersThe fleet: every worker with its live state, one worker in full, start and stop, what it may touch, its spend ceilings, and cloning it into new workers.
wk run / wk runs / wk fleetTrigger a run with a prompt for that run, watch it step by step, read the receipt, cancel or grade it; answer a run that ended by asking a question; the account-wide run feed, everything in flight, and the fleet ceiling. On a decision worker wk run decides instead and acts on what it routes: --source-args and --max-items narrow and cap what is judged, and --wait-seconds waits for the settled receipt and its per-item decisions.
wk memory / wk instructionThe rules and facts a worker carries into every run, and its standing instruction, versioned on every change with the history to roll back to. On a decision worker wk instruction get reads the routing table and its install questions, --options-for lists one app pick's live options, and wk instruction set --answers fills them.
wk schedules / wk deliveriesWhen a worker starts on its own, in its own time zone, and where its run report goes when it finishes.
wk kit / wk publisherThe public directory: search kits, read one in full, preview an install against your account, then install it as a new worker. And authoring: explore what every app lets a worker do, read the guide and the vocabulary, validate, publish a kit of your own (private first), and keep your publisher profile.
wk apps / wk model-keys / wk mcp-serversWhich apps your operator can use and connecting the rest by credential; your own model-provider keys; and registering an MCP server as your own custom MCP app when the platform does not offer the app.
wk decision sources / wk decision guide / wk decision createDiscover classification recipes and create a private kit plus decision worker from typed questions. Read JSON from --file or stdin; optionally deploy, never run automatically. Reuse the returned worker with the existing deploy, run and instruction commands.
  • npm npm install -g @workerkit/cli
  • Homebrew brew install workerkit/tap/wk

Nothing above changes on this path. The scopes on the key are still exactly the reach, an approval is still needed before anything that alters the fleet, and the cost fields still mean what they mean. What changes is only where the call is made from.

The full command reference is the wk CLI page.

Classification on demand

Create a decision worker from your questions.

Categorize, score or triage connected data, then reuse and adjust the worker.

Reuse an existing worker or decision kit when its questions fit. For a custom classification task, creation compiles a supported source recipe and typed questions into a private kit and an installed decision worker. Optional deploy:true adds deployment; creation never starts a run or adds a schedule. The kit can be edited and published later through the normal kit lifecycle.

On the workers connection, call kit_app_tools(purpose:"decision") for recipes, argument schemas, permissions and examples, then kit_authoring_guide(section:"decision"). Check account connections with apps_list; public discovery does not check them. Send the request to decision_worker_create, follow nextCall, then use worker_run and run_get. Running needs runWorkers; results need readRuns. Use instruction_get / instruction_set for saved category or level answers, or answers on one run. Structural question/source changes need a revised kit and a replacement install. Check receipt status, coverage, omissions, warnings and cost before claiming completion.

Start with email-previews, calendar-events or sheets-rows. These recipes return judgments without app writes. Email previews do not include full threads; calendar events are invitation data, not transcripts; Sheets needs a Google file ID, a finite tab-qualified range and a columns map. A connected app alone does not make every tool a supported source. Source filters select evidence, not permissions: the Sheets recipe grants spreadsheet reads across the linked Drive account.

Supply 1–8 questions: choice with named options, score with ordered levels, or noul for the probability of a statement. Choice adds unclear automatically. Set an explicit confidenceFloor between 0 and 1; it routes uncertainty and does not promise accuracy. maxItems is 1–50, default 20. Creation requires publishKits and installKits; optional deployment also needs manageDeployments.

Use a fresh requestId for each new worker. Retry with the same ID and identical body to recover the original receipt; a changed body returns 409. The response includes tokenId for MCP/CLI worker commands, stable workerId, kitSlug, readiness and nextCall. A deploymentError means the worker already exists: fix deployment on that worker. The receipt is a snapshot; check current worker readiness before running. No worker API secret is returned.

The workers connection includes discovery and authoring, so classification needs one MCP connection. Its full profile has 91 tools (84 manager tools and 7 public discovery reads); only decision_worker_create is new. For a smaller list, a client that supports custom headers can send X-WorkerKit-Profile: decision on every request, including initialization, listing and calls, to select 20 workflow tools. A server operator can instead set MCP_WORKERS_PROFILE=decision. The endpoint and existing sign-in stay the same; a profile grants no additional permissions. Reconnect and relist after changing profiles. Use the advertised tool list: fleet administration, publishing and event-stream tools require the full profile. Successful responses include structured content and a text fallback; creation declares an output schema.

Read the request example and full contract.

Least privilege

What each scope grants.

The key's scopes are exactly its reach, and a refusal names the scope it wanted. Start with the reads and add scopes as the work asks for them.

ScopeWhat it grants
readWorkersThe fleet list, worker detail, and reads of memory, schedules and the instruction.
readRunsRun history, run detail, run events and a run's stored transcript. A receipt returned by a waiting run request is run content too: without this scope the run still starts and the receipt comes back with contentWithheld.
runWorkersRun now, one worker or up to 20 in one call, and cancel.
manageMemoryAdd, edit, retire and delete rules and facts; clear a run's report; grade a run.
manageSchedulesCreate, edit and delete schedules.
manageInstructionsCreate or replace a language worker's instruction, and answer a decision worker's install questions.
manageStateStart and stop a worker.
installKitsPreview and install a directory kit as a new worker.
manageDeliveriesCreate, edit and delete run-result delivery destinations: where the platform sends a run report when the worker finishes. Reading them rides on readWorkers. Availability is judged per account, so ask the channels operation rather than inferring it from the worker apps.
manageBudgetsRead and change a worker's spend and run ceilings, and the account-wide fleet ceiling. Its own scope because raising a dollar cap is the one management action that can cost money without starting anything.
createWorkersClone a worker into a new one, singly or in bulk, with a dry-run preview. The only non-kit creation path: a clone carries permissions a person already approved on the source.
publishKitsAuthor kits: validate (a dry run that reports every gate at once), publish from content or from an owned worker, edit, replace, unlist, relist, make private, delete, and edit the publisher profile. A private kit installed with installKits is how a worker is built from scratch through the reviewed manifest pipeline. The anonymous Directory API serves the authoring guide, the live permission vocabulary and the per-app tool explorer; reads of your own kits ride on readWorkers.
manageConnectionsConnect and disconnect apps for your operators by credential: every family the Apps page accepts by paste (bot tokens, API keys, private-app tokens), validated live against the provider, stored encrypted, never returned; register your account's own MCP servers as custom MCP apps (with their credentials) and enable their tools; and set or remove your account's own model-provider keys. Reading which apps are connected, with a recipe for connecting each, rides on readWorkers. Google, Microsoft, GitHub and Reddit are browser sign-ins and stay on the Apps page.
manageDeploymentsDeploy a worker onto the hosted runtime and manage that deployment: its model and reasoning, its transcript setting, its spend ceilings, pause and resume, and undeploy. This is the step that makes an installed worker run at all: without a deployment it fires no schedule and a run request is refused with not_deployed. Reading the deployment and the model catalog rides on readWorkers.
deleteWorkersDelete a worker permanently: its key stops working, its schedules stop firing, and its instruction, memory, deployment and delivery destinations go with it — as do its sub-workers, because a dead orchestrator must never leave live workers behind. Not reversible by any call, which is why it is its own scope rather than part of start/stop: stopping a worker is reversible and this is not. Run receipts survive, and the freed worker slot is what clears a 402 limit_exceeded on install.
readWalletRead spendable wallet balance, fees and account checkout status.
requestWalletTopUpCreate a human-confirmed Stripe Checkout link and inspect purchases requested by this key. Does not authorize charging a saved card.

Operating rules

What the agent follows on every call.

The same rules the skill file carries, so a session that read neither still has them. Every row is a fact of the platform, not advice.

RuleWhat it means
The key lives in .env, never in config.yamlconfig.yaml is a file people copy, paste into a thread and check into a repository. Keep the manager key in `~/.hermes/.env` and reference it as `${WORKERKIT_MANAGER_KEY}`. Never write the key itself into the config, a skill, a memory file or a message.
A config edit is not live until it is appliedType `/reload-mcp` after editing, or wait: the running gateway watches config.yaml and picks changes up within about a minute. If a change still has not taken, restart the gateway before assuming the server is at fault.
Match tools by their WorkerKit nameHermes namespaces MCP tools under a prefix derived from the server name, and the vendor's pages spell that prefix two different ways. Look for key_info, workers_list and run_get inside the tool name rather than expecting a bare name or a particular prefix.
Read the key before planningCall key_info first in any session that touches the fleet, and plan against the scopes it returns. It also carries serverTimeUtc, which every age and deadline below is measured against.
Confirm before changing the fleetRunning, stopping, deleting or editing a worker changes the person's fleet: state the exact worker and action in plain words and get approval first, unless the person already approved that exact action. Publishing, unlisting or deleting a kit affects the directory and other installers, so confirm those too.
Know what a run will do before you start itA run can send mail, post, write or spend, and the person approving it is trusting your reading of the worker. Read instruction_get and worker_permissions_get first (both ride on readWorkers) and say what the run will touch.
The key is not a secret to repeatIt travels once, where the platform takes credentials, and after that it is sent for you. Never repeat it in a later message, print it, log it, or write it into memory, a skill or a shared file. A key that has been somewhere it should not be is revoked and replaced at Fleet access in under a minute.
An empty fleet has a next stepA new account has no workers until someone installs a kit, creates a decision worker or clones one. Say so plainly, then offer the two paths: the person installs a kit from its page in one click, or, with installKits, you shortlist with kits_search, preview with kit_install_preview and install with kit_install once they approve. Never invent a worker id to have something to run.
Rate limits, per accountThe fleet surface allows 120 requests a minute and 1,200 an hour; run triggers 30 a minute; run-event polls 120 a minute and 2,400 an hour, exempt from the surface windows; the kits surface 60 a minute; kit installs 10 an hour. On a 429, wait out Retry-After. Extra machines buy no extra budget.
Watching runsPoll run_events every 3 to 5 seconds and pass afterSeq so each call returns only what is new. To watch the whole fleet, hold runs_feed with wait: one connection covers every worker, up to four held per account, and it always returns within the wait. fleet_pulse gives the in-flight rows beside it.
Brief from fleet_healthWhen the person asks how the fleet is doing, call fleet_health once instead of crawling workers_list, worker_get and runs_feed: it lists the workers that are blocked, the ones installed but never deployed, the schedules the runtime is not picking up, the runs waiting on an answer, and the last runs that did not end clean. Empty sections are the healthy answer; paused workers are counted, not listed, because stopping one is a decision.
Check account_usage before spendingBefore an install, a deploy or a run, read account_usage: worker slots, hosted slots, spendable wallet balance and request windows. With requestWalletTopUp and permission for the amount, request a wallet_checkout_create link for the person to pay. Otherwise hand them topUpUrl. Only credited confirms committed funds.
404 not_foundThe worker is missing or belongs to another account, and the two are indistinguishable by design. Never claim which.
403 OPERATION_NOT_ALLOWEDThe key lacks a scope, and the message names it. A wider key is the fix, not a retry.
TimeCompute every age, deadline and countdown against the response's serverTimeUtc (on key_info, workers_list, fleet_pulse and fleet_health), never against your own clock.
Skipped is the brake workingA Skipped run is a receipt, not a transport error: the gate refused it before any money moved. Read skipReason (DailyRunCap, DailySpendCap, FleetSpendCap, ConcurrencyLimit, InsufficientCredits, DeploymentPaused, TokenDisabled or a readiness reason) and retry only when the reason clears on its own.
MoneyRead costAuthority before the number beside it: settled, unbilled_estimate, none or in_flight. modelCostUsd is the settled figure; costSoFarUsd exists only while a run is Running.
Cloning multiplies ceilingsA clone carries the source worker's per-run and per-day ceilings, so read fleet_budget_get before worker_clone_bulk and size the fleet ceiling for the copies you are about to make.

Quick answers

Symptoms, causes, fixes.

SymptomCause and fix
401 straight after a clean editThe variable did not resolve. An undefined `${VAR}` is left verbatim with a warning, so the literal text is sent as the bearer token. Check the name in `~/.hermes/.env`, and remember that `${file:...}` and `${vault:...}` are not resolved inline.
No Authorization field in the dashboard or DesktopExpected. The vendor documents that MCP form as taking a name, a URL, a command, arguments and KEY=VALUE environment variables; custom HTTP headers are not among them. Declare the header in config.yaml, and the dashboard still lists, tests, enables and removes the server afterwards.
hermes mcp test connects, but the agent has no WorkerKit toolsReload with `/reload-mcp`, check the server is enabled and that a `tools.include` filter is not excluding everything, then ask the agent for key_info by name rather than hunting the tool list. An entry wired to the OAuth mode belongs on a header instead: that is the path the vendor recommends for a remote gateway.
The first call times outThe documented defaults are a 60 second connect timeout, a 300 second tool-call timeout and a 180 second keepalive, all settable per server. A streamable-HTTP handshake against a public mount sits well inside them, so a timeout usually means the machine cannot reach mcp.workerkit.ai at all: test the catalog mount, which needs no credential.
Too many tools crowding the contextNarrow with `tools.include` or `tools.exclude` under the server entry. Both take fnmatch globs and `include` wins when both are set. Keep the read tools and the ones the person actually asks for, and leave key_info in every time.
401 on the fleet surfaceRead the code rather than guessing: auth_required means the Authorization header never arrived, which is a wiring problem and not a key problem, and auth_failed means the key is unknown or revoked. Re-send it spelled exactly Authorization: Bearer pe_mgr_... and it connects.
403 OPERATION_NOT_ALLOWEDA scope is missing. Read key_info; an admin re-scopes the key at Fleet access or creates a new one, and the new key drops into the same place (the snapshot rule).
404 not_found on a workerMissing, or on another account. Verify the id, and that the key belongs to the account that owns the fleet.
429Rate limited. Honour Retry-After; the per-account windows are in the operating rules above.
Empty fleet on a new accountExpected, and not a fault: an account has no workers until someone installs a kit, creates a decision worker or clones one. The setup is proved already, because the key authenticated and the reads answered. Install a kit to fill it.
Empty fleet, or the wrong workers, on an account that has someThe key was created in a different WorkerKit account. Create it in the account that owns the fleet.

Each WorkerKit failure names itself in the response, so an agent never has to guess which one it met: read the code, apply the row, and carry on.