Webex Integration

August 24, 2026 Β· View on GitHub

Chat with your Kiro Crew agent from Cisco Webex β€” on your phone, your laptop, anywhere. Create a bot on the Webex developer portal, paste one token, and you're talking.

Webex needs no public URL and no webhooks: Kiro Crew registers a device with Webex and receives messages over an outbound WebSocket, so it works from behind a firewall or NAT. Replies land as one message per turn, with a live status placeholder ("πŸ€” Thinking…" β†’ "πŸ”§ Running: …") while the agent works.

The easy way: just ask Kiro Crew

You don't have to edit anything by hand. In any Kiro Crew session β€” the dashboard, Slack, or the CLI β€” say something like "set up the Webex channel." Kiro Crew walks you through creating the bot, then writes the token and your email into ~/.kiro/crew/.env and config.json and restarts the gateway for you. You just hand it the bot token when it asks.

Prefer to wire it up yourself? The manual steps are below.

Quick start

You'll need a running gateway (kirocrew gateway) and a Webex account.

  1. Create a bot β€” log in at developer.webex.com, open My Webex Apps under your avatar, click Create a New App β†’ Create a Bot, and fill in the name/username/icon. Copy the Bot access token shown on the confirmation page (it's displayed only once; you can regenerate it later from the app's edit page).
  2. Save the token to ~/.kiro/crew/.env:
    WEBEX_BOT_TOKEN=YmFzZTY0…
    
  3. Turn it on in ~/.kiro/crew/config.json β€” your own Webex account email is the allow-list:
    "webex": { "enabled": true, "allowed_emails": ["you@example.com"] }
    
  4. Restart, then say hi:
    kirocrew restart
    
    Search for your bot's username in Webex and send it a direct message.

Using it in a group space

Spaces are off by default and are a separate, deliberate decision: a reply in a space is readable by every member, including people your allowed_emails list excludes. Four things have to line up.

  1. Add the bot to the space β€” from the space's People menu in Webex. A bot that is not a member never sees the space at all.
  2. @mention the bot in every message. Webex delivers a space message to a bot ONLY when the message mentions it. An unmentioned message produces no reply and no log line β€” the gateway never receives it, so silence there is Webex filtering, not a fault. Commands need the mention too, before the slash: @YourBot /new.
  3. Get the space's ID. It is an opaque string with no UI that shows it:
    curl -H "Authorization: Bearer $WEBEX_BOT_TOKEN" https://webexapis.com/v1/rooms
    
    The id of the space you want is what you need. (An @mention in a denied space also records the id in the security event log, so a single failed attempt surfaces it.)
  4. Turn it on and name the space β€” the switch alone grants nothing:
    "webex": {
      "enabled": true,
      "allowed_emails": ["you@example.com"],
      "allow_group_rooms": true,
      "allowed_room_ids": ["Y2lzY29zcGFyazovL3VzL1JPT00v…"]
    }
    

A space is its OWN conversation, shared by everyone in it β€” not a branch of your DM. /new there resets the space's conversation and leaves your DM untouched, and /sessions there lists the space's history rather than yours.

Commands

CommandWhat it does
/newStart a fresh conversation (new session)
/compactCompress the conversation context
/modelList the models this account can use, and pick one
/sessionsList this conversation's earlier sessions
/yolo on | off | renewAuto-approve every tool for a while
/linkResume mirroring dashboard replies here (on by default)
/unlinkStop mirroring dashboard replies here
/stop (or /cancel)Stop the current reply and clear the queue
/kirocrew dashboard [2h]Get a dashboard login link (DM only)
/helpShow available commands

/help is generated from the same table the parser uses, so it cannot go stale.

In a group space every command needs the bot's @mention in front of it (@YourBot /new), because Webex only delivers mentioned messages. A dashboard link is a credential every member of a space could read, so that one command is refused outside a direct message.

While a reply is running

A message sent mid-reply is folded into the running turn by default. Prefix it to choose:

PrefixWhat it does
/queue <message>Answer it after the current reply finishes
/steer <message>Fold it into the running reply now

Set messaging.queue_mode to queue to make queueing the default. A queued message gets a ⏳ Queued receipt that updates in place, and a burst is answered as one reply rather than several.

Approving a tool

When a tool needs your approval the bot posts Approve / Deny buttons on an Adaptive Card, and the same question as text:

πŸ” Approve `fs_write`?

Reply 1 to approve or 2 to deny.

Press a button, or reply 1 / 2 β€” either resolves it. The text always ships alongside the card, so the prompt is answerable even where the card does not render. Anything that is not an answer is treated as an ordinary mid-turn message, so you can redirect the agent instead of answering. An unanswered prompt is denied after five minutes.

Security model

  • Deny-by-default β€” an empty allowed_emails list rejects everyone. Anyone in an org can message a Webex bot, so add only your own email(s).
  • allowed_emails IS the trust boundary β€” every entry is an operator. There is no second, narrower "owner" tier, here or on any other channel. Anyone on that list can run every command, which includes /yolo (auto-approves tools for the whole process, not just their own conversation, and the dashboard toggle and CLI drive the same grant) and /kirocrew dashboard (mints a presigned dashboard login for YOUR Kiro Crew, DM-only). So add a second address only for a person you would hand your own dashboard to. Both commands write a SEL record naming the sender, so who took a grant or a link is always reviewable in the audit log.
  • Direct messages by default β€” group spaces are off until you turn them on AND name the spaces, because a reply in a space is readable by every member, including people your allowed-emails list excludes. Turning the switch on alone answers nothing.
  • Files are scanned before the agent sees them β€” Webex scans attachments for malware, and a file that is still scanning, infected, or unscannable is refused rather than handed over.
  • A group turn will not upload a file or mint a dashboard link β€” both would disclose more than the reply itself, so they stay DM-only. A reply that references a local file keeps printing the path in a space instead of shipping the bytes.
  • Shared turn pipeline β€” Webex turns run on the same TurnDriver as Slack: credential/exfiltration redaction, the tool-approval ladder, and security event logging all apply.
  • Approvals fail closed β€” a prompt nobody answers is denied, and a policy that denies this channel blocks an approve while still letting a deny through, so a refused tool never hangs. Turning /yolo on does not weaken the security gate: sensitive paths, the governance ceiling and the deny-list all run ahead of auto-approval, so a hard deny still wins.

Configuration reference

SettingDefaultWhat it does
enabledfalseTurns the channel on
allowed_emails[]Webex account emails allowed to chat (empty = nobody)
allow_group_roomsfalseAnswer in group spaces, not just DMs
allowed_room_ids[]Spaces the bot may answer in (empty = none)
reply_in_threadtrueReply under the message's own thread
wdm_base""Pin the Device Manager host, which must be an https Webex host (empty = discover it)
soft_threshold_pct80Context % where the bot suggests /compact
hard_threshold_pct95Context % where the bot force-compacts
bot_token""Token fallback if WEBEX_BOT_TOKEN isn't set
session_folder""Folder that Webex sessions are filed under

Prefer the WEBEX_BOT_TOKEN env var over bot_token β€” it keeps your secret out of config.json.

If something's off: no reply usually means your email isn't in allowed_emails or enabled is false; a missing Webex channel started line in the logs means the token isn't set or is invalid. In a group space, no reply and no log line means the message did not @mention the bot (Webex never delivered it); a reply refusal with nothing in the log but a denied_room_not_permitted security event means the space is not in allowed_room_ids.