Skip to content

Swarm spawn drops prompt when initial_message is an empty string #975

Description

@joachimBrindeau

Summary

A swarm spawn payload that contains a valid prompt but also contains initial_message: "" silently discards the prompt. The worker is created without its task and may spend a long time reasoning before asking the coordinator what it was supposed to do.

I initially encountered this while testing a local Qwen model through vLLM and CLIProxyAPI/CloudCLIProxy. I suspected the model or proxy configuration first. After tracing the recorded spawn payload and Jcode's source, the missing initial task is reproducible entirely inside Jcode before the provider request is built.

This report is intentionally limited to prompt selection. It does not claim that the proxy/model's tool-calling configuration is otherwise perfect. There may still be independent provider issues, but they cannot explain this particular empty startup message.

Environment

  • Installed Jcode: v0.76.0 (bbef1f6a8)
  • Current upstream checked at: c4cdc67680e30a957dc86c68c955ea0605a316f3
  • macOS
  • Spawn mode observed: inline/headless worker
  • Provider in the original observation: custom OpenAI-compatible CLIProxyAPI route to vLLM/Qwen

Reproduction

Send a spawn call with both fields, where initial_message is present but blank:

{
  "action": "spawn",
  "label": "local html executor",
  "model": "cliproxyapi:local",
  "prompt": "Create /Users/example/Desktop/page/index.html, then report completion.",
  "initial_message": ""
}

This shape can occur when a caller/tool serializer emits optional string fields as empty strings while using the documented prompt field for the actual task.

Minimal unit-level reproduction

let input: CommunicateInput = serde_json::from_value(serde_json::json!({
    "action": "spawn",
    "initial_message": "",
    "prompt": "preserve this task"
}))?;

assert_eq!(input.spawn_initial_message().as_deref(), Some("preserve this task"));

The assertion currently fails because the result is Some("").

Root cause

Current upstream code in crates/jcode-app-core/src/tool/communicate.rs:

fn spawn_initial_message(&self) -> Option<String> {
    self.initial_message.clone().or_else(|| self.prompt.clone())
}

Option::or_else only falls back for None. Some("") is still Some, so the non-empty prompt is never considered. spawn_swarm_agent then receives the blank value and uses it as the startup message.

In the observed sessions, the recorded tool call visibly contained the full task in prompt and initial_message: "". Two fresh workers subsequently contacted the coordinator with variants of:

What's my task? I was spawned as "local html executor" but I don't have the task prompt or details.

This aligns exactly with the source behavior.

Expected behavior

Blank or whitespace-only aliases should be treated as absent:

  1. Prefer a nonblank initial_message.
  2. Otherwise use a nonblank prompt.
  3. Otherwise return None.

Suggested fix

fn spawn_initial_message(&self) -> Option<String> {
    self.initial_message
        .as_ref()
        .filter(|message| !message.trim().is_empty())
        .cloned()
        .or_else(|| {
            self.prompt
                .as_ref()
                .filter(|prompt| !prompt.trim().is_empty())
                .cloned()
        })
}

I applied this locally and added a regression case to communicate_tests/input_format.rs. The targeted test passes:

running 1 test
test tool::communicate::tests::spawn_initial_message_accepts_prompt_alias_and_prefers_explicit_initial_message ... ok

test result: ok. 1 passed; 0 failed

Impact

  • Spawned workers can lose their entire assignment while still receiving a valid label.
  • The symptom can be misdiagnosed as model context loss, bad chat templates, or proxy/provider incompatibility.
  • Reasoning models may consume substantial tokens while trying to recover the missing task.
  • Follow-up DMs do not necessarily rescue a worker already stuck in a long generation.

Duplicate check

I searched open and closed issues for initial_message, swarm prompt, spawn prompt lost task, and related wording and did not find an existing report for this behavior.

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