Skip to content

fix(agent-core-v2): emit subagent.failed when background task registration fails - #2749

Open
tarikermis wants to merge 2 commits into
MoonshotAI:mainfrom
tarikermis:fix/subagent-registration-failed-event
Open

fix(agent-core-v2): emit subagent.failed when background task registration fails#2749
tarikermis wants to merge 2 commits into
MoonshotAI:mainfrom
tarikermis:fix/subagent-registration-failed-event

Conversation

@tarikermis

Copy link
Copy Markdown

Related Issue

Resolve #2673

Problem

On the default agent-core-v2 engine, a background subagent rejected by the running-task limit leaves a permanent ghost "running" entry in task panels: the entry's runtime keeps growing, Stop fails with task agent-N does not exist in session ..., and the entry never self-heals (the agent-facing TaskList correctly shows 0 active tasks).

Root cause: the Agent tool announces the launch through subagent.spawned (with runInBackground: true) and subagent.started before registering the background task. When registration hits the limit, the tool aborts the run and returns the Too many background tasks are already running. tool error, but the abort surfaces in mirrorAgentRun as an abort error — which deliberately never publishes subagent.failed. Clients that tracked the run from spawned/started therefore wait forever for a terminal event that never comes, while the engine-side task service never created the task (hence "does not exist" on stop). The legacy v1 engine self-heals here because its spawn pipeline emits subagent.failed even for aborts; v2 does not.

What changed

  • agentTool.ts: in the background-registration failure catch, publish subagent.failed for the spawned agent (same message the tool returns), so an announced run always reaches a terminal signal. The emitted error text and the tool output now share one registrationFailureMessage helper, so they cannot drift.
  • mirrorAgentRun.ts: extracted the existing inline subagent.failed publish into an exported emitAgentRunFailed helper (same captured event bus, identical behavior) that the tool reuses.
  • Regression coverage: extended the existing task-limit test in test/tool/tool.test.ts to assert subagent.spawned precedes exactly one subagent.failed for the rejected agent, with the limit message.
  • Changeset included (@moonshot-ai/kimi-code, patch — internal engine fix with user-visible panel behavior).

Deliberately narrow: user-cancellation aborts must keep not emitting subagent.failed (clients render those as cancellations), so the fix lives at the registration-failure site rather than in mirrorAgentRun's generic abort suppression. A theoretical race (the child failing with a real error in the same instant as the abort) could yield a second subagent.failed; both are terminal "failed" signals and the TUI/web handlers are idempotent, so this is benign.

Verification

  • Reproduced on main first: the extended test failed with the event stream containing only subagent.spawned + subagent.started for the rejected agent — matching the issue's ghost-entry symptom.
  • npx vitest run --project agent-core-v2: 310 files, 4890 passed / 1 skipped.
  • tsc -p tsconfig.json --noEmit (agent-core-v2): clean. oxlint on changed files: 0 errors (1 pre-existing duplicate-import warning in mirrorAgentRun.ts that already exists on main).
  • Independent read-only diff review, two rounds; findings addressed (unified event/output message, exactly-once + ordering assertions, captured-bus reuse in mirrorAgentRun).

Testing limitation, honestly noted: the reporter's panel was the web UI, whose source lives outside this repo, so the end-to-end panel behavior is verified at the engine event-contract level (subagent.spawned now always pairs with a terminal event) plus the TUI's equivalent background-agent badge path, not by clicking through the web panel.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

…ation fails

The Agent tool announces a background subagent through subagent.spawned
before registering it as a background task. When registration hit the
running-task limit, the tool aborted the run and returned the limit
error, but the abort surfaced in mirrorAgentRun as an abort error —
which deliberately never publishes subagent.failed — so clients that
tracked the run from spawned/started (task panels, the TUI background
agent badge) kept the rejected launch as a ghost running entry that
could never be stopped (the engine never created the task).

Publish subagent.failed from the registration-failure path so the
spawned run always reaches a terminal signal, via a shared
emitAgentRunFailed helper now also used by mirrorAgentRun.
@changeset-bot

changeset-bot Bot commented Aug 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6b222ab

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b222abf88

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1752 to +1754
// The spawn was already announced, so clients tracking the run (task
// panels, the TUI background-agent badge) need a terminal signal —
// without one the rejected launch lingers as a ghost "running" entry.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Move the inline explanation to the file header

Remove this new statement-level explanatory comment or incorporate the scenario into the test name and the file’s top-of-file header; this package explicitly prohibits comments beside statements and permits them only in the top-of-file /** */ block.

AGENTS.md reference: packages/agent-core-v2/AGENTS.md:L36-L40

Useful? React with 👍 / 👎.

The package convention keeps comments solely in the top-of-file header
block; the assertion sequence is self-explanatory without it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: 因后台任务上限被拒绝启动的子 Agent 在任务面板显示为永久「运行中」且无法停止

1 participant