[BUG] SendMessage tool description denies any address syntax while uds:<socket> addresses work and are documented elsewhere in the same build

Status Open
Reported on v2.1.251
Maintainer reply None cached
Activity 0 comments · opened Aug 29, 2026

Preflight

  • [x] I have searched existing issues; the closest are #84920 (the same schema-vs-transport mismatch for bridge: addresses cross-machine) and #84894 / #86019 (name and self-identification gaps) — none covers the same-machine uds: form or the description's affirmative denial that any address syntax exists
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.251)

Summary

The SendMessage tool description presented to the model states, about ListAgents rows: "the name IS the address; there is no separate address syntax", and its to parameter schema documents only names, main, and agent ids.

This is contradicted by the same build three ways: other tool descriptions embedded in the same binary accept "an explicit uds:<socket> / bridge:<session id> address"; the cross-session messaging docs present the uds:-prefixed socket path as the session's own inbox address (/status → Peer address row); and a live SendMessage with a raw uds: address delivers successfully.

The description doesn't merely omit the address forms — it affirmatively denies they exist, which steers the model to treat working address-based automation as broken.

Reproduction

  1. In a session on 2.1.251, read the SendMessage tool description and to schema.
  • Result: "the name IS the address; there is no separate address syntax"; to documents a name from ListAgents, a teammate name, main, or a background agent's agentId — no address form.
  1. Run strings on the release binary and search for uds:.
  • Result (excerpts):

``
, or an explicit
uds:<socket> / bridge:<session id> address.
Recipient: a peer session name from ; , or an explicit uds:<socket> / bridge:<session id> address
``

  1. With a second live session on the machine, find its socket under /tmp/cc-socks*/ (also shown in that session's /status → Peer address) and call SendMessage with to: "uds:/tmp/cc-socks/<pid>.sock".
  • Result: {"success":true,"message":"… → uds:/tmp/cc-socks/<pid>.sock","msg_id":"33da2aeb-…"} — the send is accepted and assigned a message id.

Scope

  • This is a schema/description consistency bug, not a transport bug: the transport works as (elsewhere) documented. The defect is that the model-facing description denies the address form the build accepts and other surfaces document.
  • Distinct from #84920, which covers bridge:<session id> cross-machine and the false "reply-only" claim. This report is the same-machine uds: form and the "no separate address syntax" sentence specifically.

Why this matters

The uds: address is the only deterministic way a session can identify itself to other sessions. The only officially documented to form for cross-session sends is the session name (plus listing-scoped [ref]s, main, and in-session agentIds), and a name cannot serve as a self-identifier a session hands out:

  • No environment variable exposes the session's own name. The exported set is CLAUDE_CODE_MESSAGING_SOCKET, CLAUDE_CODE_MESSAGING_TOKEN, CLAUDE_CODE_SESSION_ID, and CLAUDE_PID — so a SessionStart hook or bootstrap script that wants to tell peers "reach me here" has the socket path and nothing else.
  • Names are non-deterministic as identifiers even when known: they are harness-generated, changeable mid-session with /rename, and silently renamed to a variant when a new session collides with an existing name — so a name emitted at session start can be stale or ambiguous by the time a peer uses it.
  • [ref]s are explicitly non-transferable: the schema says a ref "you did not just read from a listing or an error will not resolve", so one carried in a message is useless to the receiver.
  • CLAUDE_CODE_SESSION_ID matches no documented to form (its only plausible consumer is the bridge:<session id> form, itself undocumented — #84920).

That leaves uds:$CLAUDE_CODE_MESSAGING_SOCKET as the only identifier that is exported to the session's own scripts and hooks, stable for the session's lifetime, and accepted by SendMessage — which is why bootstrap scripts and multi-session handshakes are built on it.

The description's affirmative denial then does real damage, because capable models follow tool text literally and weigh it above a user's own scripts. Concretely: an automated maintenance agent of ours read the schema, concluded a session-bootstrap script's (correct) statement that to accepts the socket address was stale, and raised a PR dismantling a tested multi-session handshake.

Expected

Any of, in preference order:

  1. Document the accepted address forms (uds:<socket>, bridge:<session id>) in the SendMessage description and to schema, as the binary's other recipient descriptions already do.
  2. If the forms are meant to be internal, state their support level explicitly ("addresses such as uds:… are accepted but unsupported/subject to change") rather than asserting no address syntax exists — and note that deprecating uds: without a replacement would leave sessions with no deterministic self-identifier at all, since no documented to form is derivable from the session's environment.
  3. At minimum, reconcile the description variants within one build so the model isn't shown a sentence its own tool surface elsewhere contradicts.

Related issues

  • #84920 — bridge: addresses work cross-machine while every surface says reply-only (same class, different form and claim)
  • #84894 — display names not exposed in ListAgents or accepted by SendMessage
  • #86019 (closed) — a session cannot identify itself in ListAgents

Is this a regression?

I don't know when the "no separate address syntax" wording was introduced; observed on 2.1.247 and 2.1.251.

Environment

  • Claude Code: 2.1.251 (also observed with 2.1.247 as the running build)
  • OS: macOS 15 (Darwin 25.4.0)
  • Model: claude-fable-5

View original on GitHub ↗