Intelligence

The Session ID Matched. The Conversation Did Not.

Two open GitHub issues, one upstream and one downstream, describe the same gap from opposite sides. An Agent Client Protocol adapter for Claude Code can accept a client allocated session identifier, complete the request, and return that identical identifier, without anything in the exchange establishing that the native conversation the identifier names was the one actually carried forward.

Event analysed: . This analysis was published on 7 September 2026.

When a system resumes or continues a named session by accepting and returning the exact identifier a caller supplied, does that prove the underlying conversation state was actually carried forward?

No, and two related, currently open GitHub issues against the Agent Client Protocol adapter for Claude Code show why. Issue agentclientprotocol/claude-agent-acp#1019, opened 21 August 2026, reports that resuming a native claude session started with claude session id through the adapter accepts a client allocated UUID, completes the turn, and returns that identical UUID, while a marker planted only in the native session's own prior history is not recovered and no explicit continuity failure, such as a resource not found response, is raised. The issue itself is careful about what this does and does not establish: the same identifier being requested and returned does not prove the same history was loaded, and the history's absence does not itself prove the adapter created a brand new session, only that whatever state the turn drew on was not that specific native history. The issue's own leading explanation, that the SDK bundled Claude Code executable and the native CLI executable involved may not share a session store, is offered explicitly as an unproven hypothesis. Issue taras/executable.md#770, opened 7 September 2026 by the same reporter and referencing #1019 directly, documents a downstream project's own response to the identical pattern: the ACP handle a resume call returns carries a backendSessionId equal to the caller's own requested UUID with no independently asserted agentSessionId alongside it, and the reporting project's own tooling refuses to send any prompt into that handle, on the stated basis that identifier equality alone is not independent continuity evidence. Neither issue has a maintainer reply, a linked fix, a formally assigned vulnerability identifier, or any report of exploitation as of this record's own direct verification on 7 September 2026. The general principle both issues point at, independent of whichever exact mechanism eventually explains #1019, is that a value a caller supplied or already held, returning unchanged in a response, is not on its own independent evidence that the state it names was located and continued. That evidence has to come from somewhere the caller's own request did not reach.

A resume operation is a small, specific promise. A caller names a session, a conversation, some prior state, by an identifier, and asks the system to pick up where that identifier left off. The promise is easy to state and, it turns out, easy to appear to keep without actually keeping it, because the most visible evidence a caller normally checks, did the call succeed, and did it return the identifier I asked for, can be satisfied by a system that never located the state the identifier names at all. Two open GitHub issues, filed a little over two weeks apart against the same class of adapter, describe exactly that gap from two different vantage points.

What agentclientprotocol/claude-agent-acp#1019 reports

The issue, opened 21 August 2026 by a user going by taras, concerns the Agent Client Protocol, ACP, adapter that lets an ACP capable client drive Claude Code. Its own reproduction is precise and, this record confirms by direct fetch, unambiguous about what it tests. A UUID is allocated client side. The native Claude Code CLI is run directly, claude --session-id followed by that UUID, and a turn is created inside that native run containing a marker, some word or phrase, that exists nowhere except in that turn's own history. Separately, through the ACP adapter, from the same working directory, the identical UUID is presented to resume that session. A prompt is then sent that never mentions the marker itself but asks the model to recall it, something only genuine access to the native turn's own history could answer.

What the issue reports observing: the adapter accepts the UUID. The SDK backed query underneath it initializes. The ACP turn completes normally. The same UUID is returned, or otherwise retained, as the session's own identity for the exchange. The marker is not recovered. No resource_not_found, no distinct continuity failure of any kind, is raised at any point.

The issue names the versions involved precisely, and this record preserves them exactly rather than rounding them together: @agentclientprotocol/claude-agent-acp@0.70.0, running on @anthropic-ai/claude-agent-sdk@0.3.232, which itself bundles a Claude Code executable at version 2.1.232. The native session that created the marker was run under a separately installed native Claude Code host at version 2.1.235. The ACP client driving the exchange is acpx@0.12.0.

The issue's own author is explicit, and this record treats that explicitness as part of what makes the report worth taking seriously, about the exact limits of what the reproduction shows. Same requested and returned identifier does not prove the same conversation history was loaded. Absent native history does not itself prove the adapter minted a brand new session, only that whatever the turn actually drew on was not that specific native history. The exact internal mechanism, what the adapter did instead, is not established by the reproduction, and the issue does not claim otherwise.

The issue does offer a leading explanation, and is equally explicit that it is exactly that, an explanation offered, not a finding established: an executable and version mismatch. The SDK bundled Claude Code build, 2.1.232, may run against a session store the native CLI's own build, 2.1.235, does not share or does not resolve the same way, so a resume request that looks, from the ACP client's side, like it should reach the native session's own stored history may simply never reach a store that history is actually in. This record states that hypothesis exactly as the issue states it, unproven, because whether it is the actual mechanism is not something either this record or the issue itself has established.

What taras/executable.md#770 adds

The second issue, opened 7 September 2026, the same day this record was written, by the same reporter, and explicitly naming and referencing #1019 in its own text, comes from a different angle entirely: not a reproduction designed to expose the gap, but a real integration's own encounter with it. The reporting project, XMD, launches Claude coding sessions through the native terminal CLI under a session identifier it retains client side, the same general shape #1019's reproduction uses. When XMD later tries to continue that same logical session through ACP, the adapter accepts the retained UUID for a session/resume call. What comes back is an ACP handle whose backendSessionId equals the requested UUID exactly, and whose agentSessionId, a field the issue's own author treats as the place an independent, provider native assertion of session identity would live, is absent.

The issue's own framing of why that absence matters is worth stating precisely, because it is the sharper of the two issues' contributions: a backendSessionId that merely equals the requested identifier could, on the evidence available, be nothing more than the adapter echoing the caller's own request back, rather than the provider independently asserting that it located and is now representing specific existing state. Nothing in what came back distinguishes those two possibilities. XMD's own tooling treats that as insufficient continuity evidence and refuses before sending any prompt at all. The reported outcome is precise: the adapter attachment returned, no prompt was sent, the underlying Claude transcript this record can confirm from the issue's own text was left unchanged, and the adapter and experiment processes closed cleanly. This is a caller declining to proceed on ambiguous evidence, not a caller sending a prompt into substitute history and getting a bad answer. No unsafe action is reported anywhere in this issue.

The one phenomenon these two issues carry, not two

It is worth being exact about the relationship between these two reports, because treating them as two independent confirmations of the same mechanism would overstate what is actually known. One author filed both. #770 references #1019 directly. #1019 is the primary occurrence, a controlled, marker based reproduction against the phenomenon itself. #770 is downstream, fail closed integration behavior reacting to the same underlying uncertainty #1019 documents, at a different Claude Code version, 2.1.263 rather than 2.1.235, and through a different consuming project. This record treats #1019 as the mechanism level evidence and #770 as extending it into what a careful downstream integrator does when that mechanism's own continuity guarantee cannot be independently confirmed, not as a second, separately reproduced instance of the same root cause.

What neither issue shows

Neither issue carries a comment from a maintainer of claude-agent-acp. Neither has a linked pull request proposing a fix. Neither has a formally assigned CVE or any other vulnerability identifier. Neither reports that the gap has been exploited, that any consequential action was taken on the strength of a false continuity assumption, or that any real deployment has been affected beyond the reporter's own reproduction and the reporting project's own refusal to proceed. This record found, and states plainly, that the current latest published version of the adapter on the npm registry, confirmed by this record's own direct fetch of the registry's own JSON on 7 September 2026 after npmjs.com's rendered package page itself returned a blocked response, is 0.75.1, five minor versions past the 0.70.0 both issues test against. Nothing available to this record states, and this record does not claim, that 0.75.1 addresses either issue; no changelog, release note or maintainer statement connecting a later release to either report was found anywhere this record could reach.

Why an identifier coming back unchanged is not, by itself, continuity evidence

Strip away the specific executables and version numbers, and what both issues point at is a verification problem that shows up anywhere one system asks another to resume something by name. A caller requests continuation of logical state S, identified by some value, a UUID, a session id, a handle. The value returned as confirmation is very often the identical value, or a value derived from, the one the caller supplied in the first place. That fact, by itself, proves only that the two systems agree on what string they are both calling S. It proves nothing about whether the state actually behind S on the responding side is the state the caller means when it thinks of S, because a system with no matching state at all, one that simply echoes a request or quietly opens a fresh replacement under the same name, produces exactly the same surface signal, the same string coming back, as a system that genuinely located and loaded the original state.

This is a distinct failure from an actor asserting authority nothing checks, or from a check that runs and fails and gets treated as a pass anyway. Nothing here is a false claim in words, and the evidence available does not establish that any resolution step ran and failed at all. What happens instead is that a single value is asked to do two jobs, name the request and prove the response, when nothing about its own text changes depending on which job it is actually doing. Distinguishing requested identifier, from independently provider asserted identifier, from returned or routing identifier, from the actual underlying state, from evidence a caller can use to tell them apart, is the discipline both issues are, in their own separate ways, arguing for. #1019 shows what happens when nobody asks the fourth question, whether the state matches, and gets no signal either way. #770 shows what a caller does when it insists on the second, an assertion independent of its own request, before it will accept the first three as sufficient.

Where this sits against what this desk has already argued

The broader argument that authority has to be evaluated at the point of execution rather than assumed from an earlier instruction or handshake is the family this piece belongs to, applied here to a narrower and more mechanical question: what does a resume handshake itself actually establish. Instructions are not authorization concerns a different verification gap, an agent accepting a claim of permission nothing checks; the gap here is not a claim in words at all, it is a structural value doing double duty as both a request and its own proof. GitLab's own requirement that an agent identity and the human behind it both be established, not one standing in for the other, is a related but separate discipline, identity of the actor rather than continuity of the state a session names; the failure mode here would persist even if every actor involved were perfectly, independently authenticated, because the question is not who is asking but whether what comes back was actually continued from what came before. The question of what a long running agent remains authorized to do as time passes past its original grant assumes, as its starting point, that the session carrying that grant forward is genuinely the same session; this record is about what happens when that starting assumption itself goes unverified.

The Authority Provenance ledger

Authority grantor. In #1019's reproduction, the caller who allocates the session UUID client side and later presents it to the ACP adapter is the only party shown taking an action; the issue does not describe any distinct party granting the caller authority to name or resume a session by a UUID of its own choosing. In #770, XMD, the downstream project, plays the equivalent role, retaining and later presenting the same UUID it originated. Neither issue describes a third party, an operator, a policy engine, standing between the caller and the adapter's own accept or refuse decision.

Mandate or basis. Undocumented in both issues. Neither states, and this record does not infer, what entitles a caller who allocated a UUID client side to have that allocation treated by the adapter as sufficient grounds to resume whatever session, if any, the native CLI separately created under the identical string. The adapter's own acceptance of a client supplied identifier as sufficient to attempt a resume is the behavior both issues describe; neither issue's own text states the design rationale behind that acceptance.

Delegated scope. This is the center of both issues, and the evidence, drawn directly from each issue's own text, is precise about where the scope actually sits. What the adapter's resume path is shown accepting is an identifier string. What it is not shown independently confirming, in either report, is that a specific, existing native conversation is bound to that string on the side that actually holds Claude Code's own session history. #1019's reproduction demonstrates the gap between those two things by making the second one absent while the first one still succeeds; #770 demonstrates the same gap by describing what the adapter's own resume response does and does not carry, a backendSessionId equal to the request, no separately asserted agentSessionId.

Explicit limits. Recorded here exactly as each issue itself states them for the specific versions each one tests, not generalized beyond that. #1019: adapter 0.70.0, SDK 0.3.232 bundling Claude Code 2.1.232, tested against a native host at 2.1.235, ACP client acpx 0.12.0. #770: adapter 0.70.0 again, tested against a native host at 2.1.263. Neither issue states that every version of the adapter, or every native Claude Code build, exhibits the gap; both describe the specific combinations each reporter actually ran.

Inherited permissions or assumptions. What the resumed turn in #1019 actually operated with, if not the native session's own history, is not established by the issue and is not established by this record. The issue's own account states only what was absent, the marker, and what was present, a completed turn under the requested UUID; it does not describe the resumed turn's actual context, tool access or privilege level beyond that.

Revocation or modification path. Not described in either issue. Neither reports a way for a caller to force the adapter to fail explicitly rather than proceed on an unconfirmed resume, and neither reports a setting, flag or configuration that changes the observed behavior.

Challenge authority. This is the one place the two issues diverge in outcome rather than only in vantage point, and it is worth naming plainly. In #1019, nothing in the exchange itself challenges the resume; the turn simply completes. In #770, the downstream project's own tooling is the challenge authority, applying its own rule, that a backendSessionId merely equal to the requested identifier is not independent continuity evidence, and refusing to proceed on that basis before any prompt is sent. That refusal is caller side policy, not a capability the adapter or the ACP protocol itself is shown offering; nothing in either issue describes the adapter surfacing a distinct, protocol level signal a caller could check instead of building its own refusal rule.

Recovery path. Not applicable to #770, where the reporting project's own refusal meant nothing needed recovering. Not described in #1019 beyond the reproduction itself; the issue does not report a way to detect, after the fact, that a completed resumed turn drew on absent or substitute history, other than the deliberate marker test the reproduction itself constructs.

Provenance evidence quality. Both issues were fetched directly by this record on 7 September 2026, and their title, author, opened date, open state, zero comment count, absence of a linked fix, and the specific version numbers and reproduction details each states are confirmed against that direct read rather than assumed. What neither this record nor either issue itself establishes: the actual internal mechanism behind #1019's observation, whether the version skew explanation is correct, whether any maintainer response exists that has not yet been posted publicly, and whether this exact gap has occurred, or been tested for, anywhere beyond these two reports. Each of those is recorded as unknown rather than inferred from the pattern the two issues together suggest.

What this does not show

This is not a claim that claude-agent-acp returns the wrong session identifier; both issues describe it returning the one requested. It is not a claim that the adapter definitely creates a new session on every resume; the observation is that native history was absent, not that a specific alternative mechanism produced that absence. It is not a claim that a fix exists and has not shipped, or that one does not; nothing available to this record states either. It is not a claim that a stale approval was ever acted on in the wrong context; #770's own reported outcome is a refusal before any prompt was sent, fail closed behavior, not a demonstrated exploitation. There is no CVE here, and no known exploitation. What stands, on the evidence two currently open, unaddressed GitHub issues carry, is narrower and, on its own terms, still worth stating plainly: an identifier returning unchanged is evidence that two systems agree on a name. It is not, by itself, evidence about what either of them is holding behind it.

Sources

This analysis interprets third-party reporting, research and announcements. Moona is not the original reporter of the underlying events.

[1]
Resuming a native claude --session-id conversation silently completes without its history instead of loading it or failing
agentclientprotocol/claude-agent-acp (GitHub Issues) · taras · 21 August 2026 · Primary source
[2]
Make Claude native-to-ACP continuation preserve the exact conversation
taras/executable.md (GitHub Issues) · taras · 7 September 2026 · Primary source
[3]
@agentclientprotocol/claude-agent-acp, latest version (npm registry)
npm, Inc. · 7 September 2026 · Technical documentation

Related Intelligence

All Intelligence Records →