Virtual Worker Send Commands
OpenCode Commands
Runs an OpenCode coding agent on a Virtual Worker. Covers worker setup, provider credentials, prompts, sessions, and asynchronous feedback for results, questions, and permissions.
Use these commands inside the params.commands object of a Virtual Worker Send Commands task. Each command needs a unique __order.
OpenCode runs on the worker and can work with files and repositories there. A prompt starts work in the background. Results and requests for input arrive on the originating stub through the _update_from_virtual_worker feedback action.
Worker setup
Use the github worker flavour, which pre-installs the OpenCode executable alongside Git and GitHub tools. Set params.runtime.cluster.worker.tag to github; this selects the latest-github image. The worker starts its shared OpenCode server automatically when an OpenCode command first runs.
For example, store this runtime object in template.data.settings.opencode.runtime to use with the tasks below:
Use the same worker for credential setup, prompts, and replies. Set params.directory on OpenCode commands to the project directory on that worker. The directory must already exist; use cli_run to create it or clone a repository first. If omitted, OpenCode uses the worker process's current working directory. Keep the directory consistent when continuing a session or replying to its requests.
Configure a provider key
Store the provider API key in a Generic credential. The following example uses cli_run to write an Anthropic key into the container's ~/.local/share/opencode/auth.json before sending any prompts:
Set template.data.settings.claude_api_key_credentialuuid to the credential UUID. The target helper resolves the key in the Virtual Worker Hub. This command replaces auth.json with the shown provider entry. Run it again when using a new worker container.
Send a prompt
opencode_session_prompt sends message parts to the coding agent. You can omit sessionID to create a session automatically, or supply an existing session ID to continue its conversation.
This example starts a new session in a project directory that has already been prepared on the worker:
Prompt parameters
Immediate acknowledgement and later result
The command prepares the OpenCode client and event subscription and creates a session if sessionID was omitted. It then starts the prompt in the background and returns without waiting for the agent to finish:
Every successful acknowledgement includes payload.session_id, whether you supplied an existing sessionID or the worker created a new session. Save this ID to continue the conversation. The same ID is included in later feedback updates at stubpost.data.opencode.session_id. You can also use opencode_session_create to create a session separately before sending a prompt.
An accepted prompt does not mean the agent has completed its work or that the model request succeeded. Subsequent commands in the task can run while it is still working. Continue your workflow from the feedback updates for the prompt result. Errors returned by the background model request are included in those updates. If session creation fails, the command returns a technical error immediately and does not send the prompt.
To continue a conversation, pass the saved ID as params.sessionID and send new parts on the same worker and directory. Wait for the current prompt to finish, and resolve any outstanding questions or permission requests first.
Pending input blocks a new prompt
For an existing sessionID, the command checks for pending permissions and questions before submitting another prompt. If either exists, it sends no new prompt and returns:
Use the request IDs in these arrays with the reply commands, or handle the original question.asked and permission.asked feedback events as they arrive.
Feedback updates
Define or override _update_from_virtual_worker in your template to handle the agent's updates. The worker authenticates updates with its worker token, and the hub routes the action to the originating stub.
Route event updates using stubpost.data.opencode.event.type. Route prompt results using the presence of opencode.response or opencode.error. A tool result is an intermediate update; it does not indicate that the whole prompt is finished.
Prompt result
The following is an abbreviated example of the feedback stubpost after a successful prompt:
For a normal response with info.finish equal to stop, the worker joins text parts with newlines to form stubpost.message. It also extracts tool errors for a tool-calls finish and formats message-level errors when present. Use the full response and error fields for workflow decisions, since a readable message is not always available.
Tool results and input events
The worker forwards these native events:
Text/token streaming and tool parts with pending or running status are filtered out. Session status events are not forwarded; use opencode_session_status if you need to inspect whether a session is busy, idle, or retrying.
For example, a completed tool call produces a feedback stubpost shaped like this (abbreviated):
Reply to questions and permissions
Send replies in another virtual_worker_send_commands task using the same runtime and directory. Replying lets the waiting agent continue its current prompt; you do not need to send that prompt again.
Answer a question
Use opencode_question_reply with the request ID from question.asked. answers is an array in question order, with an array of selected option labels for each question. For a question that allows a custom answer, put the answer text in that question's array.
The following command object can be placed inside params.commands of the feedback action's task:
Run this command only when handling a question.asked event, and replace the sample answer with the user's or workflow's decision. To decline the request, use opencode_question_reject with the same requestID, omitting answers.
Decide a permission request
Use opencode_permission_reply with the request ID from permission.asked. reply accepts once, always, or reject. once allows this request; always remembers approval for the request's permission patterns in the session; reject denies it. An optional message supplies decision context.
Run this command only when handling a permission.asked event, after deciding whether to allow the requested operation.
Session and discovery commands
These commands return the OpenCode result in the command's payload. They share the optional directory and workspace parameters. Required IDs and all other parameters go directly inside params.
Create a session
opencode_session_create creates a session without sending a prompt. Save payload.id and pass it as sessionID on later prompts.
Optional parameters include title, parentID, agent, model, metadata, permission, and workspaceID. For this command, model uses { "providerID": "<provider ID>", "id": "<model ID>" }; the prompt command uses modelID instead of id. permission is an OpenCode permission ruleset array.
Inspect, stop, or remove sessions
For example, retrieve the conversation after receiving an update: