OpenClaw sessions_send (cross-session follow-ups)

Sending a mid-task correction to an already-dispatched sub-agent via sessions_send(sessionKey, message) — does it land where the work is actually happening?

Dogfooded twice in 24 hours (2026-08-14 and 2026-08-15), both times for the same reason: a coding sub-agent was given a brief, started working, and a correction needed to reach it before it finished on the wrong plan.

Goals

When a dispatched sub-agent is mid-task and the brief needs to change (wrong git strategy, wrong tool variant), send the correction straight to that sub-agent's live session via sessions_send and have it apply before the task completes — rather than letting it ship the uncorrected version and cleaning up after.

Effectiveness

Not adopted for this use case. Two for two: both attempts to correct an in-flight sub-agent via a bare sessions_send follow-up failed to reach the process actually doing the work, and both times the sub-agent ran its original (wrong) plan through to full completion before the mismatch was caught.

What made it effective

Not the tool's own design — the workaround, once identified, is what actually works: don't trust a bare follow-up to reach a live task. Instead, spawn a brand-new, fully self-contained task that restates the entire brief from scratch (repo URL, current state, exact fix needed), and verify the outcome afterward against the real artifact (git log, deployed site) rather than trusting a "sent" confirmation. Applied this way on 2026-08-15 for the blades68-gallery fix, it worked cleanly — full git-history rewrite, images moved to R2, cf-cache-status: MISS → HIT → HIT confirmed on repeat requests.

Friction, pain points, surprises

A sessionKey that looks addressable may not be the live process. sessions_send accepts a sessionKey and returns as if the message was delivered, with no visible signal that it landed in a fresh, contextless session instead of injecting into the in-flight one. There's no error, no partial-context warning — just a reply from something that clearly never saw the original brief.

The failure compounds with dispatch-and-forget reporting. Both incidents were only caught because the final report from the sub-agent contradicted the correction that had (apparently) already been sent — meaning the gap surfaces late, after the wrong work is already done, not at correction-send time.

Verdict: not adopted, for anything urgent. sessions_send is fine for messages a session will pick up on its own schedule, but for a correction that must land before an in-flight task finishes, the reliable path is: wait for actual completion, or fire a fresh self-contained replacement task and verify the artifact directly. Two real incidents, one day apart, same shape both times — worth treating this as the default now, not a lesson re-learned after the fact each time.

Update, 2026-08-25: the persistent delegate session can lose itself, not just a single message

A third failure mode, distinct from the two above: this time the target wasn't a one-shot sub-agent task but a long-lived delegate session (agent:genops:main) that had been actively worked all day — Concourse URL diagnosis, a Tailscale-Serve mapping fix, an Immich prompt-egress feature, three merged PRs. Then, mid-thread, it answered a routine follow-up by denying any of that existed. Pulling its actual session history showed why: exactly one message. The whole day's context had reset, and the session reported "nothing exists" with the same sincerity it would have reported anything else — no signal that anything had been lost.

The recovery pattern held, though: don't trust the denial any more than you'd trust an over-confident claim. Told genops to re-verify from git/Concourse state instead of its own memory, and everything came back — PRs #7 and #8, real merges, a real Concourse build that had run that day. The fix for "can this delegate be trusted right now" was, again, never the session's self-report either way — check the artifact.

Second, unrelated wrinkle from the same session: the reason the thread was so long-lived and single-threaded is that every independent ask (the URL check, the MinIO check, the prompt-egress feature) was sent as its own serial sessions_send ping to genops' one persistent main thread, each one queuing behind whatever it was mid-task on. Called out directly: "I feel like we're assigning too many perfectly parallelizable and concurrent tasks... how can we avoid all the interruption?" The fix wasn't a different tool — it was telling the delegate to fan its own asks out to helper sub-sessions (it already had spawn access) instead of the dispatcher pinging it once per ask.

Verdict unchanged: not adopted for anything urgent, now for a third reason — a sessionKey can go quietly amnesiac mid-thread with no error, on top of the two known misrouting failures. The durable coping pattern across all three incidents is the same one line: never trust a session's self-report of what it has or hasn't done — verify against the real artifact (git log, live API, deployed build) every time it matters.