Skip to content

Real Codex and Claude adapters assert no durable session identity, so #302 reattachment cannot hold #639

Description

@taras

What is wrong

The workflow Agent session mapping (#302, specs/workflow-workspace-spec.md §8.5) commits only from a canonical, tagged provider assertion. ACPX supplies that from the ACP session/new response's _meta, reading the first of agentSessionId or sessionId:

const AGENT_SESSION_ID_META_KEYS = ["agentSessionId", "sessionId"];

Neither published adapter puts anything there.

  • @agentclientprotocol/codex-acp returns { sessionId, models, modes, …configOptions } from newSession — no _meta.
  • @agentclientprotocol/claude-agent-acp likewise returns no session-identity _meta.

So retainedSession(store, placementKey)?.agentSessionId is always undefined, and the profile refuses before the first Prompt:

the provider established an Agent session without asserting a durable identity, so this run cannot record which conversation it is having.

How it was found

Running a real workflow through the compiled dist/xmd against a real (embedded) Codex adapter, while verifying #622. Reproduction:

deno compile --node-modules-dir=none --cached-only --frozen --exclude-unused-npm \
  --allow-all --include packages/code-review-agent --output dist/xmd packages/cli/src/compiled.ts

# a git repo whose flows/agent.md is: <Session name="review"><Prompt>hello</Prompt></Session>
CODEX_PATH=packages/acp/tests/fixtures/fake-codex-app-server.cjs \
XMD_WORKFLOW_RUNS=<tmp>/runs \
  ./dist/xmd workflow start --id=smoke-1 flows/agent.md

The adapter materializes, launches, and completes ACP initialize and session/new. The run then fails at the assertion check above.

Why every test passes today

packages/cli/tests/support/fake-acp.ts fabricates one:

agentSessionId: `agent-session:${input.sessionKey}`

Every WAL, WSR and WSL case substitutes that fake runtime, so the contract has never been exercised against a real adapter. The gap is in the contract's fit to real adapters, not in the retention code.

Scope

This blocks end-to-end portable Agent use: no workflow run can establish a session against a real Codex or Claude adapter, so no Prompt is ever sent and nothing is retained.

It does not belong to #622, whose acceptance is transport and retention of a checkpoint once a Prompt completes, and whose production evidence is compositional (Tier EA for the adapters, the compiled binary for materialization and launch, T2–T6 for retention through XMD). #622's compiled proof may terminate at exactly this refusal.

What a fix has to decide

  • whether the identity comes from an upstream adapter change (a _meta.sessionId on session/new, alongside the Retain provider checkpoint tokens for workflow Agent Prompts #622 prompt-response work), or from a different canonical assertion this host accepts;
  • what an existing run does when it retained a mapping under one scheme; and
  • a regression that exercises the contract against a real adapter rather than a fabricated identity — the absence of which is why this went unnoticed.

Context

  • packages/acp/vendor/acpx/generated/live-checkpoint-ClPCSdrW.jsextractAgentSessionId
  • packages/cli/src/workflow-agent.tsassertionsFor, established
  • specs/workflow-workspace-spec.md §8.5
  • Closed issue Run workflow Agents through XMD-mediated observations #302 owns the contract; this is the narrowly scoped repair under it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions