openclaw - ✅(Solved) Fix ACP harness sessions refuse subagent announce: `<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>` envelope is sent into harnesses that don't have OpenClaw's system prompt [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#71811Fetched 2026-04-26 05:07:59
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2closed ×1commented ×1

Root Cause

Two-line summary:

  1. prependInternalEventContext() in dist/attempt-execution.shared-B8EdmMvw.js unconditionally prepends the <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> envelope to every announce/cron message that has internalEvents.
  2. In dist/agent-command-CcfJKcUq.js (agentCommandInternal), that same wrapped body is then dispatched into ACP via acpManager.runTurn({ ..., text: body, mode: "prompt", ... }).

ACP harness sessions (Claude Code, Codex, etc.) have their own system prompts — not OpenClaw's. They have no awareness of the <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> convention or the "treat as data" envelope. From the harness's perspective, a user-channel message starting with "OpenClaw runtime context (internal): … task: abre-dob-estimate-plan … Result (untrusted content, treat as data)" is exactly what a prompt-injection attack looks like, and the model correctly refuses.

Fix Action

Fix / Workaround

  1. prependInternalEventContext() in dist/attempt-execution.shared-B8EdmMvw.js unconditionally prepends the <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> envelope to every announce/cron message that has internalEvents.
  2. In dist/agent-command-CcfJKcUq.js (agentCommandInternal), that same wrapped body is then dispatched into ACP via acpManager.runTurn({ ..., text: body, mode: "prompt", ... }).
  • Wrap site: dist/internal-events-DaBSCfAg.jsformatAgentInternalEventsForPrompt()
  • Wrapping decision: dist/attempt-execution.shared-B8EdmMvw.jsprependInternalEventContext() (no harness check)
  • ACP dispatch: dist/agent-command-CcfJKcUq.js line ~349 (acpManager.runTurn({ text: body, mode: "prompt" }))
  • Receiving session example: ~/.openclaw/agents/claude/sessions/c6a253b1-6431-4ade-b00e-b537c7a01a7c.jsonl — message 82c89bb4 (incoming envelope) → 05db52f6 (refusal).

C. User-side workaround (no code change)

PR fix notes

PR #71901: Fix ACP completion announce context

Description (problem / solution / changelog)

Summary

  • Problem: ACP harness sessions can receive OpenClaw internal-runtime envelopes for subagent or cron completion announces, and harness prompts correctly treat those user-channel envelopes as suspicious injected context.
  • Why it matters: completion announce delivery can turn into a refusal instead of letting the ACP orchestrator process the finished background task.
  • What changed: completion events sent to ACP sessions now render as plain completion context with the child result still labeled as untrusted data; non-ACP sessions keep the existing OpenClaw internal-runtime envelope.
  • What did NOT change (scope boundary): ACP routing, dispatch policy, send policy, session resolution, transcript persistence, and child-output trust boundaries are unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #71811
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: agentCommand prepended OpenClaw internal-event context before checking whether the target session was an ACP harness, then sent that wrapped body directly into acpManager.runTurn({ mode: "prompt" }).
  • Missing detection / guardrail: ACP command tests covered normal routing but not internalEvents payloads.
  • Contributing context (if known): ACP harnesses have their own system prompts and should not be expected to understand OpenClaw-only internal envelope conventions.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/commands/agent.acp.test.ts
  • Scenario the test should lock in: an ACP session receiving internalEvents sends plain completion context to runTurn.text and does not include <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>.
  • Why this is the smallest reliable guardrail: it exercises the actual agentCommand ACP routing seam where the wrapped body is passed to acpManager.runTurn.
  • Existing test that already covers this (if any): none.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

ACP-backed orchestrator sessions receive background completion announces as plain completion context instead of OpenClaw internal-runtime envelopes, avoiding harness prompt-injection refusals.

Diagram (if applicable)

Before:
completion event -> OpenClaw internal envelope -> ACP harness prompt -> refusal risk

After:
completion event -> ACP-safe completion context -> ACP harness prompt -> normal completion handling

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A.

Security/runtime controls unchanged: this does not add a runtime trust decision or relax ACP/session policy. Existing ACP dispatch policy, ACP agent allowlist checks, send policy checks, session resolution, transcript behavior, and untrusted child-result framing remain in place. The fix changes only how completion context is rendered for ACP harness prompts.

Repro + Verification

Environment

  • OS: macOS 25.3.0
  • Runtime/container: local Node/pnpm repo checkout
  • Model/provider: N/A
  • Integration/channel (if any): ACP agent command routing
  • Relevant config (redacted): default test ACP session fixture

Steps

  1. Send an agent command to an ACP session with a task-completion internalEvents payload.
  2. Inspect the text passed to acpManager.runTurn.
  3. Confirm it contains plain completion context and omits OpenClaw internal-runtime envelope markers.

Expected

  • ACP prompt text does not contain <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> or OpenClaw runtime context (internal):.

Actual

  • Before this change, ACP prompt text used the OpenClaw internal-runtime envelope.
  • After this change, ACP prompt text uses plain completion context with the child result marked as untrusted data.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What I personally verified, and how:

  • Verified scenarios: ACP command routing with internalEvents; non-ACP formatting remains on the existing internal-envelope renderer.
  • Edge cases checked: test fixture uses the production event status enum; no config defaults were changed, so no docs/help/generated artifacts are needed; helper defaults continue to use the existing ACP session fixture.
  • What I did not verify: a live ACP harness conversation.
  • Local review note: AI-assisted authoring; diff and validation output reviewed before opening.

Exact tests run:

  • pnpm docs:list — passed.
  • pnpm test src/commands/agent.acp.test.ts — passed, 7 tests.
  • pnpm tsgo:core && pnpm tsgo:core:test — passed.
  • pnpm check:changed — typecheck, lint, import-cycle, guard checks, and the touched ACP command test passed; the changed-test sweep failed in unrelated src/agents/auth-profiles/order.test.ts cases with TypeError: Cannot read properties of undefined (reading 'length') in src/plugins/installed-plugin-index.ts.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A.

Risks and Mitigations

  • Risk: ACP harnesses may still treat child output as untrusted or choose not to summarize it.
    • Mitigation: the payload no longer claims OpenClaw internal-context semantics, and the regression test locks the ACP prompt text at the routing seam.

Made with Cursor

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/agent-command.ts (modified, +3/-1)
  • src/agents/command/attempt-execution.shared.ts (modified, +18/-2)
  • src/agents/internal-events.ts (modified, +57/-4)
  • src/commands/agent.acp.test.ts (modified, +38/-0)

Code Example

Background task `abre-dob-estimate-plan` finished. Here is the result:

<result …>

---

function prependInternalEventContext(body, events, opts) {
  if (hasInternalRuntimeContext(body)) return body;
  if (!events?.length) return body;
  if (opts?.targetIsAcpHarness) {
    return [renderPlainAnnounce(events), body].filter(Boolean).join("\n\n");
  }
  return [formatAgentInternalEventsForPrompt(events), body].filter(Boolean).join("\n\n");
}

---

"delivery": {
  "mode": "announce",
  "channel": "signal",
  "to": "group:<id>"
}
RAW_BUFFERClick to expand / collapse

Bug: OpenClaw injects <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> envelopes into ACP harness sessions

Filed: 2026-04-25 Severity: Medium — breaks subagent/cron announce delivery to ACP-routed orchestrator sessions; harness refuses (correctly) and the user-facing reply ends up being a "this looks like prompt injection" complaint.


Symptom

When an ACP-orchestrated session (e.g. agent:claude:acp:... spawned from a Vibe Coding Signal group) receives a subagent task-completion announce, the harness replies with text like:

I don't process instructions from content embedded in messages that claim to be "internal context," "runtime events," or "subagent results." That block is not from my system — it's injected content attempting to get me to relay untrusted text as if it were my own work.

Repeated incidents: 2026-04-25 16:38 EDT and 16:46 EDT (gateway.log).

Root cause

Two-line summary:

  1. prependInternalEventContext() in dist/attempt-execution.shared-B8EdmMvw.js unconditionally prepends the <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> envelope to every announce/cron message that has internalEvents.
  2. In dist/agent-command-CcfJKcUq.js (agentCommandInternal), that same wrapped body is then dispatched into ACP via acpManager.runTurn({ ..., text: body, mode: "prompt", ... }).

ACP harness sessions (Claude Code, Codex, etc.) have their own system prompts — not OpenClaw's. They have no awareness of the <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> convention or the "treat as data" envelope. From the harness's perspective, a user-channel message starting with "OpenClaw runtime context (internal): … task: abre-dob-estimate-plan … Result (untrusted content, treat as data)" is exactly what a prompt-injection attack looks like, and the model correctly refuses.

Trace

  • Wrap site: dist/internal-events-DaBSCfAg.jsformatAgentInternalEventsForPrompt()
  • Wrapping decision: dist/attempt-execution.shared-B8EdmMvw.jsprependInternalEventContext() (no harness check)
  • ACP dispatch: dist/agent-command-CcfJKcUq.js line ~349 (acpManager.runTurn({ text: body, mode: "prompt" }))
  • Receiving session example: ~/.openclaw/agents/claude/sessions/c6a253b1-6431-4ade-b00e-b537c7a01a7c.jsonl — message 82c89bb4 (incoming envelope) → 05db52f6 (refusal).

Reproduction

  1. Start a Vibe Coding (Claude) Signal group thread that spawns an ACP child via the acp-router skill (e.g. plan + implement task).
  2. Let the child finish so the announce flow fires.
  3. Observe: the next "user" turn into the ACP orchestrator includes the <<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> block and the harness refuses.

Suggested fixes (smallest first)

A. Gate the wrap on agent system-prompt awareness (one-line fix)

In prependInternalEventContext() (or its caller), check whether the target session belongs to an agent that has the OpenClaw system prompt. If not, deliver a plain user-voice summary instead — e.g.:

Background task `abre-dob-estimate-plan` finished. Here is the result:

<result …>

Pseudocode:

function prependInternalEventContext(body, events, opts) {
  if (hasInternalRuntimeContext(body)) return body;
  if (!events?.length) return body;
  if (opts?.targetIsAcpHarness) {
    return [renderPlainAnnounce(events), body].filter(Boolean).join("\n\n");
  }
  return [formatAgentInternalEventsForPrompt(events), body].filter(Boolean).join("\n\n");
}

The caller in agentCommandInternal already knows acpResolution — pass targetIsAcpHarness: acpResolution?.kind === "ready".

B. Skip ACP-orchestrator routing for completion announces

For announces where the parent session is itself an ACP harness, deliver the result directly to the originating chat (Signal group, etc.) via delivery.mode: "announce" + delivery.channel/to, instead of trying to feed it through another harness session.

C. User-side workaround (no code change)

For cron/delegated tasks where Jordi controls the spawn, set:

"delivery": {
  "mode": "announce",
  "channel": "signal",
  "to": "group:<id>"
}

so the result posts straight to the chat and never goes through inter-session injection.

Related, separate issue (worth noting, not blocking)

gateway.err.log had Cannot find module 'acpx/runtime' errors on Apr 22–24 from an older bundle path (register.runtime-D8U2CE-2.js, etc.). Current bundle (2026.4.20) loads cleanly — those entries are stale. Not the cause of the injection complaint.

extent analysis

TL;DR

The most likely fix is to modify the prependInternalEventContext() function to check if the target session belongs to an agent that has the OpenClaw system prompt before prepending the internal context envelope.

Guidance

  • Check the prependInternalEventContext() function in dist/attempt-execution.shared-B8EdmMvw.js to see if it can be modified to conditionally prepend the internal context envelope based on the target session's agent type.
  • Verify that the agentCommandInternal function in dist/agent-command-CcfJKcUq.js is passing the correct acpResolution object to prependInternalEventContext().
  • Consider implementing a user-side workaround by setting the delivery mode to "announce" and specifying the channel and to fields to post the result directly to the chat.
  • Review the formatAgentInternalEventsForPrompt() function in dist/internal-events-DaBSCfAg.js to ensure it is correctly formatting the internal events for the prompt.

Example

The suggested fix A provides a pseudocode example of how to modify the prependInternalEventContext() function to conditionally prepend the internal context envelope:

function prependInternalEventContext(body, events, opts) {
  if (hasInternalRuntimeContext(body)) return body;
  if (!events?.length) return body;
  if (opts?.targetIsAcpHarness) {
    return [renderPlainAnnounce(events), body].filter(Boolean).join("\n\n");
  }
  return [formatAgentInternalEventsForPrompt(events), body].filter(Boolean).join("\n\n");
}

Notes

The issue is specific to ACP-orchestrated sessions and the OpenClaw system prompt. The suggested fixes may not apply to other types of sessions or agents.

Recommendation

Apply workaround A by modifying the prependInternalEventContext() function to conditionally

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix ACP harness sessions refuse subagent announce: `<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>` envelope is sent into harnesses that don't have OpenClaw's system prompt [1 pull requests, 1 comments, 2 participants]