---
title: Queue a message ("send after the agent finishes")
---

# Queue a message ("send after the agent finishes")

## What it is

While the agent is mid-step, you can **queue** a follow-up message that waits and sends
itself the moment the current step finishes — instead of interrupting the work in progress.
You can line up **several** messages: they deliver **in order**, the moment the agent is free —
and when several are waiting they go over **together, in one turn**. This is the smooth way to
capture a follow-up thought, or line up a series of related instructions, without cutting off what
the agent is doing.

It's distinct from the two things it sits next to:

- **Normal send (Enter)** delivers immediately and, if the agent is running, **interrupts**
  the current step — see [send-a-message.md](send-a-message.md). Queueing is the "don't
  interrupt, send it when it's done" alternative.
- **Send Later** ([send-later.md](send-later.md)) schedules ONE reply for a clock **time**.
  The queue holds MANY messages triggered by the agent **finishing a turn**, not by the clock.

## Where to find it

Everything happens in the session's composer, at the bottom of the conversation. Press and hold
the **Send** button, or click its **▾ caret**, to open the Send Later picker; the same picker opens
from **Ctrl+Shift+L**, or from the session ⋯ menu's "Send Later". The composer's ▾ caret / hold is
available **while the agent is running**, not only when idle — so you can line this up mid-task,
right where you're typing. **"After the agent finishes"** is the first option in that picker, above
the time presets — shown **only while the agent is working** (running, starting up, or parked
waiting for account capacity), because on an idle session there is nothing to wait for.

The queue itself is the **"N messages queued"** line at the bottom of the conversation; click it to
open the ordered list, where each row carries its own **Edit** (pencil), **Reorder** (up / down
arrows) and **Remove** (✕) controls.

## How it behaves

### How to use it

1. **Type your message** in the composer as usual, while the agent is working.
2. **Open the send options** — press and hold the **Send** button, or click its **▾ caret** (or
   **Ctrl+Shift+L**, or the session ⋯ menu's "Send Later") to open the Send Later picker. The
   composer's ▾ caret / hold is available **while the agent is running**, not only when idle — so
   you can line this up mid-task, right where you're typing.
3. **Pick "After the agent finishes"** — it's the first option in the picker (above the time
   presets), so pressing **Enter** right away picks it. Your message joins the session's queue
   and the composer clears. (Just queued it by mistake? The Undo toast / **Ctrl+Z** removes it and
   restores your draft.) Start typing a time instead ("2h", "tomorrow 9am") and the option steps
   aside, so **Enter** schedules that time.
4. **See the queue** — a single **"N messages queued"** line appears at the bottom of the
   conversation. That count is your confirmation the message was queued, and it updates every
   time you add one. It sits in the chat itself and scrolls with it, so it is never parked over
   your screen (it used to be pinned above the typing box; changed 2026-09-07 at the owner's
   request).
5. **Click that line to open the list** — the messages show in the order they'll send. It starts
   **closed** so the queue never covers the conversation (changed 2026-09-14 at the owner's
   request); once you open it, it stays open for that session until you close it again.
6. **Manage the queue before it sends** — on each row:
   - **Edit** (pencil) — change the text inline (Enter to save, Esc to cancel).
   - **Reorder** (up / down arrows) — move a message earlier or later; the disabled arrows mark
     the ends. Keyboard- and screen-reader-friendly.
   - **Remove** (✕) — drop a message (a quick confirm, since it won't be sent).
7. **They send themselves.** As the agent finishes each step and goes idle, the next queued
   message is delivered automatically — appearing as a normal message from you, kicking off the
   next turn. The queue drains top to bottom until it's empty.

**Agent already idle?** Then there's nothing to wait for, so the picker doesn't offer "After the
agent finishes" at all — only the time presets — and **Send Later never sends right away**, even on
a brand-new session that hasn't started yet. (A message queued another way — over the CLI, or by
another agent — while the session is idle is delivered at once, the same as a normal send.)

**When the agent finishes by asking you a question**, the next queued message is still sent (it
becomes your answer). If you'd rather answer a specific question yourself, remove or reorder the
queued messages first — they're right there at the bottom of the conversation.

### How it works

- Each session has its own queue (up to **50** messages), stored durably — it **survives an app
  restart** and picks up delivering where it left off.
- **A message that has gone out, or that you removed, is kept for 7 days and then deleted.** Once a
  queued message has been delivered or removed, the app holds on to its record for a week and then
  deletes it for good. A message that is still waiting is never cleared this way, and one that was
  set aside as undelivered keeps its own separate copy, so it is not affected.
- Delivery rides the **same path a normal send uses**, fired the instant a turn completes and the
  session goes idle — so it is reused into a fresh turn and **never interrupts** a running step.
- **Several waiting messages go over together, in one turn** (in order, up to a size cap;
  whatever does not fit waits for the next one). Every delivery costs the agent a whole turn, so
  handing it the backlog at once is both faster and better — it can act on the messages knowing
  what the others say, instead of one at a time.
- **You still see them as separate messages.** A batch is drawn as **one block per message**, each
  tagged with whoever sent it, even though the agent received them as a single message. Messages
  written hours apart, by different agents, never fuse into one wall of text.
- The queue only delivers into a **live, idle** session. If a session is paused, has errored, or
  is waiting on capacity, its queued messages simply **wait** (they never resurrect a closed
  session); they resume delivering if the session becomes active again. That wait is capped at
  **24 hours** — past that the session has clearly not come back, so the message is set aside as
  undelivered (findable, never destroyed) rather than waiting forever with nobody told.
- **An ended session does not accept a queue at all.** Ending is the app's own "nobody is coming
  back for this" state — unlike pausing, or waiting on capacity, nothing revives an ended session
  on its own — so a message queued into one would never be read by anybody. Rather than take it
  and go quiet, the app **refuses it and says why**, naming the state, so whoever sent it can pick
  another route. Messages already waiting against a session that ends afterwards are **kept** —
  resuming that session still delivers them — and their senders are **told** they are parked, so
  they are not waiting on a reply that is not coming.
- **Archiving is the same refusal, made permanent** — an archived session can never be delivered
  into, so the app **refuses** a new message queued for one instead of accepting it and dropping
  it a moment later, and any queue it was already holding is **set aside** rather than held
  forever. Nothing is destroyed silently, and since 2026-09-17 nothing is dropped silently either:
  each discarded message is preserved as an undelivered one **and** its sender is told directly.
- **A session with messages still waiting does not land in Needs You at that moment.** It has
  not really finished — it is about to take another turn on the next message — so it takes the
  message straight away and keeps working. The Needs You card appears when it is genuinely done
  and its queue is empty, so the card you see is a real one that nothing clears out from under
  you. This includes a turn that ended by **asking you a question**: the question stays in the
  session, the queued message is handed over, and if the agent still needs an answer it asks again
  at the end of that next turn — where the card is a real one and stays. (It used to raise the card
  and then have the delivery clear it a moment later, so you saw a flash rather than a question.)
- **An agent that finishes while messages are queued for it will not archive itself.** It was
  about to sign off without ever seeing them, so the sign-off is held and the queued messages are
  delivered; the agent can finish properly afterwards. This happens **without** putting the session
  in your Needs You — it is not finished, it is about to be handed mail — so there is nothing for
  you to read or dismiss in between. (Before this, a message queued for an agent that then wrapped
  up was thrown away at the exact moment it was due to arrive.)
- If a delivery can't go through, it **retries** on the next idle a few times, then gives up with
  a visible "couldn't be delivered — you can retype it" note in the session — it never silently
  vanishes.
- Your normal **Enter / Send** behavior is unchanged: it still sends now and interrupts a running
  turn when you want that.

## For agents

The composer entry point is the Send Later picker
([SnoozePalette.tsx](../../src/renderer/src/components/ui/SnoozePalette.tsx)); the list by the
composer is [QueueList.tsx](../../src/renderer/src/features/sessions/QueueList.tsx); delivery is
[message-queue-drain.ts](../../src/main/services/session/message-queue-drain.ts). Invariants are
locked in [message-queue-contract.md](../../.claude/memory/contracts/message-queue-contract.md).
The 7-day cleanup of delivered and removed rows is `purgeDeletedQueuedMessages` in
`src/main/db/queries-sessions/message-queue.ts`.

## Related

A reader of this page usually also wants [send-a-message.md](send-a-message.md), which covers the
normal send (Enter) and the interrupt-on-send behavior this is the alternative to, and
[send-later.md](send-later.md), the sibling that schedules ONE reply for a clock time from the same
picker with a different trigger. To hold a whole session for later rather than a single message,
see [snooze-a-session.md](snooze-a-session.md); and for how images and pasted text ride along with
a queued message at delivery time, see [chat-attachments.md](chat-attachments.md).
