openclaw - ✅(Solved) Fix [Bug]: session_spawn duplicates subagent task prompt in both system and user roles, doubling token cost [4 pull requests, 2 comments, 3 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#72019Fetched 2026-04-27 05:35:58
View on GitHub
Comments
2
Participants
3
Timeline
29
Reactions
0
Author
Timeline (top)
referenced ×21cross-referenced ×4commented ×2labeled ×2

When an orchestration agent spawns a subagent via session_spawn, the full subagent task prompt is sent twice in the API request — once embedded at the end of the system prompt and again as the entire user message — resulting in doubled input token consumption for every subagent invocation.


Root Cause

Because session_spawn is the standard mechanism for subagent creation, this issue affects all multi-agent workflows. Subagent task prompts can be long (thousands of tokens); doubling them on every spawn results in consistently inflated API billing with no functional benefit. Workflows that chain multiple subagents (e.g. build → audit → deploy) are disproportionately affected as the cost multiplier applies to each hop.

Fix Action

Fixed

PR fix notes

PR #72026: fix(agents): remove duplicated task text from subagent system prompt [AI-assisted]

Description (problem / solution / changelog)

🤖 AI-assisted (built with Claude Code via Hermes orchestration). Test level: fully tested. Prompt summary available on request.

Summary

  • Problem: session_spawn duplicates the subagent task prompt — once in the system message (buildSubagentSystemPrompt line 41: You were created to handle: ${taskText}) and again in the first user message (subagent-spawn.ts line 982: [Subagent Task]: ${task}).
  • Why it matters: Redundant task text wastes tokens and can confuse the model when it sees the same instruction in two roles with slightly different phrasing.
  • What changed: Removed the verbatim taskText variable and its interpolation from buildSubagentSystemPrompt. The system prompt now uses a generic reference (specific task (see first user message)) instead. Added 5 unit tests to lock this in.
  • What did NOT change (scope boundary): The user message [Subagent Task] in subagent-spawn.ts is untouched. The task parameter on buildSubagentSystemPrompt is kept for backward compatibility (callers still pass it; it is simply no longer embedded).

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Core agent system (src/agents/)

Linked Issue/PR

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

Root Cause

  • Root cause: When subagent spawning was implemented, the task description was added to both the system prompt (for context) and the user message (as the actual instruction). This duplication was never deduplicated.
  • Missing detection / guardrail: No test asserted that the task text should NOT appear in the system prompt.
  • Contributing context: The system prompt and user message construction live in separate files (subagent-system-prompt.ts vs subagent-spawn.ts), making the duplication easy to miss.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
  • Target test or file: src/agents/subagent-system-prompt.test.ts (new)
  • Scenario the test should lock in: buildSubagentSystemPrompt({task: "..."}) must NOT contain the task text verbatim in its output; must contain a generic pointer to the first user message instead.
  • Why this is the smallest reliable guardrail: Direct unit test on the prompt builder function — no runtime dependencies needed.
  • Existing test that already covers this: N/A (no prior test file for buildSubagentSystemPrompt)

User-visible / Behavior Changes

None — subagents still receive the task via the user message as before.

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? No
  • The task text is moved from system prompt to user-message-only. No new data exposure — the same task text was already in the user message. No security-sensitive paths touched.

Changed files

  • src/agents/subagent-system-prompt.test.ts (added, +46/-0)
  • src/agents/subagent-system-prompt.ts (modified, +2/-7)

PR #72028: fix(agents): avoid duplicating subagent task prompts

Description (problem / solution / changelog)

Summary

Fixes #72019.

  • Keep the concrete sessions_spawn task in the child user message only.
  • Replace the duplicated task text in the subagent system prompt with a stable reference to the first user message.
  • Add regressions that the system prompt omits the task while the child agent payload still receives it.

Validation

  • pnpm test src/agents/system-prompt.test.ts src/agents/subagent-spawn.test.ts
  • OPENCLAW_VITEST_MAX_WORKERS=1 pnpm check:changed

Note: plain pnpm check:changed hit ERR_WORKER_OUT_OF_MEMORY in the broad agents Vitest lane after 375/376 files passed; the serial-worker retry passed.

Changed files

  • src/agents/subagent-spawn.test.ts (modified, +34/-0)
  • src/agents/subagent-system-prompt.ts (modified, +1/-5)
  • src/agents/system-prompt.test.ts (modified, +16/-0)

PR #72053: fix(agents): dedupe subagent task in first user turn (#72019)

Description (problem / solution / changelog)

Summary

  • Problem: For native sessions_spawn / subagent runs, the long task string was present both in the subagent system prompt (under ## Your Role) and again in the first user turn as [Subagent Task]: ..., roughly doubling input tokens for that portion of the first request (#72019).
  • Why it matters: Subagent spawns are on the hot path; duplicate task text is pure overhead and can push large tasks over context limits faster.
  • What changed: New helper buildSubagentInitialUserMessage (src/agents/subagent-initial-user-message.ts) produces a short bootstrap user message that points the model to ## Your Role only. spawnSubagentDirect (src/agents/subagent-spawn.ts) uses it instead of inlining the full task in the first user turn.
  • Second commit (review follow-up): buildSubagentSystemPrompt no longer replaced all whitespace in task with a single line (which could mangle multiline/JSON/shell). Multiline task is shown verbatim inside a fenced block under ## Your Role; single-line tasks stay a single bullet (src/agents/subagent-system-prompt.ts).

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 #72019
  • Related: N/A
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: The spawn path built both the subagent system prompt and the first user message from the same task string.
  • Missing guardrail: No single source-of-truth for “long task in system, short kickoff in user” for the first turn.
  • Additional finding (after deduping the user turn): The system prompt had normalized task to one line, which is wrong for multiline/shell/JSON; fixed in the second commit.
  • Contributing context (if known): N/A

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/agents/subagent-initial-user-message.test.ts, src/agents/system-prompt.test.ts
  • Scenario the test should lock in: (1) First user text does not repeat the full task or [Subagent Task]:. (2) Multiline task appears with line breaks preserved in the system prompt (fenced + verbatim) after the buildSubagentSystemPrompt follow-up.
  • Why this is the smallest reliable guardrail: The bug is entirely prompt assembly; unit tests on the two builders catch regressions without needing a full gateway.
  • Existing test that already covers this (if any): N/A
  • If no new test is added, why not: N/A (new tests are included)

User-visible / Behavior Changes

  • Subagent runs: The first user turn is a short pointer to ## Your Role; the full task remains in the subagent system prompt, with verbatim handling for multiline task (see above).
  • No change to sessions_spawn routing, tool surface, or registry of subagent runs.

Diagram (if applicable)

N/A (prompt string assembly only)

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

Repro + Verification

Environment

  • N/A (unit-test verified)

Steps

  1. Run: pnpm test src/agents/subagent-initial-user-message.test.ts
  2. Run: pnpm test src/agents/system-prompt.test.ts

Expected

  • All tests pass.

Actual

  • All tests pass locally after the task narrowing fix for buildSubagentSystemPrompt (TypeScript / CI).

Evidence

  • Failing test/log before + passing after: CI previously failed with TS18048 in subagent-system-prompt.ts after the verbatim-task change; fixed by narrowing with taskRaw: string before trim().
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: Unit behavior for no duplicated task in first user turn; multiline task not collapsed to a single line in the system prompt.
  • Edge cases checked: multiline (new test); single-line (existing cases).
  • What you did not verify: Not measured token counts end-to-end in a live subagent run (out of scope for this PR; QC asked optional integration).

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 (first user text shape only; no protocol change)
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: A provider that ignored system content and only read the user turn might miss the task — Mitigation: the system prompt is unchanged in intent; the first user line explicitly points to ## Your Role where the full task lives, matching #72019 option (1).
  • Risk (addressed in follow-up commit): Losing newlines/indentation in task when the user turn no longer included a verbatim copy — Mitigation: buildSubagentSystemPrompt no longer flattens whitespace; multiline tasks use a fenced code block.

Changelog

  • Omitted in-branch to limit merge noise on CHANGELOG.md; can be added at land time if release policy requires a user-facing line for #72019.

Changed files

  • src/agents/subagent-initial-user-message.test.ts (added, +26/-0)
  • src/agents/subagent-initial-user-message.ts (added, +24/-0)
  • src/agents/subagent-spawn.ts (modified, +6/-9)
  • src/agents/subagent-system-prompt.ts (modified, +25/-9)
  • src/agents/system-prompt.test.ts (modified, +15/-0)

PR #72570: fix(agents): stop duplicating subagent task in system prompt to cut input token cost

Description (problem / solution / changelog)

Problem

Every session_spawn sends the subagent task prompt twice in the API request:

  • In role: system"- You were created to handle: <task>"
  • In role: user"[Subagent Task]: <task>"

This doubles input token cost on every subagent invocation. Reported in #72019 with reproduction via OpenRouter request logs.

Fix

The system prompt's role is to define the agent's standing instructions and context. The task itself belongs in the user turn (where it already appears via childTaskMessage). This PR changes the system prompt line to reference the first message instead of repeating the task text verbatim.

One-line change in src/agents/subagent-system-prompt.ts:

-    `- You were created to handle: ${taskText}`,
+    `- You were created to handle the task described in your first message.`,

62 existing system-prompt.test.ts tests pass unchanged.

Fixes #72019

Changed files

  • src/agents/subagent-system-prompt.ts (modified, +1/-1)

Code Example

[
  {
    "role": "system",
    "content": "...## Subagent Context\n# Subagent Context\n\nYou are a **subagent** spawned by the main agent for a specific task.\n\n## Your Role\n- You were created to handle: [TASK PROMPT]\n- Complete this task. That's your entire purpose.\n..."
  },
  {
    "role": "user",
    "content": "[Timestamp] [Subagent Context] You are running as a subagent (depth 1/1)...\n\n[Subagent Task]: [TASK PROMPT]"
  }
]
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When an orchestration agent spawns a subagent via session_spawn, the full subagent task prompt is sent twice in the API request — once embedded at the end of the system prompt and again as the entire user message — resulting in doubled input token consumption for every subagent invocation.


Steps to reproduce

  1. Configure an orchestration agent (main agent) with a subagent spawning workflow using session_spawn.
  2. Trigger the main agent to spawn a subagent with a substantial task prompt (e.g. a coding task).
  3. Inspect the raw API request sent to the upstream LLM provider (e.g. via OpenRouter request logs).
  4. Observe the system and user fields in the outgoing request.

Expected behavior

The subagent task prompt should appear exactly once in the API request. The correct behaviour should be one of:

  • The task prompt is embedded in the system prompt (as part of the subagent context block), and the user message contains only a minimal invocation or reference; or
  • The task prompt is sent exclusively as the user message, with the system prompt containing only standing instructions (role, rules, runtime info).

In either case, the content of the task prompt should not be duplicated across both fields.


Actual behavior

The full subagent task prompt text is transmitted twice:

  • In role: "system": The task prompt is appended verbatim inside the ## Subagent Context block, under the You were created to handle: field.
  • In role: "user": The identical task prompt is sent again as the sole content of the first user message.

This was reproduced consistently across two independent subagent invocations (different subagents, different tasks) within the same session, indicating the duplication is structural and not task-specific.


OpenClaw version

2026.4.23

Operating system

Ubuntu 24.04.4 LTS

Install method

curl -fsSL https://openclaw.ai/install.sh | bash

Model

Main Agent: openrouter/anthropic/claude-sonnet-4.6 Subagent1: openrouter/xiaomi/mimo-v2.5-pro Subagent2: openrouter/google/gemini-3.1-pro-preview-customtools

Provider / routing chain

OpenClaw -> OpenRouter -> model

Additional provider/model setup details

No response


Logs, screenshots, and evidence

Source: OpenRouter request log (raw API payload), captured during a live session_spawn invocation.

Redacted excerpt (task prompt body truncated to [TASK PROMPT] for brevity; the same text appeared in full in both locations in the original log):

[
  {
    "role": "system",
    "content": "...## Subagent Context\n# Subagent Context\n\nYou are a **subagent** spawned by the main agent for a specific task.\n\n## Your Role\n- You were created to handle: [TASK PROMPT]\n- Complete this task. That's your entire purpose.\n..."
  },
  {
    "role": "user",
    "content": "[Timestamp] [Subagent Context] You are running as a subagent (depth 1/1)...\n\n[Subagent Task]: [TASK PROMPT]"
  }
]

Observations from the log:

  • The system message contains the full task prompt under You were created to handle:.
  • The user message contains the full task prompt again under [Subagent Task]:.
  • Reproduced on two separate session_spawn calls within the same orchestration run (different subagents, different task prompts, same structural duplication).
  • Runtime metadata in the system prompt confirms the session used openrouter as the provider and node=v24.14.1.

Impact and severity

  • Affected users/systems: Any user using session_spawn for multi-agent orchestration.
  • Severity: Blocks cost-efficient use; direct financial impact on every spawn.
  • Frequency: Always — reproduced on every observed session_spawn call.
  • Consequence: Doubled input token cost per subagent spawn; inflated billing on every multi-agent workflow.

Because session_spawn is the standard mechanism for subagent creation, this issue affects all multi-agent workflows. Subagent task prompts can be long (thousands of tokens); doubling them on every spawn results in consistently inflated API billing with no functional benefit. Workflows that chain multiple subagents (e.g. build → audit → deploy) are disproportionately affected as the cost multiplier applies to each hop.


Additional information

Reproduction context:

  • Observed via OpenRouter request logs (provider used for multi-model access).
  • Runtime: node=v24.14.1, os=Linux 6.8.0-110-generic (x64), host=openclaw, shell=bash, channel=webchat.
  • Subagent depth: 1/1 (direct child of main agent).
  • Model at time of observation: openrouter/xiaomi/mimo-v2.5-pro:floor (via OpenRouter).

Not a regression note: No prior known-good version observed as I am new to this — this may be a long-standing structural issue rather than a regression.

Suggested investigation area: The prompt construction logic in session_spawn — specifically where the subagent context block is assembled for the system role and where the first user turn is generated. It is likely that the task string is being written to both locations without a guard to prevent duplication.

extent analysis

TL;DR

The most likely fix involves modifying the prompt construction logic in session_spawn to prevent duplicating the subagent task prompt in both the system and user messages.

Guidance

  • Review the session_spawn function to identify where the subagent context block for the system role and the first user turn are generated.
  • Implement a check to ensure the subagent task prompt is only included once in the API request, either in the system prompt or as the user message, but not both.
  • Verify the fix by inspecting the raw API request sent to the upstream LLM provider after applying the changes.
  • Test the modified session_spawn function with different subagent invocations to confirm the task prompt is no longer duplicated.

Example

// Before fix
{
  "role": "system",
  "content": "...## Subagent Context\nYou were created to handle: [TASK PROMPT]..."
},
{
  "role": "user",
  "content": "[TASK PROMPT]"
}

// After fix (example with task prompt in system message)
{
  "role": "system",
  "content": "...## Subagent Context\nYou were created to handle: [TASK PROMPT]..."
},
{
  "role": "user",
  "content": ""
}

Notes

The provided logs and observations suggest the issue is structural and not task-specific, indicating a fix in the session_spawn logic should resolve the problem across different subagent invocations.

Recommendation

Apply a workaround by modifying the session_spawn function to prevent task prompt duplication, as this directly addresses the identified issue and should mitigate the inflated API billing caused by the current behavior.

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…

FAQ

Expected behavior

The subagent task prompt should appear exactly once in the API request. The correct behaviour should be one of:

  • The task prompt is embedded in the system prompt (as part of the subagent context block), and the user message contains only a minimal invocation or reference; or
  • The task prompt is sent exclusively as the user message, with the system prompt containing only standing instructions (role, rules, runtime info).

In either case, the content of the task prompt should not be duplicated across both fields.


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 [Bug]: session_spawn duplicates subagent task prompt in both system and user roles, doubling token cost [4 pull requests, 2 comments, 3 participants]