agent: don't let bots reply to typing indicators (#222)
The chat app sends its "…is typing" beat as a relay-only ephemeral msg frame (type:"msg", ephemeral:true, no id). The bot's frame filter only dropped non-"msg" types, so ephemeral presence traffic slipped through to processMsg — and in a DM (replyTrigger "always") the bot answered every beat before the human hit send. Drop ephemeral frames in onFrame. connect.op/connect.oauth grants are sent as normal stored messages, so they're unaffected.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 files changed,
+10
−1
agent/runtime.mjs+5 −1changelog/2026-07-05-bots-ignore-typing.md+5 −0
diff --git a/agent/runtime.mjs b/agent/runtime.mjs| index d357e41..62d922a 100644 |
| --- a/agent/runtime.mjs |
| +++ b/agent/runtime.mjs |
| @@ -525,7 +525,11 @@ export function runBot({ name, session, builtinPersona = "", builtinDocs = "", t |
| } catch { |
| return; |
| } |
| - if (f.type !== "msg" || !f.thread_id) return; // ignore reactions/edits/typing/etc. |
| + // Ignore reactions/edits/deletes/typing, and — crucially — ephemeral frames: |
| + // relay-only presence traffic (the chat app's "…is typing" beat, live cursors) |
| + // arrives as `type:"msg"` with no id (see hub.go), so the type check alone lets |
| + // it through. Without this a DM bot (replyTrigger "always") answers every beat. |
| + if (f.type !== "msg" || !f.thread_id || f.ephemeral) return; |
| if (!keys.has(f.thread_id)) await loadThreads(); // a thread we were just added to |
| await processMsg(f.thread_id, f.id, f.blob); |
| } |
diff --git a/changelog/2026-07-05-bots-ignore-typing.md b/changelog/2026-07-05-bots-ignore-typing.md| new file mode 100644 |
| index 0000000..3ad5548 |
| --- /dev/null |
| +++ b/changelog/2026-07-05-bots-ignore-typing.md |
| @@ -0,0 +1,5 @@ |
| +Bots now wait for you to actually send. In a one-on-one chat with Eleven (or any |
| +bot), the little "…is typing" indicator was being mistaken for a message, so the |
| +bot would sometimes fire off a reply before you'd finished your thought. Fixed: |
| +typing is presence, not a message, and bots ignore it — they only respond once you |
| +hit send. |