Qwen Code 0.23.1 Preview: stop cross-session messages from waiting forever
Quick answer
Qwen Code 0.23.1-preview.2, released on September 7, 2026, changes how one local agent session learns what happened to a message sent to another session. A policy-level rejection can now return refused instead of looking like a person chose denied. Messages held for review can also expire after a configured window instead of remaining unresolved until the receiving session exits.
That is a meaningful reliability improvement for multi-session agent workflows, but this build is explicitly a pre-release. Do not replace a stable automation blindly. Canary the receipt state machine, choose a finite hold window, and prove that every sent message reaches a truthful terminal state before depending on it for handoffs.
Who this is for
This guide is for developers running several Qwen Code sessions on one machine and using cross-session messaging to coordinate review, implementation, or release work. It is especially relevant when a sender decides its next action from the receipt it receives.
If you only need durable task organization inside one Channel chat, start with the Qwen Code named-session isolation checklist. This article covers peer-message delivery state, not named-session ownership or parallel file isolation.
What changed, and why it matters
Before this preview, two outcomes could mislead the sending agent. A receiver configured to refuse inbound cross-session messages could be reported as denied, which sounds like a human reviewed the message. A held message could remain pending indefinitely when nobody was available to review it.
The merged Qwen Code change separates those meanings:
| Outcome | Meaning | Sender action |
|---|---|---|
refused |
Receiver policy rejects peer messages before a person sees them | Stop resending; choose another route |
held |
Message is waiting for receiver-side review | Wait only until the recorded deadline |
denied |
A held message was actively rejected | Record the decision; do not call it a policy refusal |
expired |
Nobody decided before the hold window ended | Mark undelivered and unblock the workflow |
The new agents.crossSessionHeldExpiry setting accepts 1m, 5m, 10m, or never; the documented default is five minutes. /peers exposes remaining time. Invalid or missing values fall back to the finite default rather than silently becoming unlimited.
Build a terminal-state ledger
Do not let “the send call returned” mean “the message was delivered.” Record a row for each handoff:
message_id / sender_session / receiver_session
sent_at / initial_receipt
hold_deadline / final_receipt / finalized_at
next_action / evidence_link
Your controller should consider refused, denied, expired, and delivered/accepted outcomes terminal. held is not terminal. Alert when a row remains non-terminal after its configured deadline plus a small transport margin.
Six-step preview rollout
1. Pin both preview and rollback
Record the exact Qwen Code version, package digest, operating system, and previous stable version. The release is a preview; a successful GitHub merge is not evidence that your production environment is ready.
2. Start with synthetic sessions
Create two disposable sessions using a dummy repository and a non-production provider. Enable cross-session messaging only for those sessions. Avoid credentials, customer code, and release permissions during the canary.
3. Test policy refusal
Set the receiver's inbound policy to refuse, send one uniquely identified message, and verify that the sender receives refused. The receiver should neither display nor hold the message. A controller that responds by retrying the same peer has misunderstood the receipt.
4. Test bounded hold and expiry
Set inbound handling to hold with crossSessionHeldExpiry: "1m". Send a message, confirm /peers shows a deadline, and make no decision. The held entry should disappear after the minute and the sender should receive expired. Repeat once with an explicit approval and once with denial.
5. Test sleep and configuration changes
Suspend the canary machine beyond the deadline, then resume it. An overdue message must not be delivered as if it were fresh. Also shorten and lengthen the expiry while a message is held, and verify that /peers and actual settlement follow the current configuration.
6. Test mixed versions before promotion
The wire gains a new receipt value without changing its version. An older sender may not understand refused and can leave its ledger pending. Run old-sender/new-receiver and new-sender/old-receiver pairs. Promote only when your controller handles unknown receipts explicitly or every participating session moves together.
Acceptance matrix
| Test | Expected evidence |
|---|---|
| Refuse at admission | Sender gets refused; receiver sees nothing |
| Hold with no reviewer |
held becomes expired inside the configured window |
| Human denial | Final state is denied, distinct from refused
|
| Approval before deadline | Message is released once; no later expiry fires |
| Machine sleep | Overdue entry is swept before delivery |
| Invalid expiry | Finite default is used, not never
|
| Runtime expiry change | Remaining time and settlement match current policy |
| Mixed-version sender | Unknown receipt cannot remain silently pending forever |
Decision rule
Do cross-session messages affect downstream work?
no -> remain on stable; observe the preview
yes -> can every message be reconciled to a terminal receipt?
no -> do not automate dependent work
yes -> can all participating versions parse the receipt set?
no -> upgrade together or add unknown-state handling
yes -> run the eight canaries, then promote one cohort
Common mistakes
- Calling
send_messagesuccess proof of delivery. - Retrying a
refusedmessage to the same receiver. - Treating
heldas final and starting dependent work. - Choosing
neverwithout an operator SLA and stale-message cleanup. - Ignoring laptop sleep, daemon restarts, and runtime setting changes.
- Mixing preview and stable senders without testing unknown receipt values.
- Describing this pre-release behavior as stable Qwen Code availability.
Building something? Turn your product page into a show people want to watch with PromoFast —hosted, embeddable, and ready to export.
FAQ
Is Qwen Code 0.23.1 stable?
No. The cited build is 0.23.1-preview.2 and GitHub marks it as a pre-release. Keep a pinned stable rollback until your own canaries pass.
What expiry should I use?
Use the shortest window that still matches the real reviewer response time. Five minutes is the default, not a universal recommendation. If you use never, add a separate stale-message policy.
Does refused mean a human rejected the message?
No. It means the receiver's policy did not admit the message. denied represents an active decision on a held message.
Top comments (0)