Skip to content

fix(sessions): report ACP-runtime metadata for ACP-keyed sessions#79550

Merged
galiniliev merged 7 commits into
openclaw:mainfrom
efpiva:edpiva/acp-runtime-overlay
May 14, 2026
Merged

fix(sessions): report ACP-runtime metadata for ACP-keyed sessions#79550
galiniliev merged 7 commits into
openclaw:mainfrom
efpiva:edpiva/acp-runtime-overlay

Conversation

@efpiva

@efpiva efpiva commented May 8, 2026

Copy link
Copy Markdown
Contributor

Summary

ACP sessions reported agentRuntime.id: "auto" (post-02fe0d8978) — which is also wrong, since they aren't routed via the auto runtime; they're driven by acpx. Add a session-key-aware overlay applied at the production resolver so ACP-keyed rows report { id: "acpx", source: "session-key" }. Closes catalog #18.

Bug detail

Running openclaw sessions --all-agents --json against the deployed container produced (excerpt, redacted UUIDs):

{
  "key": "agent:copilot:acp:86b7b5af-…",
  "agentId": "copilot",
  "agentRuntime": { "id": "auto", "source": "implicit" },
  "kind": "direct"
}

The :acp: segment unambiguously marks an ACP session, yet the JSON labels it as runtime "auto". The original catalog finding documented "pi", but commit 02fe0d8978 ("Keep OpenAI Codex migrations on automatic runtime routing") had already shifted the unrecognized-model default from "pi" to "auto" before this PR was opened. The remaining bug — the production path returning the wrong runtime identifier for ACP sessions — is what this PR addresses.

How to reproduce

Live repro before fix (deployed container, OpenClaw 2026.5.6):

docker exec codeclaw-openclaw openclaw sessions --all-agents --json \
  | jq -c '.sessions[] | select(.key | startswith("agent:copilot:acp:")) | .agentRuntime'
{"id":"auto","source":"implicit"}
{"id":"auto","source":"implicit"}
{"id":"auto","source":"implicit"}
…

7/7 ACP sessions report auto/implicit.

Unit-level:

git checkout 4195dd0bf6            # red-test cherry-pick
pnpm test src/commands/sessions.acp-runtime-metadata.test.ts
# Before fix: 2 RED (resolveModelAgentRuntimeMetadata returns "auto" for ACP sessions; should be "acpx")
# After fix commits 6860ee0385 + 952afa3114: all 3 GREEN

Root cause

The 6 production emit sites all call resolveModelAgentRuntimeMetadata(...), which had zero session-key awareness — it routed off model identity / config policy only. ACP sessions, having no special model identity, fell into the post-02fe0d8978 default of "auto".

Fix approach

Caller-side overlay. Keeps the resolver pure; aligns with the same pattern PR 7 (catalog #20) uses for the model / modelProvider columns:

  1. NEW src/agents/acp-runtime-overlay.ts — exports applyAcpRuntimeOverlay(meta, sessionKey). When isAcpSessionKey(sessionKey) is true, returns { id: "acpx", source: "session-key" }; otherwise returns meta unchanged.
  2. Extends AgentRuntimeMetadata.source union with "session-key". Two downstream type unions (GatewayAgentRuntime.source, AgentListEntry.agentRuntime.source) needed the same | "session-key" addition for type compatibility — included as additive type-propagation.
  3. resolveModelAgentRuntimeMetadata calls the overlay with the session key. The 6 emit sites all already call this resolver and inherit the fix automatically — no per-call-site change needed.
  4. resolveAgentRuntimeMetadata left untouched as the 02fe0d8978 stub. The original implementation attempted to revert that contributor's intentional refactor (which had stubbed resolveAgentRuntimeMetadata to return { id: "auto", source: "implicit" }); after review, the stub-revert was undone in cleanup commit 952afa3114 to respect the upstream direction. Production already routes through resolveModelAgentRuntimeMetadata, where the overlay correctly applies.

Tests

  • Red test (now GREEN): src/commands/sessions.acp-runtime-metadata.test.ts — 3 cases:
    • ACP session id is not "auto" (the post-02fe0d8978 default) — overlay must take precedence
    • ACP session id is "acpx" — overlay sentinel
    • Non-ACP session does NOT receive the "acpx" sentinel (control)
  • Adjacent suite: src/commands/ (vitest.commands.config.ts shard) — passing.
  • Cleanup commit (952afa3114): reverted the unauthorized stub-restoration, kept the production overlay, retargeted the test at resolveModelAgentRuntimeMetadata.

Catalog reference

Catalog finding: #18. Investigation lives in branch edpiva/acp-native-session-investigation (not yet upstream) at docs/plans/2026-05-08-acp-findings-catalog.md.

Verification commands

pnpm test src/commands/sessions.acp-runtime-metadata.test.ts   # 3/3 GREEN
pnpm exec vitest run --config test/vitest/vitest.commands.config.ts src/commands/   # passes

Updates

Bot feedback addressed (P2, commit d4a6eb0b92): the overlay now reads entry.acp.backend instead of hard-coding "acpx". When a session entry carries an explicit acp.backend (configurable ACP backend, binding/agent override, or persisted entry.acp.backend), that value is used as the runtime id. Fallback to "acpx" only when no backend is set on the entry. acpBackend is threaded from call sites that have the session entry in scope (sessions.ts, session-utils.ts, server-methods/sessions.ts, status.summary.runtime.ts); call sites without an entry in scope (agents-list-tool.ts, session-utils.ts agent-list path, doctor-claude-cli.ts) continue to receive the "acpx" fallback. Two new test cases added: one proving a custom backend is reported, one proving the fallback fires when no backend is set. All 5 test cases green.

Notes for reviewers

  • The original catalog framing of "pi" is stale — 02fe0d8978 shifted unrecognized-model default to "auto". The actual production-path bug is the ACP runtime not being identified at all; this PR fixes that without touching resolveAgentRuntimeMetadata's stub.
  • The two downstream type-union edits (src/shared/session-types.ts, src/agents/tools/agents-list-tool.ts) add | "session-key" to keep the gateway/tools row types compatible with the new source variant. Additive only.
  • The new acp-runtime-overlay.ts helper is reused by PR 7 (catalog Heartbeat skipped when last inbound message is from a group chat #20model/modelProvider ACP-aware), which currently inlines the equivalent logic awaiting this PR. After both land, PR 7 can be slimmed via a small follow-up to import from this file.

Real behavior proof

Behavior addressed: ACP control-plane rows from openclaw sessions --json, status, and Gateway session RPC metadata now report ACP runtime metadata from persisted ACP session metadata/backend instead of the implicit model runtime. ACP-shaped bridge rows without entry.acp are not overlaid.

Real environment tested: Maintainer Linux worktree at PR SHA 4ebbf1d7e9242924df520cdaefd1f2e3bedc91dc, rebased on upstream/main 97ed9b2d82950dd64b94c4fd1ac732e701b54a24. Earlier Azure Crabbox seeded-session proof for the original runtime overlay ran on amber-lobster / cbx_4c7c7efb6dc7; the new bridge guard was verified locally after the rebase fix.

Exact steps or command run after this patch: Seeded a temp OPENCLAW_CONFIG_PATH and explicit session store with an ACP control-plane row carrying entry.acp.backend = "acpx", an ACP-shaped bridge row with no entry.acp, and a non-ACP control row, then ran:

OPENCLAW_CONFIG_PATH="$proof_dir/openclaw.json" OPENCLAW_HOME="$proof_dir/home" pnpm --silent openclaw sessions --store "$proof_dir/sessions.json" --json

pnpm test src/commands/sessions.acp-runtime-metadata.test.ts src/commands/sessions.acp-model-display.test.ts -- --reporter=verbose
pnpm tsgo:core
pnpm tsgo:core:test
pnpm exec oxfmt --check --threads=1 src/agents/acp-runtime-overlay.ts src/agents/agent-runtime-metadata.ts src/commands/sessions.acp-runtime-metadata.test.ts src/commands/sessions.ts src/commands/status.summary.runtime.ts src/gateway/session-utils.ts src/gateway/server-methods/sessions.ts
git diff --check upstream/main...HEAD

Evidence after fix: Copied terminal output from the after-fix CLI run and focused tests:

AFTER_FIX_ACP_AGENT_RUNTIME={"id":"acpx","source":"session-key"}
CONTROL_ACP_BRIDGE_AGENT_RUNTIME={"id":"auto","source":"implicit"}
CONTROL_NON_ACP_AGENT_RUNTIME={"id":"auto","source":"implicit"}
AFTER_FIX_ACP_SESSION_ROW={"key":"agent:copilot:acp:proof-79550","agentId":"copilot","kind":"direct","modelProvider":"acpx","model":"copilot-acp","agentRuntime":{"id":"acpx","source":"session-key"}}
CONTROL_ACP_BRIDGE_SESSION_ROW={"key":"agent:copilot:acp:bridge-proof-79550","modelProvider":"microsoft-foundry","model":"gpt-5.3-codex","agentRuntime":{"id":"auto","source":"implicit"}}
src/commands/sessions.acp-runtime-metadata.test.ts: 6/6 tests passed
src/commands/sessions.acp-model-display.test.ts: 4/4 tests passed
pnpm tsgo:core: passed
pnpm tsgo:core:test: passed
oxfmt touched-file check: passed
git diff --check upstream/main...HEAD: passed

Observed result after fix: The ACP control-plane session row reports agentRuntime.id: "acpx" and source: "session-key"; the ACP-shaped bridge row keeps modelProvider: "microsoft-foundry", model: "gpt-5.3-codex", and normal implicit runtime metadata, so key shape alone no longer triggers the ACP runtime overlay.

What was not tested: No live ACP provider/harness turn with external credentials was run after the maintainer rebase fix; this was seeded session-store CLI proof plus focused regression/type/format checks.

@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations agents Agent runtime and tooling size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 8, 2026
@clawsweeper

clawsweeper Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

Summary
The PR adds an ACP runtime metadata overlay, threads persisted ACP session metadata/backend into sessions CLI, status, and Gateway session rows, and adds regression coverage plus a changelog entry.

Reproducibility: yes. Source inspection shows current main builds ACP-aware session rows but does not pass persisted ACP metadata/backend into runtime metadata resolution, and the PR body includes a deployed-container repro showing auto/implicit for ACP rows before the fix.

Real behavior proof
Sufficient (terminal): The PR body includes after-fix terminal output from a seeded real CLI session-store run at the PR SHA plus focused regression/type/format checks, with controls for bridge and non-ACP rows.

Next step before merge
No repair lane is needed; the PR has no blocking review findings and should proceed through ordinary CI and maintainer merge handling.

Security
Cleared: No concrete security or supply-chain concern found; the diff changes metadata classification, type unions, tests, and changelog only.

Review details

Best possible solution:

Land the ACP metadata overlay after normal CI and maintainer merge checks, keeping the entry.acp-gated bridge-session guard and backend-derived runtime id.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection shows current main builds ACP-aware session rows but does not pass persisted ACP metadata/backend into runtime metadata resolution, and the PR body includes a deployed-container repro showing auto/implicit for ACP rows before the fix.

Is this the best way to solve the issue?

Yes. The patch is the narrow maintainable fix: keep model/runtime policy pure, then overlay runtime metadata only when both the ACP key shape and persisted ACP metadata identify a control-plane session.

What I checked:

  • current resolver lacks ACP metadata input: On current main, resolveModelAgentRuntimeMetadata accepts cfg/agent/model/provider/sessionKey and returns policy runtime/source, but has no parameter for persisted SessionAcpMeta or backend, so ACP control-plane rows can fall through to auto/implicit. (src/agents/agent-runtime-metadata.ts:21, 3ce922437fb6)
  • current sessions path computes ACP marker but does not pass it to runtime metadata: Current main derives acpRuntime from entry.acp for the model overlay, then calls resolveModelAgentRuntimeMetadata with only the session key, provider, and model for agentRuntime. (src/commands/sessions.ts:286, 3ce922437fb6)
  • PR overlay uses persisted ACP metadata and backend: The PR adds applyAcpRuntimeOverlay so ACP-keyed rows with acpRuntime true return source session-key and id from acpBackend when available, falling back to acpx. (src/agents/acp-runtime-overlay.ts:33, 4ebbf1d7e924)
  • PR threads ACP metadata through production emit sites: The PR passes acpRuntime and acpBackend at sessions CLI, status runtime summary, Gateway session row, and sessions.patch response paths where the session entry is available. (src/gateway/session-utils.ts:1732, 4ebbf1d7e924)
  • persisted ACP session metadata includes backend identity: SessionAcpMeta includes a required backend string, and the ACP control-plane manager persists backend from the handle or resolved backend id during session initialization. (src/config/sessions/types.ts:41, 3ce922437fb6)
  • adjacent merged ACP sessions work supports the same guard shape: Merged ACP model-display work uses the same entry.acp plus ACP-key guard to avoid misreporting ACP-shaped bridge sessions, and the current PR preserves that distinction for runtime metadata. (src/commands/sessions.acp-model-display.test.ts:28, 207fb9951d67)

Likely related people:

  • efpiva: Authored merged ACP sessions work on current main for model/runtime-adjacent display and session-kind behavior, including the same entry.acp-gated sessions surface this PR extends. (role: recent adjacent sessions/ACP contributor; confidence: high; commits: 207fb9951d67, 9431d18aaf9f; files: src/commands/sessions.ts, src/commands/sessions.acp-model-display.test.ts, src/sessions/classify-session-kind.ts)
  • pashpashpash: Introduced the provider/model-scoped runtime policy baseline and auto/implicit behavior that this PR overlays for ACP session rows. (role: runtime policy refactor contributor; confidence: medium; commits: 02fe0d8978db; files: src/agents/agent-runtime-metadata.ts, src/gateway/session-utils.ts, src/gateway/server-methods/sessions.ts)

Remaining risk / open question:

  • I did not run local tests because this review was constrained to read-only inspection; verification relies on source review plus the PR body's terminal proof.
  • The supplied real behavior proof uses a seeded session store rather than a live ACP provider turn, which is appropriate for metadata plumbing but not a live-provider exercise.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 3ce922437fb6.

Re-review progress:

@openclaw-barnacle openclaw-barnacle Bot added the gateway Gateway runtime label May 8, 2026
@efpiva

efpiva commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

Bot feedback (P2) addressed in commit d4a6eb0b92: the overlay now reads entry.acp.backend and uses that as the runtime id instead of always hard-coding "acpx". Falls back to "acpx" only when no backend is set on the entry. Two new test cases cover both paths (5/5 green).

efpiva added a commit to efpiva/openclaw that referenced this pull request May 9, 2026
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 14, 2026
@galiniliev galiniliev self-assigned this May 14, 2026
efpiva and others added 7 commits May 14, 2026 01:41
…time-overlay and agent-runtime-metadata

Move AgentRuntimeMetadata type definition into acp-runtime-overlay.ts (the leaf
module) so agent-runtime-metadata.ts can import both the type and applyAcpRuntimeOverlay
from a single direction.  agent-runtime-metadata.ts re-exports the type to keep
all existing consumers unchanged.  Fixes check:madge-import-cycles failure in
check-additional-runtime-topology-architecture CI shard.
@galiniliev
galiniliev force-pushed the edpiva/acp-runtime-overlay branch from 82ecdb1 to 4ebbf1d Compare May 14, 2026 01:47
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 14, 2026
@galiniliev

Copy link
Copy Markdown
Contributor

Landing proof for PR #79550 at head SHA 4ebbf1d7e9242924df520cdaefd1f2e3bedc91dc.

Behavior addressed: ACP control-plane session rows now report ACP runtime metadata from persisted entry.acp metadata/backend, while ACP-shaped bridge rows without entry.acp keep normal configured model/runtime metadata.

Local verification from maintainer worktree:

pnpm test src/commands/sessions.acp-runtime-metadata.test.ts src/commands/sessions.acp-model-display.test.ts -- --reporter=verbose
pnpm tsgo:core
pnpm tsgo:core:test
pnpm exec oxfmt --check --threads=1 src/agents/acp-runtime-overlay.ts src/agents/agent-runtime-metadata.ts src/commands/sessions.acp-runtime-metadata.test.ts src/commands/sessions.ts src/commands/status.summary.runtime.ts src/gateway/session-utils.ts src/gateway/server-methods/sessions.ts
git diff --check upstream/main...HEAD

Observed local result: focused tests passed 10/10; pnpm tsgo:core passed; pnpm tsgo:core:test passed; touched-file format check passed; git diff --check upstream/main...HEAD passed.

User-facing seeded CLI proof after the maintainer fix:

AFTER_FIX_ACP_AGENT_RUNTIME={"id":"acpx","source":"session-key"}
CONTROL_ACP_BRIDGE_AGENT_RUNTIME={"id":"auto","source":"implicit"}
CONTROL_NON_ACP_AGENT_RUNTIME={"id":"auto","source":"implicit"}
AFTER_FIX_ACP_SESSION_ROW={"key":"agent:copilot:acp:proof-79550","agentId":"copilot","kind":"direct","modelProvider":"acpx","model":"copilot-acp","agentRuntime":{"id":"acpx","source":"session-key"}}
CONTROL_ACP_BRIDGE_SESSION_ROW={"key":"agent:copilot:acp:bridge-proof-79550","modelProvider":"microsoft-foundry","model":"gpt-5.3-codex","agentRuntime":{"id":"auto","source":"implicit"}}

CI / GitHub proof:

  • Real behavior proof: pass, run 25836878182, job 75913768253.
  • Scan changed paths (precise): pass, run 25836811138, job 75913561755.
  • Critical Quality (agent-runtime-boundary): pass, run 25836811126, job 75913574438.
  • Critical Quality (gateway-runtime-boundary): pass, run 25836811126, job 75913574432.
  • Critical Quality (session-diagnostics-boundary): pass, run 25836811126, job 75913574439.
  • Critical Quality (network-runtime-boundary): pass, run 25836811126, job 75913574440.
  • check-prod-types: pass, run 25836811135, job 75913583393.
  • check-test-types: pass, run 25836811135, job 75913583395.
  • check-lint: pass, run 25836811135, job 75913583389.
  • build-artifacts: pass, run 25836811135, job 75913583296.

Known proof gap / unrelated red check: checks-fast-contracts-plugins-d failed in run 25836811135, job 75913583348, at src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts:661 because codex-mcp-projection and codex-native-task-runtime are undocumented plugin-owned SDK subpaths. PR #79550 does not touch plugin SDK docs/contracts or those subpaths; the PR diff is limited to sessions/runtime metadata plus changelog/test files.

No live ACP provider/harness turn with external credentials was run after the maintainer rebase fix; the proof is seeded session-store CLI behavior plus focused regression/type/format checks.

@galiniliev
galiniliev merged commit 983064f into openclaw:main May 14, 2026
118 of 120 checks passed
@galiniliev
galiniliev self-requested a review May 14, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling commands Command implementations gateway Gateway runtime proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants