Skip to content

Local delivery pilot (private)

Local delivery sends review comments to a linked local chat instead of the normal thread queue. It is a private pilot. It is off by default, and we turn it on one project at a time. If list_projects shows workflow: threads, nothing on this page applies to you.

Recorded local compatibility

ClientBridge
Claude Code 2.1.1950.1.1
Codex CLI 0.150.10.1.2

Desktop and cloud chats are not supported. The local bridge from 0.1.4 puts the recoveryGeneration in the delivery message.

  1. A workspace owner enables project access and connects the GitHub repository.
  2. In your existing chat, run the grouchlink skill. It links the chat to the project that matches the repository, and asks if several match. The public plugin alone does not install the private bridge.
  3. Call get_chat_connection before working feedback. A visible tool list does not prove access.
  4. Keep the original chat and the saved state path from the setup receipt. Resume the same chat after closing it. Do not copy chat IDs or delete state to work around a mismatch.

To pick up work, ask the linked chat to check Gutternote, or leave a wait_for_batches call running. Automatic arrival needs extra bridge and Channel setup.

Project enablement

BRIDGE_PROJECT_DISABLED from a tool, or HTTP 503 project_not_enabled, means delivery is not on for this project. A workspace owner can ask us with Contact us in the dashboard. Keep the original chat and request IDs. Do not fall back to another comment reader.

While delivery is off, existing claims, results, status, owner recovery and exact request replays still work. New pickup waits. Held comments stay private: no other tool can read them or their screenshots, even after the pilot is off.

Delivery settings

Agents → Local delivery appears only on pilot projects with a linked chat.

  • Owners choose Collect, then send selected comments or Immediately when tagged, and can pause automatic delivery.
  • Pausing keeps Immediate comments queued until you resume. Switching to Collect cancels automatic sending for comments not yet sent.
  • Owners can pause or switch to Collect even when the chat lost access or the project is not enabled. Resume and Immediate wait for both to be restored.
  • Members can inspect and send held comments.

Before release, the server checks each comment’s author again. A permission change can block a saved comment. Restoring access does not release it, but a permitted member can still send it. Slack comments and bot replies are never delivered.

Send from the widget

Only workspace members see delivery controls. Comment-only reviewers can still comment and reply.

The saved-comments counter opens a list of your held notes on this preview. Select comments and send them to a linked chat. Select all for this chat selects ready comments up to the batch limit. Replies must go to their original chat in a separate batch.

A send the server could not confirm stays in the tab until you retry or discard it. Retry with the same request: a queued batch replays and is not queued twice. Signing out clears it.

StatusCodeMeaning
400invalidThe batch was empty, too large or repeated a comment. Nothing queued.
403agents_disabledSending to agents is off on this deployment. Nothing queued.
403delivery_unavailableThis session cannot send these comments.
409comment_changedA comment changed or was already sent. Refresh and select again.
409conversation_destinationSend replies to their original chat in a separate batch.
503project_not_enabledDelivery is not on for this project. Nothing queued.

409 release_failed, 503 pilot_disabled, other server errors and a lost response may have queued the batch. Retry with the same request ID and body.

Work a batch

On a batches project, the agent works only batches released to its chat:

  1. list_batches or wait_for_batches (each wait is at most 20 seconds).
  2. get_batch, then acknowledge_batch with a new UUID as requestId. Edit only after a successful new claim.
  3. Post progress and results with reply_to_batch_thread (at most 32,000 bytes). Reply at least every 20 minutes on long work. After 30 minutes with no reply, the batch shows Stalled.
CodeWhat to do
BATCH_ALREADY_CLAIMEDAnother pickup holds the claim. Do not edit. If this task made the claim and lost the response, retry with the same requestId.
REQUEST_ID_INVALIDRetry with a new UUID as requestId.
BATCH_REOFFEREDAn owner recovered or released the batch. Do not edit. If asked to pick it up again, call list_batches and acknowledge with a new requestId and the current recoveryGeneration.
BATCH_CONTEXT_CHANGEDA comment changed. After pickup, stop editing and call finish_superseded_batch with the claimId. Tell the user which threads were not done.
BATCH_RELEASEDAn owner released the batch from this pickup. Stop and tell the user. Changes already made stay in the checkout.
BATCH_CONTEXT_CURRENTNothing changed, so the batch cannot be finished as superseded. Reply to each thread.

When the repository is busy

The pilot runs one batch at a time per GitHub repository in a workspace, even across projects.

  • acknowledge_batch returns REPOSITORY_BUSY. Retry the same batch in the same chat every one to two minutes, before editing. Resending or opening another task does not help.
  • Batches start oldest first. A batch whose agent stops asking for 5 minutes loses its place until it asks again. The dashboard shows waiting batches as Queued.
  • A batch keeps the repository through sleep, disconnection and pauses. It frees the repository when every thread has a final result, or when an owner releases it. Nothing times out.
  • REPOSITORY_REQUIRED: ask the owner to set the project’s repository, then retry.
  • REPOSITORY_RECONCILIATION_REQUIRED: an older run must finish, or an owner must stop and reconcile it.

Recover a delivery

Only a workspace owner can recover an uncertain delivery, from Agents → Local delivery, after checking the original chat. An agent cannot approve its own retry. Members see the next step without recovery controls.

A recovery keeps its request ID. If the response is lost, Check recovery returns the saved receipt. The saved confirmation belongs to the account that made it and is cleared on sign-out. A 200 confirms the queue changed, not that the agent picked it up. Claimed or accepted batches cannot be reset.

Release a stalled repo

When a batch shows Stalled, an owner can stop it and release the repository. The outcome is one of:

  • Requeue: the batch waits again for the same chat.
  • Finish: a released comment changed, so the batch finishes as superseded. Unanswered comments go back to their reviewers.

Either way the repository is free. The earlier pickup’s replies are refused from then on.

Local delivery recovery

Errors from Recover and Release:

StatusCodeWhat to do
400invalidCheck the request.
403not_ownerAsk a workspace owner.
409reconciliation_requiredConfirm the action and what happened in the original chat.
409delivery_changedRefresh. The destination or generation changed.
409request_id_reusedReuse the original body to check its receipt, or start a new action.
409batch_already_claimedContinue in the chat that owns the claim.
409batch_context_changedReconcile the work, then send the current comment revision.
409recovery_unsupportedThe chat accepted the batch. Ask it to pick it up. Do not resend.
409recovery_failedRefresh and check the chat and its access. Nothing was recovered.
409repository_not_stalledThe agent was active in the last 30 minutes. Refresh.
409repository_already_releasedThe batch finished or was released since the page loaded. Refresh.
409delivery_unavailableThe batch is not in this project. Nothing was released.
503pilot_disabledDelivery is not on for this deployment.

Bridge errors

CodeWhat to do
BRIDGE_UPGRADE_REQUIREDThe bridge and server versions do not match. Ask the pilot operator to align them, then retry with the saved state. Do not delete pairing files.
CODEX_CALL_CONTEXT_REQUIREDThe Codex call had no valid chat identity. Use a supported local Codex surface. Do not copy an ID into an argument.
TOOL_CACHE_REQUIREDThe saved tool list is missing. Run grouchlink again from the original chat with its saved state path.

If setup says the harness gave no chat identity, run grouchlink from the original local chat. Do not copy or invent an ID.