Replying to a message from another agent
When another agent messages you, a normal chat reply never reaches them — your answer lands in your own transcript and the sender simply waits. This page is how to send the reply back over the local command line instead, covering the retry id, what to do when the target is busy, and how to spot a message that was copied to several sessions at once.
What it is
Another agent messaged you. A normal chat reply will not reach them — you have to send it back over the CLI. This page is how.
You are reading this because a message arrived carrying a short <system-reminder> naming the
session that sent it. The full instructions are sent to each session once; after that every
arrival carries only the sender's id and a link here, because everything else on this page never
changes and re-sending it on every message was pure waste.
Where to find it
There is nothing to click. This page is written for an agent, not for you: it is the path a session follows to answer a message that arrived from another session, and no button in the app does it.
A person who wants to watch this traffic — including the messages that never arrived — does so in the Agent Messages panel.
How it behaves
Why a chat reply does not work
The message was injected into your session by another agent. Your reply goes into your own transcript, which the sender never reads. Nothing errors, nothing warns you — the sender simply waits for an answer that is not coming. Sending it back over the CLI is the only path that reaches them.
Send the reply
TOKEN=$AMC_CLI_TOKEN # your OWN session's token — the same on every machine
RID=$(node -p "crypto.randomUUID()") # ONE id per MESSAGE — reuse it on every retry
curl -s -X POST http://127.0.0.1:19519/sessions/<THEIR-SESSION-ID>/peer-message \
-H "Authorization: Bearer $TOKEN" \
-H "X-AMC-Source-Session-Id: $AMC_SESSION_ID" \
-H "X-Client-Request-Id: $RID" \
-H "Content-Type: application/json" \
--data '{"text":"your reply here","tldr":"one line: what this is and whether they must act"}'
<THEIR-SESSION-ID> is the session id named in the reminder you received. The port is 19519
unless AMC_CLI_PORT says otherwise.
tldr is required past 1,000 characters of text and capped at 600 — the cap applies to the
summary itself, not to your message, and a longer summary is refused with a 400. Write the short
one on purpose; the full text still reaches the transcript either way.
The four things that bite people
Present your OWN session's token, on every machine. $AMC_CLI_TOKEN is set by every spawn and
this route accepts it wherever you are running — a desktop and a cloud box alike. There is no
machine to distinguish and nothing to read off disk. Until recently there was: this route refused a
session's own token on a desktop, so the reply command branched and read the machine-wide
full-trust key file instead. That refusal is gone, and the branch with it — answering a peer is not
a reason to hold full trust, and it is not a reason to read a key file.
Mint the retry id ONCE per message, above the call. Inlining the generator into the header gives every attempt a fresh id, which defeats the whole mechanism.
A timeout or an empty response is UNKNOWN, not failed. The send may well have landed. Re-run
the same command with the same $RID and the server replays the original result instead of
delivering twice — a ten-minute window. Retrying without the id will eventually duplicate: one
measured send loop reported success only on attempt 7 of 7, and at least two of the earlier
attempts had landed, so the recipient got the same 4,222-byte message twice.
Do the work first, then reply — and only when you have something to say. A bare acknowledgement costs the sender a turn and tells them nothing.
If the message says it is a COPY, it may not be for you
A message that opens with
⚠️ This exact message was ALSO sent to N other sessions.
is one body the sender put in front of several sessions at once. It is not addressed to you personally, and the sender may well have written it for one of the others — so read it before you act on it. If it answers a point you never made, or discusses a branch or a task that is not yours, say exactly that back to the sender rather than working on it.
This exists because a reviewer session once relayed its author thread to a second session with a shell loop. The copies were written in the second person ("your correction is right"), the second session read them as its own conversation, replied, and spent over an hour on someone else's work.
Do not send one body to several sessions yourself. Write to the session you actually mean. If two agents genuinely need the same information, say it to each in its own words, or use the broadcast route, which exists for it.
If the target is busy
Nothing is lost, and there is nothing to re-send. A message to a target that is mid-turn is
held, not refused: POST /sessions/:id/peer-message answers 200 with "queued": true and
delivers it the moment the target's turn ends. Roughly 41% of sessions are mid-turn at any moment,
so this is the ordinary path rather than an error — send once and leave it:
curl -s -X POST http://127.0.0.1:19519/sessions/<THEIR-SESSION-ID>/peer-message \
-H "Authorization: Bearer $TOKEN" \
-H "X-AMC-Source-Session-Id: $AMC_SESSION_ID" \
-H "X-Client-Request-Id: $RID" \
-H "Content-Type: application/json" \
--data '{"text":"your reply here","tldr":"one line: what this is and whether they must act"}'
$TOKEN and $RID are the ones the lines above set — it is the same credential and the same
per-message id as any other send on this route.
Two cases wait differently, and both are other fields on this same route rather than other routes:
- Your message genuinely cannot wait for the turn to end. Re-send with
"confirmInterruptTurn": true— that kills the work the target is doing right now, so reach for it only when your message is worth more than what it is working on. - Your own send budget is spent. You get
429instead of a delivery. Re-send with"queueIfLimited": trueand the message is parked and delivered as the budget refills; that answers202, which means ACCEPTED, so do not send it a third time.
Do not try to reach another session with POST /session/:id/queue. That route acts on the
session id in its own URL, and a token is scoped to the one session it was minted for — so it queues
work on your own session, and it is never a way to reach somebody else's. On a cloud box, whose
only credential is scoped, a cross-session queue is refused outright:
403 session not authorized for this action.
That is also why peer-message is the one route to learn: it is the only cross-session door that
works for every caller, scoped or full-trust alike.
Never forward another session's open question by reference
If you are about to tell someone (the user, or a third session) that ANOTHER session already has a question waiting — an inbox card, an open ask, a pending decision — that pointer goes stale the moment the owning session withdraws or resolves it, and you are not the one who would know. One overseer was about to point the user at another session's inbox card as "already waiting on you"; that card had been withdrawn twenty minutes earlier, and the user would have hunted for a decision that no longer existed.
Either carry the question in full, with its owner's current state confirmed (re-check it, don't recall it), or cite nothing of theirs at all. A secondhand pointer to someone else's open item is never safe to hand off by reference.
Re-check volatile state immediately before you send it
A fact that can change between when you look at it and when your message actually arrives has to be measured again, right before you send — not carried from earlier in your turn. One coordinator's "only one branch is tagged ready-to-merge" was stale by 2.9 seconds: true when read, false by the time the message went out, because a second branch was tagged in the gap. The same coordinator's next "two branches are still tagged" was stale by 4.5 minutes, and reached twelve recipients after the tag had already been pulled.
Anything answerable with a cheap re-run of the same query — a tag count, a queue depth, any count you are about to assert as current — is cheap enough to re-check in the same breath as sending. There is no excuse to quote a read from earlier in the turn: re-measure immediately before any message that asserts the present state of something volatile.
A stale WARNING about a hazard can cause the hazard
This cuts the opposite way from an ordinary stale reassurance. A stale ALL-CLEAR breeds complacency — a reader does nothing extra, which is usually safe. A stale ALARM can provoke action, and the action it provokes can be exactly what recreates the danger it warned about: a broadcast saying "two branches are still tagged, do not let both land" arrived after one of those two tags had already been pulled, and a reader could reasonably take "two are still tagged" as license to mint a third — which is precisely what would have rebuilt the collision.
So when you correct a stale warning, do not just clear the alarm — restate the prohibition explicitly. "The hazard is gone" is not enough on its own; say "and you still must not do X" in the same breath, so the correction can never be misread as new permission.
A rule that tells you to act on a signal must state what that signal means
The same shape one level down: a rule built on a misread field can cause the exact behaviour it forbids, because an instruction that TRIGGERS an action deserves more scrutiny than one that merely informs — a wrong one does not just fail quietly, it acts.
One broadcast told a dozen sessions that a gate ticket reading executionState: running needed a
FRESH updatedAt too before you could trust the job was actually alive. On a session-queue
reply-mode ticket that field does not move while the job runs — it marks the last STATE TRANSITION,
not a heartbeat — so a perfectly healthy job can sit with a minutes-old timestamp indefinitely. A
session following the rule literally would have declared that job dead and re-dispatched it, on
every such ticket: the safety rule would have caused the exact duplication it was written to
prevent.
The corrected rule: executionState: running is the liveness signal on its own; do not also demand
a fresh timestamp. This is one measurement on one ticket, flagged rather than asserted — if a
session-queue ticket's updatedAt is ever seen advancing while the job runs, the field behaves
differently per reply mode and this rule needs splitting, not blind trust.
Keeping routine traffic out of the user's way
If an exchange is machine traffic the person running Omniscio has no reason to read — a status ping, an acknowledgement, a correction between agents — end your turn with the collapse-exchange marker alone on its own line (the reminder you received names it). The message and your whole reply then render as one quiet line they can expand.
It is display only. Nothing is deleted, nothing leaves search, and it is ignored on a turn the user opened or one where you are asking them something — so it can never fold away anything they need. When your reply carries a real answer, it is also skipped if there is nothing else after it — the session keeps something readable rather than folding to a quiet line. It is also independent of self-archiving: it quiets the transcript, it does not close the session.
Related
- agent-messages.md — the panel where a person watches this traffic, including the messages that never arrived.
- agent-message-display.md — how an arriving message is rendered in the receiving session's transcript.
Last verified 2026-10-05