Repository navigation
fix(agents): start returns skills_injection/skills_result — skill-delivery failures reach REST and MCP callers (#2991) - #3008
Merged
Conversation
…ivery failures reach REST and MCP callers (#2991) `start_agent_internal` computed the skill-delivery result, and `POST /api/agents/{name}/start` rebuilt its response from a whitelist that left it out, so a caller could not tell a clean start from one whose assigned skill failed or hit a name conflict. - The endpoint returns `skills_injection` + `skills_result` beside the credentials pair. `skills_result` is a projection (`public_skills_result`): names, statuses and codes only — a per-skill error that carries an exception string, URL or path is reduced to a code (ent#334). A no-op start answers `skipped` + reason; a missing result reads `unknown`, never absent. - A conflict keeps `success` (#2914), so `inject_assigned_skills` now names it in `conflicts` — distinguishable from a clean start in one response. - MCP `start_agent` keeps its first line and, when delivery was not clean, adds the status and one line per skill that did not land. - Same gap closed on `POST /api/system-agent/restart`; the fleet restart entry gains `skills_conflicts`. The projection is shape-defensive: it runs inside the start's try, so a raise would turn a start that happened into a 500. Mutations: whitelist reverted (6 red), raw result passed through (5 red), lifecycle drops conflicts (1 red), MCP returns only the message (2 red). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…result # Conflicts: # tests/registry.json
…result # Conflicts: # tests/registry.json
…result # Conflicts: # tests/registry.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2991
Problem
start_agent_internalcomputed the skill-delivery result, butPOST /api/agents/{name}/startrebuilds its response from a whitelist that left it out. So a REST or MCP caller could not tell a clean start from one where an assigned skill failed to land or hit a nameconflict.Fix
skills_injectionandskills_resultare returned beside the credentials pair they mirror.skills_resultis a projection built bypublic_skills_result, with names, statuses and codes only (the ent#334 rule).skill_too_large,not_in_library,name_conflict, or elseerror. The only warnings passed through aremissing_env:/missing_binary:names; the rest are dropped.skippedwith its reason (no_skills,container_already_running). A missing result readsunknown; the field is never absent (AC4).successfor a conflict, because the agent's own copy runs.inject_assigned_skillsnow lists it inconflicts, so the case is distinguishable in one response. The status vocabulary is unchanged, as agreed.start_agent(AC2): the first line is unchanged. When delivery wasn't clean, it addsSkills delivery: <status>and one line per skill that didn't land, e.g.- backlog: conflict (name_conflict). A clean or no-op start adds nothing, and an unknown result is never presented as clean.POST /api/system-agent/restartreturns the same pair.skills_conflicts.try, so a raise would turn a start that happened into a 500 the caller retries.Tests
tests/unit/test_2991_start_skills_result.pydrives the realstart_agent_endpointwith the lifecycle stubbed, across clean, conflict, partial with leaky error text, no-op, already-running, missing and malformed results. It also coversinject_assigned_skillsnaming conflicts.The system-agent restart and fleet-restart assertions were added to their existing tests.
src/mcp-server/src/tools/agents.start.test.tsdrives the real toolexecute().Mutation checks (fix reverted, then restored):
Results: 115 backend tests pass across the start, skip-inject, fleet-restart and system-agent suites. The MCP suite passes (277), and
tscis clean.Review
The independent review found no blockers. I fixed its lows:
skills_conflictsentry;unassigned_meanwhileis quiet in the MCP output;Noted, out of scope:
credentials_resultin the same response still passes raw error text through. It's the same projection concern, and I'd suggest a follow-up issue.refused/faileddetail is reduced to status plus count.🤖 Generated with Claude Code