Slug: agent-extension
Principle
o-tower is the Tower entrypoint and coordinator, not an all-purpose executor.
The official Tower profile stays clean by default: Tower MCP plus the tower skill. External systems such as Feishu, mail, Slack, Notion, and company knowledge bases should be configured as dedicated local operator agents, then reached through capability routing.
Example:
capabilityRoutes:
tower.task: o-tower
tower.project: o-tower
tower.note: o-tower
feishu.docs: xiao-fei
feishu.wiki: xiao-fei
feishu.sheets: xiao-fei
feishu.bitable: xiao-fei
feishu.drive: xiao-fei
feishu.permissions: xiao-feio-tower handles Tower work directly. Feishu document pages, knowledge-base pages, Sheets, Bitable/Base apps, Drive files, folders, attachments, and permission checks are delegated to xiao-fei, which owns the Feishu MCP/skills and user credentials. In the Feishu example, xiao-fei is a Feishu workspace operator, not only a spreadsheet operator. It can own the user's accessible company documents: knowledge-base pages, cloud documents, ordinary Sheets, Bitable/Base apps, Drive files, folders, attachments, and permission checks.
Installing And Updating OpenClaw + Feishu
Tower Agent assumes OpenClaw can already receive Feishu messages. OpenClaw owns the Feishu app, bot, permissions, and credentials; Tower's extension installer does not install the Feishu channel. Before proceeding, verify that OpenClaw can answer a basic message in the target group or private chat, and that addressed messages in those chats route to the profile Tower will install (o-tower by default). Configure that channel binding in OpenClaw.
1. Build And Start Tower
For the published npm package:
npm install -g @tower-org/cli@latest
towerFor a source deployment, stop the old Tower process first, then run:
pnpm install
pnpm build
pnpm startKeep the new Tower process running for the remaining steps. Tower startup runs database migrations and recovers durable gateway work and pending deliveries.
2. Install Or Reinject Tower Agent
- Open Tower -> Settings -> Extensions -> Tower gateway agent settings.
- Under Tower Agent (OpenClaw), keep the default
o-towerprofile or enter the profile actually used by the Feishu channel. - Enter only gateway runtime environment values required by this machine. Tower does not prescribe proxy or
NO_PROXYrules. - Click Install for first setup or Update after Tower, profile, or skill changes.
Update is the reinjection flow. It refreshes SOUL.md, AGENTS.md, TOOLS.md, Tower MCP configuration, and the bundled tower skill from the currently running Tower package. Unmanaged fields in the OpenClaw agent entry are kept.
OWNER And Dynamic Group Access
The settings page keeps platform OWNER IDs. OpenClaw uses the verified sender to expose OWNER management tools or the NON_OWNER query-only surface. Group ingress uses groupPolicy=open with requireMention=true, allowing a new group to reach the access decision without granting it Tower data access.
An OWNER authorizes, binds, unbinds, or revokes the current group from inside that group. Versioned extension config tower-agent.channel-access.v1 stores an explicit ALL, WORKSPACE, or PROJECTS scope. Tower rechecks that scope before every project read and discussion completion. The settings page shows the display name, authoritative chat ID, status, and resolved scope; the display name never participates in authorization. Legacy trusted-channel fields are imported once and no longer decide runtime access.
3. Restart The Gateway And Refresh Feishu Sessions
Run the following in order:
openclaw gateway restart
openclaw gateway status
openclaw status --allThen send the following as a standalone message in every affected Feishu group or private chat:
/new/new makes that OpenClaw conversation load the newly injected profile and skills. Send it after the gateway restart and separately in every conversation under test. It does not remove or close Tower's durable queue, discussion history, or project bindings, and it does not refresh a long-running Tower Workbench terminal.
The complete order is: update and start Tower -> update/reinject Tower Agent -> restart the OpenClaw gateway -> send /new in affected Feishu conversations -> run acceptance.
OpenClaw First Hop And Three Tower Routes
OpenClaw first decides which capability owns the request. Ordinary Q&A and work for external operators stay in OpenClaw, never call Tower, and create no GatewayInbound. Only Tower operations, project discussion, and project work call route_gateway_message. Old clients that still send DIRECT receive direct_not_supported without persistence.
| Route | Responsibility | Workbench | User task creation | Reply and persistence |
|---|---|---|---|---|
TOWER | Tower MCP query or simple command in the gateway | No | Not by routing itself; only an explicitly requested successful MCP mutation may create one | The gateway replies directly. Confirm a mutation only after the tool succeeds. |
PROJECT_DISCUSSION | Repository-aware discussion in the resident project Workbench | Yes, through GATEWAY_DISCUSSION_REQUEST | No WorkItem or child task | The Workbench calls complete_gateway_discussion to reply to the current inbound message. |
PROJECT_WORK | Research, dispatch, and review by the project's resident Workbench | Yes, only through the durable event queue | Only after the Workbench successfully calls create_task | Tower sends native queued, real-data task-created, and reviewed final-result cards. |
Project discussion and project work are deliberately separate:
- Discussion persists
GATEWAY_DISCUSSION_REQUESTand enters the resident Workbench, but creates no WorkItem or child task. - Only a later explicit create/start request persists
GATEWAY_WORK_REQUEST; the same Workbench then creates and supervises a child task. - The resident Workbench is coordination infrastructure, not the task requested by the user.
queued: truemeans the inbound request and Workbench event are durable. It does not mean a task was created.confirm_gateway_task_createdmay send a creation confirmation only aftercreate_taskreturns a real task id.complete_gateway_workmay send the final result only after the Workbench reviews the child and moves it toDONE.
Project resolution prioritizes reply bindings, existing thread bindings, and an explicit project id/name/alias. If multiple candidates remain, the gateway must ask the user to choose rather than select the highest score. Consecutive threadless discussions reuse a chat + sender + session-kind binding; the recent project fallback expires after seven days. Explicit thread bindings do not use that expiry fallback.
Project discussion reuses the resident Workbench context. Task creation does not create a separate discussion Assistant session; the Workbench distinguishes direct-answer and child-task behavior from the durable event type. Replies to an old task first call resolve_gateway_task_context, which only returns task/project/status, OPEN-ask, and latest-execution context. OPEN asks use reply_to_ask; status/result questions stay read-only; external work is delegated with towerContext; only explicit continue/fix/rerun intent calls OWNER-only continue_bound_task. Resolution never resumes a terminal. Only an explicit new-task/start-new-work request sets startNewWork=true to override the old binding.
Feishu Channel Acceptance
Use a project name or alias that exists in Tower and is accessible to the bot. Wait for each response before moving to the next step.
1. Ordinary Q&A (outside Tower)
Send:
Explain idempotency in one sentence.Expected: an ordinary Feishu answer with no route_gateway_message call, GatewayInbound, project Workbench activity, or task.
2. Read-only Tower Query (TOWER)
Send:
List the in-progress tasks in <project name> in Tower. Read only; do not create a task.Expected: an answer from actual Tower data, with no project Workbench or new task. An ambiguous project must produce candidates, not a guess.
3. Project Discussion And Same-thread Follow-up (PROJECT_DISCUSSION)
Send:
Discuss <project name>: what is the largest risk in the current gateway design? Do not create a task.Expected: a response from the resident project Workbench and one discussion queue event, but no WorkItem or child task.
Reply in the same Feishu thread:
Continue the previous discussion and list the top two risks in priority order.Expected: the same project-bound discussion session and context are reused, and the reply returns to the original thread. Real-channel acceptance has already confirmed Tower queries and project discussion session reuse.
4. Project Work (PROJECT_WORK)
Send:
In <project name>, do this work: add gateway acceptance documentation.Accept three distinct results in this order:
- A "⏳ 小塔 · 请求已进入工作台" card says only that the request was queued for the project Workbench. It must not claim that a task was created.
- After
create_task, a "🚀 小塔 · 任务已创建" card presents server-authoritative status, priority, project, workspace, execution mode, and branch in a compact two-column grid, with the goal in its own section. Only then verify the task in Tower. - After the child finishes and the Workbench accepts its review, a "✅ 小塔 · 任务已完成" card separates the reviewed result from commit/branch metadata and retains the same Tower task id.
Receiving only the queue acknowledgement means acceptance is still waiting for task creation.
Reliable Delivery And Idempotency
Tower persists queued acknowledgements, project-discussion replies, task-created confirmations, and final results, including their native-card payloads, before sending them through OpenClaw. These GatewayDelivery records have stable semantic deduplication keys:
- failed sends remain
FAILEDand retry with backoff; - Tower startup recovers stale
SENDINGclaims and retries due deliveries; - a successfully delivered semantic message is immutable and is not sent twice;
- a duplicate platform callback reuses the same inbound row, Workbench event, and delivery instead of replaying the action.
Ordinary Q&A never enters Tower. TOWER gateway replies are also not the same as these durable Tower deliveries. The current implementation has no complete Tower-owned project-discussion history UI. Do not describe Notification Center as a full audit log of all gateway conversations.
Troubleshooting
Queued For A Long Time Without A Real Task Confirmation
- Do not resend the work request. A manual resend has a new Feishu message id and may represent a second request; only retries of the original callback are deduplicated.
- Confirm the new Tower process is running. Inspect its startup/runtime logs for
Gateway recovery,Workbench, or gateway-delivery errors. - Open Tower Missions or the project's Workbench and check the resident terminal. A busy terminal receives no direct write; the durable event waits for a completed-turn safe boundary.
- Tower restart recovery starts or continues the Workbench and restores a safe drain boundary automatically. It should not require a manual Stop/Continue; inspect recovery logs if the event remains pending.
/newrefreshes only OpenClaw/Feishu. It neither closes a Tower discussion nor replaces Workbench recovery.
Recovery After A Tower Restart
At startup Tower scans QUEUED/PROCESSING project work, ensures its Workbench is running, restores a safe drain boundary, and retries pending or failed deliveries. After a restart, observe the recovery logs and original Feishu thread before sending anything again. Persistence and deduplication recover the original request; they do not create a replacement request.
Profile Or Skill Is Still Old
Click Update in Extensions, run openclaw gateway restart, then send /new in each affected Feishu conversation. Restarting Tower alone does not refresh an active OpenClaw session. /new alone does not update files or Workbench hooks.
Tower And OpenClaw Status
openclaw gateway status
openclaw status --all- Settings -> Extensions shows whether Tower Agent (OpenClaw) is installed and its package version.
- Missions or the project Workbench shows the resident execution/terminal.
- The Tower board/task detail verifies the real task id from a creation confirmation; never infer it from a queue acknowledgement.
- Tower foreground/service logs show startup recovery, queue drain, and delivery failures.
- Notification Center is useful for task asks and notices, but is not a complete history of project discussion, inbound routing, or gateway deliveries.
Current Limitations
- Tower Agent installs Tower capability only. It does not install Feishu MCP, credentials, or third-party operators.
- Project discussion history is Tower-owned, but there is no complete discussion history UI today.
- Native cards require OpenClaw
--presentation; older versions fall back to the same persisted text payload. - Shared chats can be restricted with
harness.channelBindings; do not assume a dedicated visual management page exists today.
Unified tower-bridge
Use tower-bridge for external operations that require Gateway-owned channels, credentials, user sessions, capability routes, or Operators. Shell, filesystem, Git, dependency, build, test, and local-database work stays in the task terminal; network access or a consent requirement alone does not make a terminal command a bridge operation. Human and group messages are human.message.send: an explicitly named recipient uses recipientMode: explicit and push_to_human; an unattended OWNER message uses recipientMode: owner_home, the fixed OWNER route, and a bounded grant. The old tower-ask skill has been merged and is no longer installed separately.
The current CapabilityRequest contract reserves DIRECT / R2 for human.message.send. Other advertised capabilities, including document, spreadsheet, browser, and computer work, use the JOB lane returned by discovery.
When a Tower task needs to send prepared content to o-tower so the gateway can route it through local extensions, use tower-bridge:
current task
-> tower-bridge
-> o-tower gateway / Tower task terminal
-> local route to xiao-fei or another operator
-> summarized result back to the current task or usertower-bridge is the unified external-capability skill. It does not install third-party MCPs and does not hold Feishu, mail, or knowledge-base credentials by default. It hands a structured request to the right channel or execution owner.
OpenClaw Sketch
Create a dedicated operator workspace:
openclaw agents add xiao-fei \
--workspace ~/.openclaw/workspaces/xiao-fei \
--agent-dir ~/.openclaw/agents/xiao-fei/agent \
--non-interactive
openclaw agents set-identity --agent xiao-fei --name 小飞Keep allowlists narrow:
{
"agents": {
"list": [
{
"id": "o-tower",
"skills": ["tower"],
"allowedTools": ["tower__*"]
},
{
"id": "xiao-fei",
"skills": ["feishu"],
"allowedTools": ["feishu__*"]
}
]
}
}Place local routes in:
~/.openclaw/workspaces/o-tower/delegation-routes.jsonSee the copyable example:
extensions/tower-agent/examples/openclaw-local-delegation-routes.jsonAdd an instruction to the o-tower workspace rules saying that Tower work is direct, while feishu.docs, feishu.wiki, feishu.sheets, and feishu.bitable, feishu.drive, and feishu.permissions are delegated to xiao-fei.
Boundaries
- Do not store app secrets, access tokens, or refresh tokens in docs, prompts, or route files.
- Use least privilege and a single token owner for third-party MCPs.
- Write, delete, bulk, permission-changing, and outbound-send actions should return a plan first unless the user already confirmed the exact action.
- Tower does not ship Feishu or other third-party integrations by default; it ships the delegation pattern.
- User-facing replies should use business names such as document page, knowledge-base page, Sheet, Bitable, Drive file, and attachment. Do not expose implementation names such as
DocX,obj_type, MCP namespaces, tokens, temp file paths, or raw commands.
