Reliable Workbench Gateway
The Workbench gateway connects Feishu, WeChat, and platforms supported by OpenClaw/Hermes to Tower while preserving identity, project scope, task ownership, and the original reply thread.

Download the editable Draw.io source
Capability boundaries
OWNER
The bot owner may:
- query workspaces, projects, tasks, and runtime status;
- start a project discussion;
- route work to the resident project Workbench;
- use diagnostics to inspect an external message chain.
The message ingress does not receive create_task, task mutation, or terminal start tools. Every write must be performed by the bound project Workbench, preventing the ingress agent from bypassing review and creating duplicates.
NON_OWNER
Colleagues receive read-only access only in groups authorized by an OWNER:
ALLcovers every workspace/project;WORKSPACEandPROJECTSadd mandatory filters;- unauthorized, revoked, and invalid scopes fail closed;
- personal tasks, personal daily reports, and local paths are never returned;
- tasks cannot be created, changed, started, or deleted;
- unknown channels and unverifiable identities receive a permission error.
The OWNER manages the current group through manage_gateway_channel_access. OpenClaw controls the sender-specific tool surface, while Tower performs the final data-scope check from the versioned extension configuration.
Request classes
| Class | Behavior | Creates a task |
|---|---|---|
GENERAL | General conversation or content unrelated to Tower | No |
PROJECT_DISCUSSION | Enqueues GATEWAY_DISCUSSION_REQUEST for the project Workbench to answer directly | No |
PROJECT_WORK | Persists the inbound event and dispatches it to Workbench | After Workbench review |
REMOTE_PROJECT | Adds a Git project after the OWNER provides its destination | Depends on access mode |
Reliable work loop

Download the editable Draw.io source
- A verified platform event carries stable sender, chat, and message IDs.
- Tower persists
GatewayInboundbefore sending the queued card. - The resident Workbench receives a leased, fenced durable batch and explicitly ACKs it.
- Workbench creates the unique
GatewayTaskLink, then starts the child task. - After the child enters
IN_REVIEW, Workbench verifies the original constraints and evidence. Task=DONEandFINAL_RESULT/PENDINGare committed atomically.- The outbox replies to the original platform message and deduplicates with a stable semantic key.
- Associated events become
CONSUMEDonly afterresolve_workbench_batchsucceeds.
Three independent state layers
Workbench does not use one state machine for terminal turns, durable consumption, and operational health:
- The live PTY Provider turn records whether the current turn is
BUSY.writeRawonly forwards terminal bytes; it does not updatelastInputAtor change turn state.writeSubmittedInputis the semantic submit boundary: it updateslastInputAt, closes the one-shot drain boundary, and entersBUSY. WorkbenchEvent/WorkbenchBatchstore durable delivery state.Batch=RESOLVEDandEvent=CONSUMEDrelease processing responsibility; they do not finish the Provider turn.WorkbenchRuntimeis a persisted operational projection. It may remainBUSYafter the batch resolves. Only Provider Stop/turn-complete moves it toIDLE, opens one drain boundary, and attempts the nextPENDINGevent.
If the Stop hook is lost, Provider transcript evidence can restore the boundary: Claude uses stop_reason=end_turn; Codex task_complete is accepted only when it is not earlier than the live session's last semantic submit. Terminal silence, output-idle time, and terminal protocol bytes are not completion evidence. The current implementation does not persist per-turn turnId or turnSeq values.
Reliability invariants
- One inbound can bind at most one external work task.
- Neither a PTY write nor ACK finally consumes an event; only
RESOLVEDreleases processing responsibility. RESOLVEDnever marks a still-running Provider turnIDLEearly.CLAIMED,DISPATCHED, andACKEDare leased. An expired lease replays the same batch ID safely.- ACK, heartbeat, and resolve carry the current generation's lease token, so a stale terminal cannot confirm a newer delivery.
- An unresolved batch renews its lease every two minutes instead of waiting for the five-minute processing lease to expire.
- After a restart, Tower recovers from the SQLite inbox/outbox rather than a terminal screen or in-memory state.
- Unattended human messages persist a
HarnessOutboundand ask intent before a worker sends them. - Implicit content deduplication covers only the current ask lifecycle. The same question starts a new send cycle after the previous ask is answered, while an explicit dedup key remains strictly idempotent.
GatewayTaskLinkreferences both the inbound and task with cascading cleanup; recovery never treats an orphan link as proof that a task exists.- One Tower database admits one runtime leader at a time, preventing competing scanners from owning the same PTYs.
- A
REVIEW_ONLYproject cannot create an executable task or start a terminal. - OpenClaw ingress receives only routing, read-only query, and diagnostic tools.
- Sender, chat, project, Workbench, and global queue limits prevent resource exhaustion.
Operational data lifecycle
The lifecycle distinguishes three kinds of data:
WorkbenchEvent.payloadis replay input. ACONSUMEDevent may be requeued during recovery, so V1 retains every payload in full.WorkbenchBatch.promptand the message bodies inGatewayInboundandGatewayDeliveryare operational duplicates. They become possible compaction candidates only after the protocol is demonstrably settled.- The small identity fields in
WorkbenchEvent,WorkbenchBatch,GatewayInbound,GatewayDelivery, andGatewayTaskLinkare idempotency tombstones. Consumption alone never permits deleting them.
Tower performs read-only observation from the existing six-hour Harness sweep; it adds no timer. The candidate windows are RESOLVED > 24h for Workbench and seven days for Gateway. A processed inbound must have no non-DELIVERED delivery, and a delivered row must still reference a PROCESSED inbound. SENT_UNVERIFIED, active, failed, and retryable states are never considered settled.
On 2026-08-01, a real local database contained only 70,062 eligible text bytes, about 0.16% of its 44.9 MB file. The current version therefore records rows and byte totals by state plus eligible rows and bytes, but does not compact or delete data. Logs never include message bodies. A future mutation requires new growth evidence and another review of the atomic state and relation guards.
This is not a sensitive-data erasure guarantee. The same content may remain in TaskMessage, terminal logs, application logs, and backups under their own retention policies. Existing architecture diagrams remain correct because no ownership boundary, relation, or data flow changed.
Remote project modes
| Mode | Capability |
|---|---|
REVIEW_ONLY | Clone, read, index, discuss, and generate a review report; untrusted scripts cannot start |
FULL_WORK | After an explicit OWNER upgrade, dependencies, code changes, and commits are allowed |
Git URLs are normalized into a unique repositoryKey, so concurrent requests for the same repository converge on one project. Tower asks for the workspace and local root when the owner did not provide them.
Diagnostics
diagnose_gateway_request: inspect the stage timeline by inbound or platform message ID.get_gateway_runtime_health: inspect Tower and OpenClaw/Hermes health with redacted logs, the runtime leader, leased batches, and Harness outbox state.- Missions Workbench card: inspect generation, heartbeat, batch, and block reasons.
tower service status: inspect the operating-system service.
