Conversation
…n (MAS-214) Add async_=True parameter to spawn_subagents MCP tool for non-blocking subagent execution. When enabled, subagents run in background while parent continues working. Results are automatically injected via SubagentCompleteHook when subagents complete. Key changes: - SubagentManager: Add callback mechanism for completion notification - SubagentCompleteHook: New PostToolUse hook for result injection - Orchestrator: Add pending results queue and hook registration - MCP tool: Add async_ parameter with immediate return for background mode - Result formatter: XML-structured format for injected results - Config: Add async_subagents config with injection_strategy option Includes TDD test suite (196 tests) and integration tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR implements async subagent execution with automatic result injection. It reorganizes subagent configuration under a coordination block, adds per-round timeouts, introduces async spawning and continuation capabilities, implements a PostToolUse hook for result injection, and extends orchestration to queue and deliver subagent results to parent agents. Changes
Sequence Diagram(s)sequenceDiagram
participant Parent as Parent Agent
participant Orch as Orchestrator
participant SubMgr as SubagentManager
participant Sub as Subagent
participant Hook as SubagentCompleteHook
Parent->>Orch: Run with coordination config<br/>(async_subagents enabled)
Orch->>Orch: Register SubagentCompleteHook<br/>with pending results queue
Orch->>SubMgr: Register completion callback<br/>(_on_subagent_complete)
Parent->>Orch: Tool call: spawn_subagents<br/>(async_=true)
Orch->>SubMgr: spawn_subagent_background()
SubMgr->>Sub: Launch subprocess<br/>(subagent with refine=false)
SubMgr-->>Orch: Return immediately with IDs
Orch-->>Parent: Return async mode response<br/>(subagent IDs, running status)
Note over Sub: Subagent executes<br/>(potentially multiple turns<br/>if refine=true)
Sub-->>SubMgr: Completes with result
SubMgr->>Orch: Invoke completion callback<br/>(_on_subagent_complete)
Orch->>Orch: Queue result in<br/>pending_subagent_results[parent_id]
Parent->>Orch: Next tool call
Orch->>Hook: PostToolUse event
Hook->>Orch: Get pending results
Hook->>Hook: format_batch_results()
Hook-->>Orch: Inject formatted content<br/>(tool_result or user_message)
Orch-->>Parent: Tool output with<br/>injected subagent results
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
massgen/config_validator.py (1)
785-858: Addasync_subagents,subagent_round_timeouts, andplan_depthto excluded config parameters and config builder.The new coordination validation logic adds three parameters that are missing from the required propagation points:
massgen/backend/base.py→get_base_excluded_config_params(): Must excludeasync_subagents,subagent_round_timeouts, andplan_depthalongside existing coordination params likevote_onlyanduse_two_tier_workspace, otherwise these parameters will leak to backend provider APIs.
massgen/api_params_handler/_api_params_handler_base.py→get_base_excluded_params(): Same exclusions needed to prevent API parameter pollution.
massgen/config_builder.py: Missing interactive wizard prompts forasync_subagents,subagent_round_timeouts, andplan_depth. The builder currently supportsenable_subagentsandsubagent_orchestratorbut not the new async coordination controls or planning depth options.Without these updates, users cannot configure these settings through the interactive builder, and the new parameters will incorrectly propagate to backend implementations.
massgen/mcp_tools/subagent/_subagent_mcp_server.py (1)
323-338: Return docs don’t match the actual summary payload.The docstring omits
failed(and doesn’t mentionpartial/completed_but_timeout), but the implementation returnsfailedand supports additional statuses. Please update the return docs to mirror the actual shape. As per coding guidelines, keep documentation consistent with implementation.massgen/orchestrator.py (1)
31-63: Stale subagent results can persist across coordination rounds and leak into later turns; add state validation to drop results when parent is inactive.
_on_subagent_complete()appends results to_pending_subagent_resultswithout checking parent state. If a subagent completes after its parent has voted or after coordination ends, the result is queued but never retrieved (hooks only trigger on tool use). Results then persist in the dictionary across coordination rounds since it's not cleared whenworkflow_phaseresets toidle, risking injection into the next turn if the same agent is reused.Add validation to drop results when the parent is no longer active:
🛠️ Suggested fix
def _on_subagent_complete( self, parent_agent_id: str, subagent_id: str, result: "SubagentResult", ) -> None: + state = self.agent_states.get(parent_agent_id) + if self.workflow_phase != "coordinating" or (state and state.has_voted): + logger.debug( + f"[Orchestrator] Dropping subagent result {subagent_id} for {parent_agent_id} (parent inactive)" + ) + return if parent_agent_id not in self._pending_subagent_results: self._pending_subagent_results[parent_agent_id] = [] self._pending_subagent_results[parent_agent_id].append((subagent_id, result))Also applies to: 284-295, 4316-4334, 4875-4891
massgen/subagent/manager.py (1)
735-784: Critical: Tuple unpacking mismatch will causeValueErrorat runtime.The
_parse_subprocess_statusmethod was updated to return a 3-tuple(token_usage, subprocess_log_dir, session_id)(line 997), but the timeout, cancellation, and generic exception handlers still use 2-tuple unpacking.🐛 Proposed fix
except asyncio.TimeoutError: logger.error(f"[SubagentManager] Subagent {config.id} timed out") # Still copy logs even on timeout - they contain useful debugging info - _, subprocess_log_dir = self._parse_subprocess_status(workspace) + _, subprocess_log_dir, _ = self._parse_subprocess_status(workspace) self._write_subprocess_log_reference(config.id, subprocess_log_dir, error="Subagent timed out")except asyncio.CancelledError: # ... # Still copy logs even on cancellation - they contain useful debugging info - _, subprocess_log_dir = self._parse_subprocess_status(workspace) + _, subprocess_log_dir, _ = self._parse_subprocess_status(workspace) self._write_subprocess_log_reference(config.id, subprocess_log_dir, error="Subagent cancelled")except Exception as e: logger.error(f"[SubagentManager] Subagent {config.id} error: {e}") # Still copy logs even on error - they contain useful debugging info - _, subprocess_log_dir = self._parse_subprocess_status(workspace) + _, subprocess_log_dir, _ = self._parse_subprocess_status(workspace) self._write_subprocess_log_reference(config.id, subprocess_log_dir, error=str(e))
🤖 Fix all issues with AI agents
In `@docs/source/user_guide/advanced/subagents.rst`:
- Around line 166-169: The example call to spawn_subagents in the docs includes
an invalid "context" parameter; remove the "context": "Building a Bob Dylan
tribute website with biography, discography, and songs pages" line from the JSON
example so the call only uses the supported parameters (tasks, async_, refine)
and relies on the workspace CONTEXT.md for context; keep the "refine": true line
intact and ensure the example matches the spawn_subagents signature.
In `@massgen/cli.py`:
- Around line 2289-2294: CoordinationConfig constructions are missing
propagation of the subagent_round_timeouts option, so per-round subagent
timeouts are ignored in modes like run_single_question and run_turn; update
every CoordinationConfig instantiation (e.g., where run_single_question and
run_turn build a CoordinationConfig) to include
subagent_round_timeouts=coord_cfg.get("subagent_round_timeouts") alongside the
existing subagent_* fields (subagent_default_timeout, subagent_max_concurrent,
enable_subagents, subagent_orchestrator, use_two_tier_workspace) so the setting
is consistently applied across all code paths.
In `@massgen/mcp_tools/hooks.py`:
- Around line 888-895: Add a Google-style docstring to
SubagentCompleteHook.execute that documents parameters and return value:
describe Args including function_name (str): name of the subagent function,
arguments (str): serialized args passed, context (Optional[Dict[str, Any]]):
optional execution context, and **kwargs for extra options; and add a Returns
section describing that the method returns a HookResult indicating
success/failure and any payload, plus an optional Raises section if the method
can raise errors; place this docstring directly under the async def execute
signature so tools and linters pick it up.
In `@massgen/mcp_tools/subagent/_subagent_mcp_server.py`:
- Around line 422-447: The async branch currently returns "success": True
regardless of individual spawn results from manager.spawn_subagent_background;
change the logic after collecting spawned to inspect each returned info (e.g.,
check for dicts with success==False or presence of an "error" key) and compute
an overall success boolean (False if any spawn failed), include a list/summary
of failures in the response, and only call _save_subagents_to_filesystem() if
there is at least one successful spawn; reference
manager.spawn_subagent_background, normalized_tasks, spawned, and
_save_subagents_to_filesystem when making these checks and updating the returned
payload.
- Around line 498-513: The summary counts currently only count statuses
"completed", "error", and "timeout" and thus misses the new statuses; update the
summary calculation in the spawn_subagents response to include the new statuses
from results: compute completed as sum for r.status in ("completed",
"completed_but_timeout", "partial"), compute timeout as sum for r.status in
("timeout", "completed_but_timeout"), keep failed as r.status == "error", and
ensure any downstream use of all_success (all(r.success for r in results))
remains correct; update the returned "summary" object accordingly where
completed, failed, and timeout are set.
In `@massgen/subagent/manager.py`:
- Around line 2003-2011: The conditional inside the loop over
agent_registry.get("subagents", {}) is wrong: `agent_id == self.parent_agent_id`
can never be relied on there and makes the skip logic dead/incorrect; update the
skip to only check whether this subagent is already present by using `if
subagent_id in subagents` (remove the `agent_id == self.parent_agent_id`
conjunct) so the loop correctly skips duplicates when iterating agent_registry
in the manager code that builds prefixed_id from agent_id and subagent_id.
- Around line 1680-1683: The NameError happens because registry (and possibly
registry_file) are only set when the subagent is found in the current agent's
registry; when you locate the subagent in another agent's registry you must
assign the same names before updating. Modify the code path that handles
“subagent found in another agent's registry” to set registry = other_registry
(or the variable holding that other agent's registry) and registry_file =
other_registry_file (or the Path used for that registry) so that the subsequent
lines that set subagent_entry["status"] and call
registry_file.write_text(json.dumps(registry, ...)) operate on the correct
registry object; ensure you reference the same subagent_entry object found in
that registry.
- Around line 1396-1410: The SubagentState instantiation in manager.py passes
finished_at=datetime.now() but the SubagentState dataclass
(massgen/subagent/models.py) has no finished_at field; remove the finished_at
keyword from the SubagentState(...) call in manager.py to match the dataclass,
or if you need to track finish time, add a finished_at: Optional[datetime] =
None field (with appropriate import) to the SubagentState dataclass definition
instead; update either SubagentState(...) or the dataclass so both sides use the
same fields.
In `@massgen/subagent/result_formatter.py`:
- Around line 73-85: The header currently uses count = len(results) and labels
all entries as "completed" which is misleading; change it to compute a
completed_count by iterating results and checking each result's status (e.g.,
sum(1 for _, r in results if r.get("status") == "completed" or getattr(r,
"status", None) == "completed")), then use that completed_count in the header
string (and optionally include total=len(results) for clarity); update
references around format_single_result, formatted_results, results, and header
so the header accurately reflects completed vs. total results.
- Around line 35-53: The returned XML is vulnerable because raw result.answer,
result.error and other fields (e.g., result.workspace_path, token_element
content) can contain XML-breaking characters or closing tags; update the
formatter that builds the string (the block returning the f-string in
result_formatter.py) to escape XML special characters (at minimum &, <, >, " and
') for all injected fields or wrap the dynamic content in a CDATA section
(choose one consistent approach), applying it to content (derived from
result.answer/result.error), workspace_path, and any token_element text before
constructing the final <subagent_result> string so injected text cannot break
the XML wrapper.
In `@massgen/tests/test_subagent_result_formatter.py`:
- Around line 403-419: The formatter in massgen.subagent.result_formatter
(format_single_result and any helpers that build XML for SubagentResult)
currently injects raw result.answer/result.error (and any fields used as XML
attributes) into XML; update format_single_result to escape XML special
characters (&, <, >, ", ') for both element text and attribute values before
inserting (use a standard utility such as xml.sax.saxutils.escape or
html.escape), ensure workspace_path/subagent_id used in attributes are escaped
too, and run/adjust tests so they assert the escaped content appears (or
continue asserting unescaped substrings like "Answer with" if they remain
present).
In `@openspec/changes/add-async-subagent-execution/proposal.md`:
- Around line 28-36: Update the example YAML so it matches the actual validation
path by nesting async_subagents under orchestrator.coordination (i.e., change
the block from orchestrator: async_subagents: ... to orchestrator.coordination:
async_subagents: ...); ensure the keys (enabled, injection_strategy,
inject_progress, max_background) remain unchanged and reference the same
async_subagents identifier used by the validator to avoid copy‑paste
misconfigurations.
In `@openspec/changes/add-async-subagent-execution/specs/subagent/spec.md`:
- Around line 116-123: The spec snippet shows the config under
orchestrator.async_subagents but the validator (massgen/config_validator.py)
expects orchestrator.coordination.async_subagents; update the spec example in
specs/subagent/spec.md to use the correct path
orchestrator.coordination.async_subagents (including the same nested keys
enabled and injection_strategy) so the example matches the implementation and
validation logic.
- Around line 1-2: There are duplicate section headers "## ADDED Requirements"
in the spec; locate the second occurrence of the header (the duplicate "## ADDED
Requirements" block) and either remove it or rename it to "## MODIFIED
Requirements" if the content is meant to be a modification, ensuring only one
"## ADDED Requirements" header remains and the document structure/linting is
preserved.
In `@openspec/changes/add-async-subagent-execution/tasks.md`:
- Around line 144-154: Update the documentation checklist paths to match actual
locations: replace `docs/source/user_guide/subagents.rst` with
`docs/source/user_guide/advanced/subagents.rst` and replace
`massgen/configs/tools/subagent/async_subagent_example.yaml` with
`massgen/configs/features/async_subagent_example.yaml` in the tasks.md entry
(the checklist items under "9.1 Update subagent user guide" and "9.2 Add example
configs") so the referenced targets point to the correct files.
In `@scripts/test_async_subagent_integration.py`:
- Around line 22-26: The import lines referencing SubagentResult and the two
formatter functions (format_batch_results, format_single_result) include unused
"# noqa: E402" directives; remove those trailing "# noqa: E402" annotations from
the import statements so the imports remain the same but without the unnecessary
linter suppressions (update the imports that import SubagentResult and the two
format_* functions accordingly).
🧹 Nitpick comments (11)
massgen/tests/test_subagent_manager.py (1)
31-36: Consider using pytesttmp_pathfor workspace paths.Hard-coded
/tmp/testpaths reduce isolation and trigger Ruff S108. Usingtmp_pathkeeps tests hermetic and portable. Apply across this file as feasible.♻️ Example refactor
-def test_register_completion_callback(self): +def test_register_completion_callback(self, tmp_path): """Test that a callback can be registered.""" from massgen.subagent.manager import SubagentManager manager = SubagentManager( - parent_workspace="/tmp/test", + parent_workspace=str(tmp_path), parent_agent_id="test-agent", orchestrator_id="test-orch", parent_agent_configs=[], )docs/source/reference/yaml_schema.rst (1)
994-1005: List sub-keys forsubagent_round_timeoutsandasync_subagents.
These are listed as generic objects; adding the expected keys (and types) would keep the schema as precise as other sections.openspec/changes/add-async-subagent-execution/design.md (1)
133-169: Align injection format in the design doc with the implemented formatter.
The design specifies a<subagent_results>wrapper and Summary/Details sections, but the current formatter uses a separator header plus individual<subagent_result>blocks. Update the design doc (or add a note) to reflect the final format.massgen/tests/test_subagent_result_formatter.py (1)
20-167: Adopt Google-style docstrings for new test methods.These test functions use brief one-line docstrings; the guideline calls for Google-style docstrings on new/changed functions. Consider expanding them (or documenting an exemption) for this test suite. As per coding guidelines, please align docstrings accordingly.
scripts/test_async_subagent_integration.py (1)
29-62: Use Google‑style docstrings for new helper functions.These new test helpers use short docstrings; the guideline calls for Google‑style docstrings on new/changed functions. Consider updating them across this script. As per coding guidelines, please align docstrings accordingly.
massgen/tests/test_subagent_mcp_server.py (4)
17-105: Exercise real code paths (and complete the placeholder test).This class mostly asserts against locally-constructed dicts and includes a placeholder
pass. Consider invoking the MCP tool via fixtures/mocks (or marking as xfail/skip until implemented) to avoid tautological tests and improve coverage. Also, Google‑style docstrings are expected for new test functions. As per coding guidelines, please align docstrings accordingly.
246-264: Implement or mark placeholder validation tests.These
passtests currently provide no coverage. Consider implementing assertions or marking them xfail/skip until behavior is ready.
271-303: Implement or mark placeholder background‑spawning tests.These
passtests currently provide no coverage. Consider implementing assertions or marking them xfail/skip until behavior is ready.
310-322: Implement or mark placeholder error‑handling tests.These
passtests currently provide no coverage. Consider implementing assertions or marking them xfail/skip until behavior is ready.massgen/subagent/manager.py (2)
997-1029: Consider logging exceptions for debugging.The bare
except Exception: passat lines 1027-1028 silently swallows all errors when parsing status.json. While this is acceptable for graceful fallback, logging at DEBUG level would help troubleshoot issues without cluttering normal output.♻️ Optional improvement
except Exception: - pass + logger.debug(f"[SubagentManager] Failed to parse status.json in {log_dir}")
1720-1728: Uselogging.exceptionfor better error diagnostics.Per static analysis hint,
logging.exceptionautomatically includes the stack trace without needingexc_info=True, making the error more useful for debugging.♻️ Proposed fix
except Exception as e: execution_time = time.time() - start_time - logger.error(f"[SubagentManager] Error continuing subagent {subagent_id}: {e}") + logger.exception(f"[SubagentManager] Error continuing subagent {subagent_id}") return SubagentResult.create_error( subagent_id=subagent_id, error=str(e), workspace_path=str(workspace), execution_time_seconds=execution_time, )
PR: Subagent Continuation & Round Timeouts
Summary
This PR implements two major features for subagent functionality, along with several important enhancements and bug fixes:
Key Benefits:
What Changed (10 Phases):
Implementation Details
Phase 1: Session Registry Integration
Closes MAS-211 (partial)
Changes:
--no-session-registryflag from subagent subprocess invocationstatus.jsonafter subagent completes--continuecommand filters out subagent sessions (user-facing only){workspace}/subagents/_registry.jsonFiles Modified:
massgen/subagent/manager.py:622-637- Removed--session-idfrom initial spawnmassgen/subagent/manager.py:688-694- Extract session ID from status.jsonmassgen/subagent/manager.py:995-1027- Updated_parse_subprocess_status()to return 3 valuesmassgen/cli.py:7415-7423- Auto-detect and label subagent sessionsmassgen/session/_registry.py:198-216- Filter subagents from--continuemassgen/subagent/manager.py:326-369- Added_save_subagent_to_registry()How It Works:
Key Fix: The original implementation passed
--session-idto new subagents, but the CLI treats--session-idas "restore existing session" not "create with this ID". This caused "Session not found in registry" errors. The fix lets MassGen auto-generate the session ID, then extracts it fromstatus.jsonafterward.Phase 2: Continue Subagent Tool
Closes MAS-211
Changes:
continue_subagent()method to SubagentManagercontinue_subagentMCP tool--session-idmechanism for session restorationFiles Modified:
massgen/subagent/manager.py:1424-1609- Addedcontinue_subagent()methodmassgen/mcp_tools/subagent/_subagent_mcp_server.py:697-802- Added MCP toolUsage Example:
How It Works:
_registry.jsonto getsession_idmassgen --session-id {session_id} "new message"restore_session()handles conversation restorationPhase 3: Round Timeouts for Subagents
Closes MAS-239
Changes:
initial_round_timeout_seconds,subsequent_round_timeout_seconds,round_timeout_grace_secondsFiles Modified:
massgen/subagent/manager.py:957-976- Round timeout inheritance logicConfiguration:
Inheritance Logic:
parent_round_timeoutssubagent_round_timeouts(only non-None values)timeout_settingsPhase 4: Refine Parameter
Closes MAS-211 (enhancement)
Changes:
refineparameter tospawn_subagents,spawn_parallel,spawn_subagent,spawn_subagent_backgroundmassgen/agent_config.py:254-269)refine=False: Single-pass execution (faster)refine=True: Multi-round coordination with voting (default)Files Modified:
massgen/subagent/manager.py:790- Read refine from metadatamassgen/subagent/manager.py:913-921- Apply TUI refinement flagsmassgen/mcp_tools/subagent/_subagent_mcp_server.py:279- Added parameter to MCP toolRefinement Flags (when
refine=False):Usage:
Phase 5: Enhanced list_subagents
Closes MAS-211 (partial)
Changes:
list_subagentsnow reads from_registry.jsonsession_id,continuable,last_continued_atFiles Modified:
massgen/subagent/manager.py:1863-1908- Enhanced list implementationmassgen/mcp_tools/subagent/_subagent_mcp_server.py:533- Removed unused parameterOutput Format:
{ "success": true, "subagents": [ { "subagent_id": "research_oauth", "status": "timeout", "workspace": "/path/to/workspace", "task": "Research OAuth 2.0...", "session_id": "subagent_research_oauth_abc123", "continuable": true, "created_at": "2024-01-20T10:00:00", "last_continued_at": "2024-01-20T10:05:00" } ], "count": 1 }Phase 6: Context Parameter Removal
Closes MAS-211 (enhancement)
Changes:
contextparameter from all subagent spawning methodsCONTEXT.mdfile in workspace before spawning subagentsgenerate_mediatool (seemassgen/mcp_tools/media/generate_media.py)Files Modified:
massgen/subagent/models.py:20-45- Removedcontextfield from SubagentConfigmassgen/subagent/manager.py:1107-1116- Removedcontextparameter fromspawn_subagent()massgen/subagent/manager.py:1251-1256- Removedcontextparameter fromspawn_parallel()massgen/subagent/manager.py:1167-1180- Added CONTEXT.md validationmassgen/mcp_tools/subagent/_subagent_mcp_server.py:275-285- Removedcontextfrom MCP toolWhy This Change:
The original implementation passed context as a string parameter, which created inconsistency with other tools. Following the
generate_mediapattern, we now require aCONTEXT.mdfile that subagents read directly. This:Usage Pattern:
Validation:
If CONTEXT.md doesn't exist, the tool returns a clear error:
Phase 7: Registry Merging (Cross-Agent Visibility)
Closes MAS-211 (enhancement)
Changes:
agent_temporary_workspaceparameter to SubagentManagerlist_subagents()now scans all agent temporary workspacescontinue_subagent()searches across all agent registriesFiles Modified:
massgen/subagent/manager.py:67- Addedagent_temporary_workspaceparametermassgen/subagent/manager.py:1870-1975- Enhancedlist_subagents()with registry mergingmassgen/subagent/manager.py:1491-1530- Enhancedcontinue_subagent()with cross-registry searchWhy This Matters:
When multiple agents spawn subagents, each agent needs visibility into subagents from other agents. This follows the same principle as workspace visibility - if an agent can see another agent's temporary workspace, it should be able to see and continue that agent's subagents.
How It Works:
Workspace Structure:
Phase 8: Async Subagent Spawning
Related to MAS-211 (background execution)
Changes:
async_parameter tospawn_subagentsMCP toolspawn_subagent_background()method for async executionFiles Modified:
massgen/subagent/manager.py:1206-1250- Addedspawn_subagent_background()methodmassgen/mcp_tools/subagent/_subagent_mcp_server.py:275- Addedasync_parametermassgen/mcp_tools/subagent/_subagent_mcp_server.py:416-472- Async execution logicHow It Works:
Broadcast Integration:
When async subagents complete:
{workspace}/subagents/{id}/answer.txtUse Cases:
Example Flow:
Phase 9: Detailed Subprocess Error Logging
Bug Fix
Changes:
Files Modified:
massgen/subagent/manager.py:720-727- Enhanced error loggingExample Output:
This logging was critical for discovering the session ID bug (Phase 1 fix).
Phase 10: Triple Unpacking Fix
Bug Fix
Changes:
Files Modified:
massgen/subagent/manager.py:738- Timeout handlermassgen/subagent/manager.py:760- Cancelled handlermassgen/subagent/manager.py:774- Generic error handlerThe Bug:
Changed
_parse_subprocess_status()to return 3 values(token_usage, log_dir, session_id)but forgot to update exception handlers:Testing
Unit Tests
massgen/tests/test_subagent_continuation.py- Tests for MAS-211:test_subagent_gets_session_id- Verify session ID generationtest_session_registry_saves_metadata- Registry persistencetest_continue_subagent_with_session_id- Continuation mechanismtest_continue_nonexistent_subagent- Error handlingtest_continue_completed_subagent- Refinement use casetest_list_shows_session_id- Enhanced listingtest_list_reads_from_registry- Registry integrationtest_refine_false_single_agent- Refine parameter behaviormassgen/tests/test_subagent_round_timeouts.py- Tests for MAS-239:test_inherits_parent_round_timeouts- Inheritance from parenttest_subagent_overrides_parent_timeouts- Subagent-specific overridestest_no_timeouts_when_not_configured- Empty config handlingtest_subagent_timeout_overrides_only_specified_fields- Partial overridestest_none_values_dont_override- None value handlingManual Test Script:
scripts/test_subagent_continuation_manual.py- End-to-end flow testRun Tests:
Example Configs
Basic Continuation Example
Usage:
Round Timeout Configuration
Refine Mode Examples
Fast Mode (refine=False):
Full Mode (refine=True, default):
Verification Checklist
Core Features (MAS-211, MAS-239)
massgen --continue, verify skips subagent sessionsrefine=False, verify single answer returnedrefine=True, verify multi-round coordinationBug Fixes
Context Parameter Removal
spawn_subagentsrequires CONTEXT.md filecontextparameter in tool signatureRegistry Merging
list_subagents()shows all subagents with source_agentcontinue_subagent()can continue subagents from other agentsAsync Spawning
async_=True, verify parent continues immediatelyBreaking Changes
Context Parameter Removed (MAS-211)
Breaking: The
contextparameter has been removed from all subagent spawning methods.Migration:
Rationale: This change follows the
generate_mediapattern and provides better separation between shared context and task-specific instructions.Other Changes (Backward Compatible)
refine=True,async_=False)Future Work
docs/source/user_guide/subagents.rst)Related Issues