For agents
Set up WorkerKit in Meta Muse.
Connect Muse to the WorkerKit API at api.workerkit.ai, plain HTTPS described by OpenAPI, then choose a job and bring back a useful result. The person approves account access and enters the credential through Muse's hosted entry. Muse prepares the worker and checks deployment, funding and budget before running.
Before you start
What you need.
A WorkerKit account, and admin access on it: manager keys are an admin-only surface. The Free plan is enough, and no card is needed.
Meta Muse, on any of its platforms, able to add a custom connector for a service that has an API.
An account admin to approve the manager key and enter it through Muse's hosted credential entry. Running a job also needs app access, an enabled deployment, model funding and budget headroom.
| What | Address | Why |
|---|---|---|
| API base | https://api.workerkit.ai | Every request goes here, and nowhere else: plain HTTPS and JSON, the server both OpenAPI documents name. |
| Fleet OpenAPI document | https://api.workerkit.ai/openapi/workers.json | The protocol: an OpenAPI 3 description of every fleet operation, with its method, path, operationId, the scope it needs and its request and response shapes. The agent reads it to build each request; Muse does not import it. |
| Catalog OpenAPI document | https://api.workerkit.ai/openapi/directory.json | The same for the public catalog and the kit authoring guide, which need no key. Their routes sit under /api/directory/mcp/, a path on this API, not an MCP server. |
| AI access | https://workerkit.ai/fleet-access | Where an account admin creates the manager key. Admin only. |
| Skill file | https://workerkit.ai/muse/SKILL.md | The endpoint reference and the operating rules the agent installs in step 4. |
| Kit-authoring skill | https://workerkit.ai/build/SKILL.md | The procedure for building, validating and publishing a kit of your own. Load it when the person wants a custom worker. |
| This guide as markdown | https://workerkit.ai/muse/setup.md | The same steps, for an agent that reads markdown rather than a page. |
Why this route: Muse adds an outside service as a custom connector over its API rather than as an MCP server, so it uses the WorkerKit API at api.workerkit.ai, with OpenAPI as the protocol. Every request the agent sends is described in the fleet OpenAPI document above, and a snake_case name this guide gives beside a route, such as worker_get beside GET /api/manage/workers/{tokenId}, is that operation's operationId there, not an MCP tool. The case for connecting at all is on the Muse page.
Step 1. Human
Create the manager key.
An account admin creates a key at workerkit.ai/fleet-access, picks its scopes and copies it once. The agent cannot do this part.
- 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 is the most common setup mistake, and it shows up later as an empty fleet.
- 02
Open AI access
workerkit.ai/fleet-access is an admin-only page. A member sees a notice saying so rather than a broken page.
- 03
Create a manager key named for its purpose
"Muse" is a good name. A purpose-specific name makes the key easy to audit, and easy to revoke later without touching anything else.
- 04
Pick its scopes
The table below says 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.
- 05
Copy the key once
It is shown at creation and never again. It goes nowhere but Muse's credential entry in step 2: not into the chat, a document, a screenshot or a file.
| Scope | What it grants |
|---|---|
readWorkers | The fleet list, worker detail, fleet health, account usage, an Action worker's tools, and reads of memory, schedules and the instruction. |
readRuns | Run history, run detail, run events, a run's stored transcript, and activity feeds and counts of runs, app calls and configuration changes. 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. |
runWorkers | Run now, one worker or up to 20 in one call, and cancel. |
invokeActions | Call an Action worker's selected tools and read the receipts of its writes. Cannot change the tools, connection or permissions. Existing keys need explicit re-scoping. |
manageMemory | Add, edit, retire and delete rules and facts; clear a run's report; grade a run. |
manageSchedules | Create, edit and delete schedules, and set a worker's own time zone. |
manageInstructions | Create or replace a language worker's instruction, and answer a decision worker's install questions. |
manageState | Start and stop a worker. |
installKits | Preview and install a directory kit as a new worker. |
manageAppsAndWorkers | Change what an existing worker may reach: replace its app set (account Admin) and fill, re-point or clear its grants to call other workers. Rules, identities and MCP tool bindings stay in the dashboard. |
manageDeliveries | Create, 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. |
manageBudgets | Read and change a worker's spend and run ceilings and the fleet ceiling; read spend by worker, day and model, plus wallet charges with whole-account reach. Its own scope because raising a dollar cap is the one management action that can cost money without starting anything. |
createWorkers | Create an Action worker or a decision worker from scratch in one call, and clone a worker into new ones, singly or in bulk, with a dry-run preview. A clone carries only permissions a person already approved on the source, while a worker created from scratch gets the app access its request asks for, so this is a separate power from installing a reviewed kit. |
publishKits | Author 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. |
manageConnections | Connect 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. |
manageDeployments | Deploy 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. An Action worker is never deployed. Reading the deployment and the model catalog rides on readWorkers. |
deleteWorkers | Delete 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. |
readWallet | Read spendable wallet balance, fees and account checkout status. |
requestWalletTopUp | Create a human-confirmed Stripe Checkout link and inspect purchases requested by this key. Does not authorize charging a saved card. |
discoverAppResources | Discover private setup metadata across your workspaces: connected GitHub accounts, repositories and branches, and Slack workspaces and conversation IDs. Does not read contents or grant worker access. Existing keys need explicit re-scoping. |
managePrivateApiApps | Define account-private API operations, worker bindings and private kits. Connection changes also require manageConnections. |
readKnowledge | Discover sources, search published reports, read evidence and reconcile changes. Publication, reader grants and credential worker limits still apply; no transcript or source-app access. |
manageKnowledge | Read and replace company Knowledge settings. Requires current account Admin authority and an unrestricted worker ceiling. Existing keys need explicit re-scoping. |
| Key | Scopes | What Muse can then do |
|---|---|---|
| Observer | readWorkers, readRuns | Describe the fleet and everything it has done, and change nothing. Most of the first session's value is here. |
| Operator | add runWorkers, invokeActions, manageState, manageDeliveries | Run workers now, call Action worker tools, start and stop them, and route their reports. |
| Full automation | add manageSchedules, manageMemory, manageInstructions, manageBudgets, createWorkers | Schedule, teach, rewrite, cap and clone workers, and create Action or decision workers from scratch. manageInstructions rewrites a worker's tested method, so it is the one to withhold longest. |
| Builder | add installKits, publishKits, manageConnections, manageDeployments, deleteWorkers | Install directory kits as new workers, author and publish kits, connect apps by credential and register your own MCP servers. manageDeployments is what puts an installed worker on the hosted runtime: without it the worker exists but never runs, and a run request answers 409 not_deployed. |
A key carries the scopes it was granted when it was created, not the ones that exist today. Granting a scope later never reaches an existing key: if a call answers 403 OPERATION_NOT_ALLOWED, an admin re-scopes the key at AI access or creates a new one. Read key-info rather than assuming.
Step 2. Human and agent
Store the key where Muse keeps credentials.
The person enters it through Muse's own hosted API-key entry, never the chat. From then on the agent calls https://api.workerkit.ai directly with a bearer header, building each request from the OpenAPI document.
- 01
Hand the key to Muse, not to the chat
The person enters it through Muse's own hosted API-key entry, the path Muse's documentation describes as credentials.request_api_access. An agent offers that entry; it never asks for the key in a message. Muse's documentation is the authority on where that sits in its interface, and this guide does not second-guess it.
- 02
Let Muse hold it
By Meta's published design, a credential you connect is stored in your own VM and inserted at the network boundary by Sentinel, so the agent only ever handles a stand-in. From here on the agent works with a reference, and the raw key must never appear in a command, a log, a file or a message.
- 03
Call the API directly
The protocol is OpenAPI over plain HTTPS: the agent makes ordinary requests to https://api.workerkit.ai, sending Authorization: Bearer pe_mgr_... on each one, and looks up each operation's method, path, operationId, scope and body in https://api.workerkit.ai/openapi/workers.json. Nothing registers a base URL and nothing imports that document: the agent reads it. Muse's VM has a shell, so the wk CLI is the other shape that works: install it there and let it carry the same key.
Do not go looking for a form that takes a base URL and an API description. WorkerKit is reached by holding a credential for it and calling it, the way Muse reaches any service with an API: there is no MCP server to add, and the OpenAPI document is something the agent reads, not something Muse imports. If a request fails auth later, read the code the response carries rather than assuming the key is wrong; the troubleshooting table below has the full set.
Either shape works from Muse's VM: plain HTTPS requests, or the wk CLI installed there and carrying the same key. The CLI is generated from the same tool definitions the API publishes, so nothing it can do is missing from the requests, and nothing here depends on which you pick.
Step 3. Agent
Verify the scopes.
GET /api/manage/workers/key-info. The scope list it returns is the truth, whatever was intended.
- Ask the key what it can do
GET /api/manage/workers/key-info
It returns the account name, the key's scopes and expiry, and serverTimeUtc; any valid key may ask. Confirm the scope list matches what was granted in step 1. If anything is missing it was either not granted, or granted after the key was created, and the person goes back to AI access to re-scope or create a new key. Do not proceed on a partial scope set without saying what is unavailable.
Step 4. Agent
Install the WorkerKit skill.
Fetch https://workerkit.ai/muse/SKILL.md into the skills directory Muse reads, and re-read it before first use.
- Fetch the skill file into the skills directory Muse reads (~/workspace/skills on the workspaces we have seen)
mkdir -p ~/workspace/skills/workerkit && curl -fsSL https://workerkit.ai/muse/SKILL.md -o ~/workspace/skills/workerkit/SKILL.md
The file is a standard skill: a name and a description in its front matter, then the endpoint reference, the cost-field semantics and the safety rules the agent needs. Save it as workerkit/SKILL.md under whichever directory this workspace reads skills from, and re-read it before first use. The command above uses ~/workspace/skills, which is where the Muse workspaces we have seen keep them; if yours differs, use yours, because a file written where nothing reads it installs nothing.
Step 5. Agent
Run the smoke test.
Verify the account with fleet reads, then review the selected worker, deployment, funding and budgets. Run the approved job and inspect the result, cost and delivery.
Successful fleet reads confirm the connection. For an empty account, choose a kit at workerkit.ai/kits or use the API installation path with installKits and manageDeployments after approval, setting deploy to true. Connect the required apps, check the enabled model deployment, usable funding and budget headroom, then run the job. Report connection success separately from a completed result.
Choose a small job that represents the intended use. Inspect its instructions and effective app grants, then confirm the input, expected output and any app changes. For a read-only test, use a worker whose grants permit reads only; for an action kit, review and approve the specific writes. Check the model deployment, funding and per-run, daily and account budgets before execution. App grants enforce access independently of the prompt.
- 1. The fleet list: report how many workers Muse can see
GET /api/manage/workers - 2. Recent runs across the fleet: confirms readRuns
GET /api/manage/workers/runs?limit=5 - 3. Before running anything, read what that worker does and what it may touch. Both rides on readWorkers, and this is the step that decides whether the run is safe
GET /api/manage/workers/{workerId}/instruction GET /api/manage/workers/{workerId}/permissions - 4. 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
POST /api/manage/workers/{workerId}/run {} GET /api/manage/workers/runs/{runId}/events?afterSeq={lastSeq} - 5. Read the receipt: costAuthority first, then modelCostUsd
GET /api/manage/workers/runs/{runId}
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.
For a Skipped run, use skipReason to complete the named readiness or funding step before another attempt. Keep the run ID and check that run after a timeout before starting another. Inspect the actual output and cost, verify delivery to the chosen destination, then enable the approved schedule with its time zone. Report connection, job and delivery status separately.
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.
Discover recipes with GET /api/directory/mcp/authoring/tools?purpose=decision and read GET /api/directory/mcp/authoring/guide?section=decision; both are anonymous. Check connections with GET /api/manage/apps, then send the request to POST /api/manage/decision-workers. Use the returned worker with the existing deployment, run and instruction endpoints in the workers OpenAPI document. Running needs runWorkers; results need readRuns. Saved setup answers adjust categories/levels; a structural question or source change needs 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 createWorkers; 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.
App tools, no model
Call app tools through an Action worker.
One exact app operation per call, with the inputs you supply.
An Action worker (modelType: "none") exposes 1 to 64 selected app tools and has no model, instruction, schedule or deployment. Each call invokes one tool with the arguments the caller sends, under the worker's own app access, and readiness.canInvoke on GET /api/manage/workers/{tokenId} (worker_get) says whether its tools can be called now. Run and deploy requests answer 400 action_worker_requires_invoke.
Discover apps with GET /api/manage/workers/action-options (readWorkers), then select one with ?app=<code> for tool schemas and defaults. Omitting app selects no tools. Create with POST /api/manage/workers/actions (createWorkers): {"requestId":"...","name":"...","app":"<code>"} copies that app's default tools; add "actionSpec":{"schemaVersion":1,"tools":[{"ref":"<tool>","version":1}]} to choose 1 to 64 instead, and slackConnectionId for Slack tools when the account has more than one Slack bot. It answers 201 with tokenId, workerId and kitSlug; repeat a requestId only with the same body. GET /api/manage/workers/{tokenId}/tools (readWorkers) lists the saved tools. POST /api/manage/workers/{tokenId}/tools/{toolName}/invoke with {"contractVersion":1,"arguments":{...}} calls one (invokeActions), with an Idempotency-Key header on a write. GET /api/manage/workers/{tokenId}/tool-invocations/{invocationId} reads a write's receipt (invokeActions). GET /api/directory/mcp/kits?modelType=none finds Action kits; install one without deploy.
An explicit actionSpec needs no app and can span native or reviewed MCP apps. Private API tools require a dashboard binding to a published version; they are not actionSpec refs.
A write tool (readOnly: false) needs an idempotency key. Repeating the key with the same arguments returns the stored receipt (a confirmation, not the app's response) without calling the app again; with other arguments it is a 409. A call answers with status succeeded, denied, failed, in_progress or outcome_unknown; branch on it, not on the HTTP code. On outcome_unknown the write may have happened: never resend it automatically, under any key; read the receipt and check the app. Each call counts toward the worker's daily request limit; a refusal marked retryable, such as usage_limit, is retried later under a new key. Only the owner changes the selected tools, in the dashboard.
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 API, not advice.
| Rule | What it means |
|---|---|
| Confirm before changing the fleet | Running, 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. An Action tool call that writes needs the same approval, naming the tool and its arguments. |
| Know what a run will do before you start it | A run can send mail, post, write or spend, and the person approving it is trusting your reading of the worker. Read the instruction and the permissions first (both ride on readWorkers) and say what the run will touch. Approval is not informed if neither of you knows. |
| One host, no raw keys | Authenticated requests go to api.workerkit.ai and nowhere else. Never print, log or persist the raw key. |
| Rate limits, per account | The fleet surface allows 120 requests a minute and 1,200 an hour; run triggers 30 a minute (the bulk trigger, up to 20 workers a call, 2 a minute and 20 an hour); 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; Action routes 120 a minute in a window of their own. On a 429, wait out Retry-After (the body is plain text). Extra machines buy no extra budget. |
| Send a body on every POST | At least {}: a POST with no Content-Length is refused at the edge with an HTML 411 page before it reaches the API, and that page is not an API error. It bites on the bodyless actions first: cancel, delivery secret rotate, instruction restore, and the kit unpublish, relist and make-private calls. |
| Runs in flight per worker | Set by the plan, not per worker: Free 5, Pro 20, Team 50, Enterprise uncapped; the budget read reports it and the budget PATCH does not take it. A worker at its limit lands the next on-demand run as Skipped with skipReason ConcurrencyLimit. A schedule never overlaps itself: a scheduled fire that finds any run of that worker in flight is Skipped whatever the plan allows. |
| Watching runs | Poll a run's events every 3 to 5 seconds and pass afterSeq so each call returns only what is new. To watch the whole fleet, hold GET /api/manage/workers/runs?wait=60: one connection covers every worker, up to four held per account, and it always returns within the wait. |
| 404 not_found | The worker is missing or belongs to another account, and the two are indistinguishable by design. Never claim which. |
| 403 OPERATION_NOT_ALLOWED | The key lacks a scope, and the message names it. A wider key is the fix, not a retry. |
| Time | Compute every age, deadline and countdown against the response's serverTimeUtc (on key-info, the fleet list and the fleet pulse), never against your own clock. |
| Skipped is not an error | Read skipReason: DailyRunCap, DailySpendCap, FleetSpendCap, ConcurrencyLimit, InsufficientCredits, DeploymentPaused, TokenDisabled or a readiness reason. Retry only when the reason clears on its own. |
| Money | Read 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. |
Troubleshooting
Symptoms, causes, fixes.
| Symptom | Cause and fix |
|---|---|
401 | Read 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. The full table is below. If the surface hides the code, check that the credential was attached before asking anyone for a new key. |
403 OPERATION_NOT_ALLOWED | A scope is missing. Read key-info; an admin re-scopes the key at AI access or creates a new one (the snapshot rule). |
404 not_found on a worker | Missing, or on another account. Verify the id, and that the key belongs to the account that owns the fleet. |
429 | Rate limited. Honour Retry-After; the per-account windows are in the operating rules. |
402 limit_exceeded or feature_gated | A plan wall, and terminal: an admin raises the plan or removes a worker. Retrying will not help. |
422 RUNTIME_NOT_ENABLED | The account's hosted runtime is switched off. A capability switch, not a transient error. |
Empty fleet on a new account | Expected, and not a fault: an account has no workers until someone installs a kit or clones one. The setup is still proved, because the key authenticated and the reads answered. |
Empty fleet, or the wrong workers, on an account that has some | The key was created in a different WorkerKit account. Create it in the account that owns the fleet. |
| Status | Code | When |
|---|---|---|
401 | auth_required | The Authorization header is missing or malformed. |
401 | auth_failed | The key is unknown or has been revoked. |
401 | manager_key_expired | The key passed its expiry. |
403 | account_paused | The account is paused; every key on it is refused. |
429 | auth_throttled | Too many failed attempts from your network. JSON, unlike the rate-limit 429. Honour Retry-After; a valid key is never throttled. |
The second table is the auth set in full, the same one the API page carries: each failure names itself in the response, so an agent never has to guess which one it met.
Keep work moving
Connect, collect results and deliver reports.
- 01
Connect with approved API access
Use the scoped manager key entered through Muse's hosted credential flow. Confirm the account, permissions and expiry before operating its workers.
- 02
Collect results through the fleet feed
Use a held feed request to watch the fleet, then read each relevant run receipt. Muse can summarize the result and use it in the next part of the task.
- 03
Deliver to the people who need it
Configure reports for the channels connected to the WorkerKit account, such as email, Slack and Teams. Verify the first delivery and include the worker and run links for follow-up.