Skip to content

[Bug]: ACP child run completes, but parent relay receives no progress or completion events #45205

@fatalist

Description

@fatalist

Bug type

Regression (worked before, now fails)

Summary

Observed version: OpenClaw 2026.3.12 (6472949)

One-line summary

When spawning an ACP child agent, the child session runs and writes assistant output, but the parent session only receives synthetic start and stall system events and never receives assistant deltas or lifecycle completion.

Expected

After ACP spawn:

  • parent session should receive assistant progress updates from child
  • parent session should receive lifecycle end/error
  • orchestration logic should be able to observe child progress and completion

Actual

Parent session receives only:

  • Started claude session ... Streaming progress updates to parent session.
  • claude has produced no output for 60s. It may be waiting for interactive input.

But the child transcript contains real assistant responses and file changes.

Concrete evidence from this installation

Parent session key:

agent:main:telegram:direct:377231761

Example child session key:

agent:claude:acp:4db51d29-1722-4000-8c0a-67446bc6a277

Child stream log contains only start + stall:

  • agents/claude/sessions/1a01588e-80c6-4276-8923-9236a1f0b4f2.acp-stream.jsonl

Child transcript contains real assistant messages:

  • agents/claude/sessions/1a01588e-80c6-4276-8923-9236a1f0b4f2.jsonl

Another reproducible child shows the same pattern:

  • stream log: agents/claude/sessions/9d2e728b-545f-44b8-a235-656f9ee731f5.acp-stream.jsonl
  • transcript: agents/claude/sessions/9d2e728b-545f-44b8-a235-656f9ee731f5.jsonl

Example mismatch from one affected run:

stream_relay:
  system_event=2 assistant_delta=0 lifecycle=0
  last_text=claude has produced no output for 60s. It may be waiting for interactive input.

child_transcript:
  user_messages=2
  assistant_messages=2

Why this looks like an OpenClaw bug, not a user config bug

Relevant config is already present:

  • openclaw.json

Specifically:

  • acp.enabled = true
  • acp.dispatch.enabled = true
  • acp.backend = "acpx"
  • acp.stream.deliveryMode = "live"
  • tools.sessions.visibility = "all"

The child session manager also records the ACP sessions as valid and later idle, which suggests the child run is not crashing:

  • agents/claude/sessions/sessions.json

Suspected root cause

The parent relay appears to subscribe only to local onAgentEvent(...) events.

Relevant built code:

  • relay listens for assistant / lifecycle in dist/reply-BEN3KNDZ.js around startAcpSpawnParentStreamRelay(...)
  • ACP spawn uses callGateway({ method: "agent" ... }) in the same built file around the ACP spawn path

This suggests a cross-process bridge problem:

  • child work runs behind gateway/ACP runtime
  • relay listens in parent process
  • assistant/lifecycle events do not come back to that relay

Suggested fix directions

Any of these would likely solve it:

  1. Bridge ACP child assistant and lifecycle events back through gateway to the parent relay.
  2. Make the relay read the child transcript/session stream directly instead of relying on in-process emitter only.
  3. Subscribe the parent to a gateway-backed event stream/WebSocket for the child run.

Minimal reproduction

  1. Configure ACP with backend acpx and parent streaming enabled.
  2. Spawn a Claude ACP child from main session.
  3. Give a task that produces visible assistant output quickly.
  4. Observe:
    • parent receives start
    • after 60s parent receives stall
    • child transcript already contains assistant replies
    • child may have modified files successfully

Extra note

openclaw agents list currently shows agent claude with displayed model openai-codex/gpt-5.4. That may be a separate display/model-resolution inconsistency, but it does not explain the missing parent relay events.

Redactions

  • Local absolute filesystem paths are omitted on purpose.
  • All referenced files above are relative to the OpenClaw data directory / workspace on the affected machine.

Steps to reproduce

  1. Install and enable ACP with backend acpx.
  2. Configure OpenClaw with:
    • acp.enabled = true
    • acp.dispatch.enabled = true
    • acp.backend = "acpx"
    • acp.stream.deliveryMode = "live"
  3. Start a fresh main session in Telegram.
  4. From that main session, trigger delegation to Claude through ACP, not subagent.
  5. Use a task that should produce visible progress or a quick textual reply, for example:
Reply with exactly LIVE-ACP-STREAM-OK

or a short coding task that clearly edits files and writes a short summary.

  1. Ensure the ACP spawn is created with parent streaming enabled.
  2. Wait for the parent session to receive events.
  3. Observe:
    • parent receives Started claude session ... Streaming progress updates to parent session.
    • after about 60 seconds parent receives claude has produced no output for 60s. It may be waiting for interactive input.
    • but the child transcript already contains assistant replies
    • and in coding tasks the child may already have modified files successfully

Expected behavior

  • Parent session receives assistant deltas/progress from the child.
  • Parent session receives lifecycle completion.
  • Main agent can reliably orchestrate the child from Telegram.

Actual behavior

  • Parent session receives only synthetic start and stall.
  • No assistant deltas are relayed to the parent.
  • No lifecycle completion is relayed to the parent.
  • Child session itself does run and produce output.

OpenClaw version

OpenClaw 2026.3.12 (6472949)

Operating system

Debian 13

Install method

npm global

Model

anthropic/opus_4.6

Provider / routing chain

openrouter

Config file / key location

~/.openclaw/openclaw.json

Additional provider/model setup details

"agents": {
    "defaults": {
      "model": {
        "primary": "openai-codex/gpt-5.4"
      },
      "models": {
        "openrouter/auto": {
          "alias": "OpenRouter"
        },
        "openrouter/anthropic/claude-sonnet-4.6": {
          "alias": "sonnet"
        },
        "openrouter/google/gemini-3.1-flash-lite-preview": {
          "alias": "gemini"
        },
        "openrouter/moonshotai/kimi-k2.5": {
          "alias": "kimi"
        },
        "openrouter/anthropic/claude-haiku-4.5": {
          "alias": "haiku"
        },
        "openrouter/openai/gpt-5.1-codex-mini": {
          "alias": "codex-mini"
        },
        "openrouter/openai/gpt-5.1-codex-max:nitro": {
          "alias": "codex-max"
        },
        "openai-codex/gpt-5.4": {
          "alias": "openai-codex-gpt"
        }
      },
      "workspace": "/home/paul/.openclaw/workspace",
      "timeFormat": "24",
      "memorySearch": {
        "provider": "openai",
        "remote": {
          "baseUrl": "https://openrouter.ai/api/v1/",
          "apiKey": "${OPENROUTER_KEY}"
        },
        "fallback": "none",
        "model": "openai/text-embedding-3-small",
        "sync": {
          "watch": true
        },
        "query": {
          "hybrid": {
            "enabled": true,
            "vectorWeight": 0.7,
            "textWeight": 0.3,
            "candidateMultiplier": 4,
            "mmr": {
              "enabled": true,
              "lambda": 0.7
            },
            "temporalDecay": {
              "enabled": true,
              "halfLifeDays": 30
            }
          }
        },
        "cache": {
          "enabled": true,
          "maxEntries": 50000
        }
      },
      "compaction": {
        "mode": "safeguard",
        "reserveTokensFloor": 40000,
        "memoryFlush": {
          "enabled": true,
          "softThresholdTokens": 4000,
          "prompt": "Write lasting notes to memory/YYYY-MM-DD.md. Reply NO_REPLY if nothing to store.",
          "systemPrompt": "Session nearing compaction. Store durable memories now."
        }
      },
      "thinkingDefault": "medium",
      "heartbeat": {
        "every": "1h",
        "includeReasoning": false
      },
      "maxConcurrent": 4,
      "subagents": {
        "maxConcurrent": 8,
        "maxSpawnDepth": 1,
        "maxChildrenPerAgent": 5,
        "runTimeoutSeconds": 900
      }
    },
    "list": [
      {
        "id": "main",
        "default": true,
        "subagents": {
          "allowAgents": [
            "claude"
          ]
        },
        "tools": {
          "profile": "full"
        }
      },
      {
        "id": "claude",
        "tools": {
          "profile": "full"
        },
        "runtime": {
          "type": "acp",
          "acp": {
            "agent": "claude",
            "backend": "acpx",
            "mode": "persistent"
          }
        }
      }
    ]
  }

"session": {
    "dmScope": "per-channel-peer",
    "maintenance": {
      "mode": "enforce",
      "pruneAfter": "14d",
      "maxEntries": 2000,
      "rotateBytes": "25mb",
      "maxDiskBytes": "1gb",
      "highWaterBytes": "800mb"
    }
  }
"plugins": {
    "allow": [
      "acpx",
      "telegram"
    ],
    "load": {
      "paths": [
        "/home/paul/.npm-global/lib/node_modules/openclaw/extensions/acpx"
      ]
    },
    "entries": {
      "telegram": {
        "enabled": true
      },
      "acpx": {
        "enabled": true,
        "config": {
          "permissionMode": "approve-all",
          "nonInteractivePermissions": "deny"
        }
      }
    },
    "installs": {
      "acpx": {
        "source": "path",
        "spec": "acpx",
        "sourcePath": "/home/paul/.npm-global/lib/node_modules/openclaw/extensions/acpx",
        "installPath": "/home/paul/.npm-global/lib/node_modules/openclaw/extensions/acpx",
        "installedAt": "2026-03-08T20:22:52.968Z"
      }
    }
  }

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingregressionBehavior that previously worked and now fails

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions