Swarm workers on Moonshot AI hang forever before the request is built (PROVIDER_CANONICAL_INPUT never logged)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Bug: Moonshot AI swarm workers hang forever before the request is built (PROVIDER_CANONICAL_INPUT never logged)
Version: v0.64.2 (6c6fbba1c), macOS aarch64
Provider: moonshot-ai (openai-compatible:moonshotai, https://api.moonshot.ai/v1), API key auth
Summary
Spawning a swarm worker on any moonshotai: model produces an agent that never
returns. It stays Activity: busy indefinitely (observed >3 min, and one earlier
worker sat unfinished for ~17 min). The journal only ever contains the initial
user message; no assistant message is ever appended.
The same models work correctly through the CLI on the same machine, same key,
same daemon. So this is specific to the swarm spawn path, not the provider,
the credential, or the model.
The exact fault line
A working swarm spawn logs PROVIDER_CANONICAL_INPUT and API stream opened
about 2 ms after API call starting. The Moonshot swarm spawn logs
API call starting and then nothing, ever.
Working swarm spawn (ollama:glm-5.2:cloud, answered in ~5 s):
18:39:27.250 [ses:session_butterfly_17|prv:OpenRouter|mod:glm] API call starting: 2 messages, 30 tools
18:39:27.252 [ses:session_butterfly_17|prv:OpenRouter|mod:glm] PROVIDER_CANONICAL_INPUT: provider=openai-compatible model=glm-5.2:cloud
18:39:27.252 [ses:session_butterfly_17|prv:OpenRouter|mod:glm] OpenRouter transport: HTTPS (SSE)
18:39:27.252 [ses:session_butterfly_17|prv:OpenRouter|mod:glm] API stream opened in 0.00s
18:39:27.252 [ses:session_butterfly_17|prv:OpenRouter|mod:glm] EVENT event=AGENT_PROVIDER_STREAM_LIFECYCLE ...
18:39:29.930 [ses:session_butterfly_17|prv:OpenRouter|mod:glm] EVENT event=AGENT_PROVIDER_STREAM_LIFECYCLE connection_type=https/sse ...
Hung Moonshot swarm spawn (moonshotai:kimi-k3) — complete log for the session,
nothing follows the last line:
19:20:24.969 EVENT event=SWARM_LIFECYCLE ... new_status=running old_status=ready phase=member_started
19:20:24.969 [ses:session_crab_1785626|prv:OpenRouter|mod:kimi] Created macOS sleep-prevention assertion while streaming (id=42902)
19:20:24.969 [ses:session_crab_1785626|prv:OpenRouter|mod:kimi] TURN_CANCEL_REGISTERED ... active_turns=1
19:20:24.969 [ses:session_crab_1785626|prv:OpenRouter|mod:kimi] messages_for_provider (compaction): returning 2 messages (user=2, assistant=0)
19:20:24.969 [ses:session_crab_1785626|prv:OpenRouter|mod:kimi] Locking tool list at 30 tools for cache stability
19:20:24.970 [ses:session_crab_1785626|prv:OpenRouter|mod:kimi] Prompt prefix estimate: total=19950 tokens (system=6540 tools=13410)
19:20:24.970 [ses:session_crab_1785626|prv:OpenRouter|mod:kimi] API call starting: 2 messages, 30 tools
<no further lines for this session, ever>
Event counts for the two sessions:
| Session | API call starting |
PROVIDER_CANONICAL_INPUT |
API stream opened |
STREAM_LIFECYCLE |
|---|---|---|---|---|
butterfly (ollama, worked) |
1 | 1 | 1 | 2+ |
crab (moonshot, hung) |
1 | 0 | 0 | 0 |
So the worker wedges after the tool list is locked and the prompt is estimated,
but before the canonical provider request is emitted. No HTTP request appears to
be issued: lsof on the daemon showed no established connection to the Moonshot
Cloudflare range while a worker was hung.
Reproduction
swarm spawn label="repro" model="moonshotai:kimi-k3" prompt="Reply with exactly: REPRO. Then stop."
Worker stays busy forever. Same result for moonshotai:kimi-k2.7-code and
moonshotai:kimi-k2.6.
Interesting wrinkle: the very first Moonshot spawn of the session
(kimi-k2.7-code) succeeded and answered correctly in ~12 s. Every spawn after
that hung, including solo spawns with no other workers running, and including
kimi-k2.7-code again. That smells like one-shot state: a cached client,
connector, or semaphore for this provider that is initialised once and then not
reusable.
What I ruled out
- Not the credential. Direct
POST https://api.moonshot.ai/v1/chat/completions
with the same key returns 200 in ~1.9 s. - Not rate limiting or quota. Direct API calls to
kimi-k3and
kimi-k2.7-codesucceeded immediately, both before and after reproducing the
hang. No 429 anywhere in the logs. - Not payload size or tool schemas. Replaying the realistic agent payload
(30 function tools + ~20k-token system prompt,stream: true) directly against
the API returned 76 SSE chunks in 3.2 s. - Not the model.
jcode run -p moonshot-ai -m kimi-k3 '...'completes
normally, including a tool-calling prompt that reads a repo file and answers
correctly. Those CLI sessions logAGENT_PROVIDER_STREAM_LIFECYCLEas expected. - Not the daemon being wedged. An
ollama:glm-5.2:cloudworker spawned while
a Moonshot worker was hung answered correctly in ~5 s. - Not model-name casing. A working Ollama spawn and a hung Moonshot spawn both
renderprv:OpenRouterin the session tag, so that difference is cosmetic.
Impact
Any swarm work routed to moonshotai: silently stalls. There is no error, no
timeout, and no failed status. The coordinator just sees a worker that is
permanently busy, so a run_plan or await_members on it would wait forever.
A hard failure would be much better than this.
Possibly related
#512 (non-Claude-route spawns die at boot). That looks different: those died
at boot with journals stuck at 4 K and reported failed. These get further,
building the prompt and locking tools, then hang as running and never settle.
Filing separately, happy to have it merged if maintainers see one root cause.
Suggested follow-up
- A timeout on the swarm worker path between
API call startingand the first
stream event, so this settles asfailedrather than hanging forever. - Check whether
openai-compatibleprovider clients are cached per-provider in
the spawn path in a way that only works once (consistent with first-spawn-works,
all-later-spawns-hang).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the swarm spawn path and trace the provider flow from API call starting to PROVIDER_CANONICAL_INPUT, using the supplied Moonshot reproduction and logs. Compare a first spawn with subsequent spawns and verify that hung workers fail with a timeout instead of remaining busy, while later Moonshot workers can complete.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- ai, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100