Agent operations
What an agent operation is, the six kinds, own-harness handoff versus a nima-hosted VM, and how to start, follow and finish one from MCP, Slack or the API.
An agent operation is one unit of agent work that nima tracks from request to result. You start it from Slack, over MCP or over the REST API. There is no page for it in the web app.
Handing a spec to your own coding agent: on for every workspace. Over MCP or the API it needs a key that holds operations:write, which only owners and admins can get. No plan feature is needed.
Running work on a nima-hosted VM: enabled by the nima team on request. See nima-hosted VMs.
What an agent operation is
An agent operation is one unit of agent work on a connected GitHub repository. Each operation has a kind (what to do), a target (who does it), a budget and a state.
- Kind: one of six, listed below.
- Target:
own_harness(your coding agent does the work, nima hands it a brief) ornima_vm(a nima-hosted VM does it). - Budget: AI spend in USD, active minutes and number of sessions. The workspace sets defaults and a maximum.
- State: one of 14 states, from
queuedto a terminal state such aspublishedorfailed.
Every operation is recorded in the workspace, with its usage, end reason and, when it was started from Slack, the thread it came from. Any member can read every operation's state. See Who can see operations.
Operation kinds
nima has six operation kinds. Only implement_spec can run on your own coding agent. The other five need a nima-hosted VM.
| Kind | What it does | Input | Publishes |
|---|---|---|---|
implement_spec | Turns an approved spec into a draft pull request | documentId, repositoryId (pass null to use the spec's repository; the key is required) | new_draft_pr on a VM, nothing on your own harness |
fix_ci | Adds commits to the branch of a failing pull request | repositoryId, pullRequestNumber | append_to_pr |
reproduce_issue | Turns a signal into a failing test and a report | repositoryId, signalId | nothing by default; comment_only or new_draft_pr allowed |
run_checks | Runs the repository's configured test command and stores the log | repositoryId, pullRequestNumber and branch: send both of the last two keys and set exactly one of them to null | nothing by default; comment_only allowed |
browser_check | Serves the app in the VM, takes screenshots and runs tests, then reports | same as run_checks | nothing by default; comment_only allowed |
task | Free-form one-off work (an investigation, a benchmark, try-and-report) that ends in a report, never a pull request | repositoryId, instruction (1 to 8000 characters), baseBranch (a branch name, or null for the default branch; the key is required), optional requesterMessage | nothing, always |
Rules that apply across kinds:
implement_speconly starts for a spec whose status isapprovedorin_progress. Any other status is a 409.- A publish policy that a kind does not allow is a 409
invalid_publish_policy. nima refuses it; it never downgrades it to a report. taskis left out of a workspace'sallowedKindsby default. An admin adds it to allow it.- A
taskinstruction that looks like a credential is refused with a 400. The VM has no network access, so a pasted credential could not be used anyway. taskis for investigation and reports. Feature work goes through a spec andimplement_spec.
Two targets: your own coding agent or a nima-hosted VM
An operation runs either on your own coding agent (own_harness) or on a nima-hosted VM (nima_vm). The target decides who does the work, what it can publish and whether the workspace needs hosted compute.
Hand a spec to your own coding agent
The own_harness target needs no plan feature and no hosted compute. It supports implement_spec only, and it never publishes: nima builds a brief and your agent does the work in your environment. The flow uses three MCP tools, and only the requester can call them:
get_operation_briefreads the handoff brief as Markdown. It starts no VM.claim_operation_handoffmarks the handoff as started. The operation moves fromqueuedtoactive.report_operation_resultrecords what your agent produced (1 to 100,000 characters). The operation moves toreported.
nima stores the result as an external report. It does not attest that tests passed and does not publish code for it. Passing a publish policy other than none on an own-harness operation is a 409.
Run an operation on a nima-hosted VM
The nima_vm target runs the agent in a nima-hosted, isolated VM. It supports every kind. How VMs are enabled, what they can reach and how results reach GitHub is covered in nima-hosted VMs.
How nima picks the target
nima resolves the target with these rules, in order:
- If hosted compute is off for the workspace (the default): asking for
nima_vmis a 409org_disabled; otherwise the target isown_harness, and any kind other thanimplement_specis a 409kind_requires_vm. - If hosted compute is on and you give a
target, nima uses it. - If hosted compute is on and you give none:
implement_specuses the workspace'sdefaultTarget(own_harnessunless changed); every other kind usesnima_vm. - For a VM, the kind must be in the workspace's
allowedKinds, or the request is a 409kind_not_allowed.
nima never falls back silently from a VM to your own harness, and never to a different publish policy.
Getting a key that can start operations
A key that can start operations holds the operations:write scope, and that scope comes only from Slack. The API key form in Settings and the OAuth consent screen do not offer it.
An owner or admin messages @nima in a channel or a DM, or runs the /nima slash command:
@nima mcp-key operationsnima replies privately with a Confirm button. After the admin confirms (or tells @nima confirm <code> in the same channel within 5 minutes), nima shows the key once. The key:
- lasts 30 days;
- holds
operations:write,documents:readandknowledge:read; - does not turn on hosted compute or GitHub publishing.
Only a workspace owner or admin can run mcp-key operations, and the key belongs to that person. Members cannot get operations:write. A member can still start work from Slack with agent ..., which needs no key, but only an owner or admin can start operations over MCP or the API and then claim and report an own-harness handoff.
Configuring hosted compute or publishing needs a separate key from mcp-key integrations, which holds only integrations:write. An admin who wants to both configure and start operations needs both keys. mcp-key list shows your active keys and mcp-key revoke <key-id> revokes one. See Members and roles for who counts as an admin.
Starting an operation
You start an operation from MCP, Slack or the API. All three create the same record.
| Surface | How |
|---|---|
| MCP | Call start_operation with kind and input. |
| Slack | Message @nima with agent spec <document-id> [repository-id], agent checks <repository-id> <branch> or agent task <repository-id> [base:<branch>] <instruction>. Ids are UUIDs. You can also ask nima's Slack assistant in plain words; it resolves the repository by name, starts one operation per request and publishes nothing unless you ask. |
| API | POST /v1/operations, or POST /v1/documents/:id/dispatch as shorthand for implement_spec. |
Details of each surface:
- Scope: an MCP or API caller needs
operations:write; a signed-in browser session skips the scope check. Slack needs no key, but the Slack user must be linked to an active member of the workspace, or the command is dropped without a reply. - Optional fields:
target,publishPolicy,attempts(1 to 10, default 1),note(up to 20,000 characters),budgetandidempotencyKey. - Attempts:
attemptsstarts that many parallel operations and the response is an array of operations. The fleet caps it (3 by default), and a larger number is a 400. - Idempotency: repeat a call with the same
idempotencyKeyand nima returns the operation it already started. Animplement_specrequest without a key uses the spec id and version as its key, so dispatching the same spec version again returns the first operation; pass a newidempotencyKeyto start another. Reusing a key for a different request, including another member's dispatch of the same spec version, is a 409. A Slack command uses the Slack message as its key, so a Slack retry never starts a second operation. - Budget: each budget field must stay within the workspace maximum. A larger value is a 400.
- Slack limits: the command text is at most 1000 characters. A channel set to silent drops the command without a reply. Refusals such as an unapproved spec come back as a private message to the person who asked.
The full route and field reference is in Operations API, and the tools are in the operation tools reference.
Operation states
An operation moves through 14 states, and five of them are terminal.
| Group | States |
|---|---|
| Waiting and starting | queued, placing, hydrating |
| Working | active |
| Pausing | parking, parked, resuming |
| Finishing | exporting, gating |
| Terminal | published, reported, failed, cancelled, expired |
published: nima pushed commits or opened a pull request.reported: nima stored a report or posted a comment, with no code published.failed: the operation stopped before a usable result. A denied admission also lands here.cancelled: someone cancelled it.expired: it stayed parked longer than the maximum parked time.
An own-harness operation only uses queued, active, reported and cancelled. A terminal operation accepts no further events. list_operations filters by a single state value.
Talking to a running operation
You can message, inspect, raise the limit of or cancel an operation while it runs. These calls need operations:write, except inspect_operation, which needs documents:read.
| Action | MCP tool | What it does |
|---|---|---|
| Message | message_operation | Sends a new user turn (1 to 100,000 characters) while the operation is active, hydrating, resuming or parked. It resumes a parked operation, except one paused for its budget or held by nima, which refuses the message with a 409. |
| Inspect | inspect_operation | Queues a request for the transcript or git_diff of a live VM. Accepted means queued, not run. |
| Raise a limit | raise_operation_limit | Sets new absolute caps for aiUsd, activeMinutes or maxSessions. It never lowers a cap and cannot exceed the workspace maximum. |
| Cancel | cancel_operation | Cancels the operation from any non-terminal state and revokes its run credentials. |
Steer, park and resume exist over HTTP only (POST /v1/operations/:id/steer, /park, /resume), with no MCP tool. inspect_operation returns nothing to the caller and works only while the operation is active, exporting or gating.
Only the requester or a holder of operations:write can control an operation. For a task, only the requester can message or steer it, because those messages carry instruction authority. Another holder of operations:write can still cancel or park it.
Operation results and end reasons
Every finished operation records an endReason and an endDetail. The first line of endDetail is nima's own verdict. Text after the line Agent report: is the agent's own account and is untrusted.
endReason | Meaning |
|---|---|
checks_passed, checks_failed, checks_timed_out, checks_not_run | The result of a run_checks or browser_check, taken from the test command's exit code: 0 passes, 124 times out, any other non-zero fails, and no command means not run |
task_completed | A task whose agent reported completion and whose export nima accepted |
task_ended | A task that ended without a completion report but whose export nima accepted |
org_disabled, budget_exhausted, concurrency_limit, daily_limit | Admission denials for a VM operation. Each one is terminal, not queued |
compute_disabled | An admin turned hosted compute off while the operation was live |
gate_rejected | nima's safety gate rejected the result. endDetail lists the rule codes |
list_operations cuts endDetail to its first line. get_operation returns it in full (up to 8000 characters, redacted).
Read a task's result
get_operation_result returns a finished task's output: nima's own diff stat (up to 50 files) and a redacted, size-capped patch for display, not for applying. Only the requester or an owner or admin can call it, and it works only for task operations.
- Size:
maxPatchCharsaccepts 1000 to 120,000 and defaults to 20,000. - Missing patch:
patchUnavailableReasonsays why, with values such asnot_finished,no_changes,too_largeandsecret_suspected. - Retention: stored patches expire after 90 days.
Agent operations in Slack threads
An operation started from Slack reports back in the thread where you asked. nima posts one status message and edits it in place as the state changes, using plain wording such as "waiting to start", "preparing your workspace", "working" and "paused as requested".
- Question: if the agent needs input, nima posts the question in the thread. When the requester replies, nima's Slack assistant passes the answer to the operation, which resumes if it was waiting.
- Result: when the operation ends, nima posts exactly one reply that mentions the requester (edits do not notify). It carries nima's verdict, and for a
taskit also carries nima's diff stat and the agent's report, labelled as the agent's own account that nima did not verify. - Follow-ups: a reply in the thread from the requester goes to nima's Slack assistant, which can message or cancel the operation. It asks which operation you mean when "cancel that" is ambiguous. There is no literal
cancelkeyword.
Replies from other members also reach nima's Slack assistant, but the assistant reads, messages and cancels only the asker's own operations, so it cannot act on someone else's operation. Silent channels get none of these messages.
Who can see agent operations
Any member whose token holds documents:read sees every operation in the workspace: its state, budget, usage and endDetail. The exceptions are the handoff brief and handoff tools (requester only) and get_operation_result (requester, owner or admin).
Operations run inside one workspace. Reading an operation from another workspace returns 404; the handoff tools return 403 for any operation that is not your own own-harness handoff.
People, identities and mentions
How nima links people's Slack, Jira, Linear and Notion accounts to workspace members, and how that decides who it answers, messages and tags.
nima-hosted VMs
How nima-hosted agent VMs are enabled, what the VM can reach, how nima.yml configures checks, budgets and admission, and how results are published to GitHub.