diff --git a/tools/delegate_tool.py b/tools/delegate_tool.py index 5fcac557b4..a5c9eae0d1 100644 --- a/tools/delegate_tool.py +++ b/tools/delegate_tool.py @@ -475,8 +475,7 @@ def _build_top_level_description() -> str: "transcript paths, and the completed result (one consolidated message, " "results in task order) re-enters the conversation on its own. Do NOT " "wait or poll; continue other work. While children run, `action` " - "(list/steer/stop) controls them live — steer when a transcript shows " - "a child drifting.\n\n" + "(list/steer/stop) controls them live — steer when a transcript shows a child drifting.\n\n" "USE FOR: reasoning-heavy subtasks, work that would flood your context " "with intermediate data, or independent parallel workstreams.\n" "DO NOT USE FOR (use these instead):\n" @@ -484,12 +483,10 @@ def _build_top_level_description() -> str: "- A single tool call -> call the tool directly\n" "- Tasks needing user interaction -> subagents cannot ask questions\n" "- Durable work that must survive this session -> cronjob or " - "terminal(background=True, notify=True); /stop, /new, or " - "process exit discards running subagents.\n\n" + "terminal(background=True, notify=True); /stop, /new, or process exit discards running subagents.\n\n" "RULES:\n" "- Children know nothing of this conversation: pass everything needed " - "via 'context', including any required output language, tone, or " - "style (e.g. \"respond in Chinese\").\n" + "via 'context', including any required output language, tone, or style (e.g. \"respond in Chinese\").\n" "- Child summaries are SELF-REPORTS, not verified facts: a child " "claiming \"uploaded successfully\" or \"file written\" may be wrong. " "For external side effects (uploads, remote writes, publishing), " diff --git a/tools/delegate_tool_child_run.py b/tools/delegate_tool_child_run.py index f641b3ba6e..f4e7c2e047 100644 --- a/tools/delegate_tool_child_run.py +++ b/tools/delegate_tool_child_run.py @@ -176,19 +176,10 @@ def _dump_subagent_timeout_diagnostic( if len(_goal_preview) > 1000: _goal_preview = _goal_preview[:1000] + " ...[truncated]" lines: List[str] = [ - "# Subagent timeout diagnostic — issue #14726", - f"# Generated: {_dt.datetime.now().isoformat()}", - "", - "## Timeout", - f" task_index: {task_index}", - f" subagent_id: {subagent_id}", - f" configured_timeout: {timeout_seconds}s", - f" actual_duration: {duration_seconds:.2f}s", - "", - "## Goal", - _goal_preview or "(empty)", - "", - "## Child config", + "# Subagent timeout diagnostic — issue #14726", f"# Generated: {_dt.datetime.now().isoformat()}", "", + "## Timeout", f" task_index: {task_index}", f" subagent_id: {subagent_id}", + f" configured_timeout: {timeout_seconds}s", f" actual_duration: {duration_seconds:.2f}s", "", "## Goal", + _goal_preview or "(empty)", "", "## Child config", ] for attr in _DIAG_CHILD_ATTRS: try: @@ -458,8 +449,7 @@ def _build_tool_trace(messages: Any) -> list[Dict[str, Any]]: fn = tc.get("function", {}) arguments = fn.get("arguments", "") entry_t = { - "tool": fn.get("name", "unknown"), - "args_bytes": len(arguments), + "tool": fn.get("name", "unknown"), "args_bytes": len(arguments), "input_summary": _summarize_tool_arguments(arguments), } tool_trace.append(entry_t) @@ -773,8 +763,7 @@ class _ChildRun: if not mod_paths: return reminder = ( - "\n\n[NOTE: subagent modified files the parent " - "previously read — re-read before editing: " + "\n\n[NOTE: subagent modified files the parent previously read — re-read before editing: " + ", ".join(mod_paths[:8]) + (f" (+{len(mod_paths) - 8} more)" if len(mod_paths) > 8 else "") + "]" diff --git a/tools/delegate_tool_config.py b/tools/delegate_tool_config.py index 623c4621c3..da144e78a0 100644 --- a/tools/delegate_tool_config.py +++ b/tools/delegate_tool_config.py @@ -99,8 +99,7 @@ def _get_max_concurrent_children() -> int: ) if result > 10 and _cfg().get("max_concurrent_children") is not None: _warn_once( - "_HIGH_CONCURRENCY_WARNED", - "delegation.max_concurrent_children=%d: each child consumes API tokens " + "_HIGH_CONCURRENCY_WARNED", "delegation.max_concurrent_children=%d: each child consumes API tokens " "independently. High values multiply cost linearly.", result, ) return result @@ -125,8 +124,7 @@ def _get_max_async_children() -> int: from tools.delegate_tool import _get_max_concurrent_children if _cfg().get("max_async_children") is not None: _warn_once( - "_LEGACY_MAX_ASYNC_WARNED", - "delegation.max_async_children is deprecated and ignored; " + "_LEGACY_MAX_ASYNC_WARNED", "delegation.max_async_children is deprecated and ignored; " "delegation.max_concurrent_children now caps background " "delegations too. Remove the stale key from config.yaml.", ) diff --git a/tools/delegate_tool_dispatch.py b/tools/delegate_tool_dispatch.py index d75bece043..bfe72e0d1a 100644 --- a/tools/delegate_tool_dispatch.py +++ b/tools/delegate_tool_dispatch.py @@ -49,8 +49,7 @@ class _Batch: def owner_kwargs(self) -> Dict[str, Any]: """Steer/stop authority of the originating session, passed to every child run.""" return { - "owner_session_id": self.origin_ui_session_id or None, - "owner_transport": self.origin_owner_transport, + "owner_session_id": self.origin_ui_session_id or None, "owner_transport": self.origin_owner_transport, "owner_session_record": self.origin_owner_session_record, } @@ -174,15 +173,12 @@ _SYNC_FALLBACK_NOTES = { "background=true is not available in this session — it cannot " "receive a detached subagent result after the turn ends (a " "one-shot runner such as `hermes -z`, a cron job, a Kanban " - "worker, or a stateless HTTP endpoint). The subagent(s) ran " - "SYNCHRONOUSLY and the result is included above." + "worker, or a stateless HTTP endpoint). The subagent(s) ran SYNCHRONOUSLY and the result is included above." ), "at_capacity": ( - "The background delegation pool was at capacity " - "(delegation.max_concurrent_children), so the subagent(s) ran " + "The background delegation pool was at capacity (delegation.max_concurrent_children), so the subagent(s) ran " "SYNCHRONOUSLY and the result is included above. Raise " - "delegation.max_concurrent_children in config.yaml to allow " - "more concurrent background delegations." + "delegation.max_concurrent_children in config.yaml to allow more concurrent background delegations." ), } @@ -212,12 +208,9 @@ def _resolve_async_wake_sid(origin_wake_sid: str) -> Optional[str]: return "" if origin_wake_sid: logger.info( - "delegate_task: async delivery unsupported on this " - "session, but a session id is bound (%s) — dispatching " - "in the background and waking the session via self-post " - "when it completes instead of forcing synchronous " - "execution.", - origin_wake_sid, + "delegate_task: async delivery unsupported on this session, but a session id is bound (%s) — dispatching " + "in the background and waking the session via self-post when it completes instead of forcing synchronous " + "execution.", origin_wake_sid, ) return origin_wake_sid return None @@ -277,14 +270,12 @@ def _dispatched_payload(dispatch: dict, goals: List[str], child_agents: List[Any "note": ( "Subagent is running in the background. You and the user can " "keep working; its full result re-enters the conversation as a " - "new message when it finishes. Do not wait or poll — just " - "continue." + "new message when it finishes. Do not wait or poll — just continue." if n == 1 else f"{n} subagents are running in parallel in the background. You " f"and the user can keep working; they wait on each other and " f"their consolidated results re-enter the conversation as a " - f"single message once ALL of them finish. Do not wait or poll " - f"— just continue." + f"single message once ALL of them finish. Do not wait or poll — just continue." ), } sids = [getattr(c, "_subagent_id", None) for c in child_agents] @@ -294,16 +285,14 @@ def _dispatched_payload(dispatch: dict, goals: List[str], child_agents: List[Any "While a child runs you can orchestrate it live with this " "same tool: delegate_task(action='list') to see live " "children, action='steer' with subagent_id + message to " - "redirect one, action='stop' with subagent_id to end one " - "early." + "redirect one, action='stop' with subagent_id to end one early." ) if live_paths: payload["live_transcripts"] = list(live_paths) payload["live_transcripts_hint"] = ( "Each subagent streams a human-readable transcript of its " "operations to the file listed above (append-only, one per " - "task). Read or `tail -f` these paths at any time to watch " - "a child work while it runs." + "task). Read or `tail -f` these paths at any time to watch a child work while it runs." ) return payload @@ -318,7 +307,6 @@ def _dispatch_background(batch: _Batch) -> str: """ from tools.delegate_tool import _get_max_async_children from tools.async_delegation import dispatch_async_delegation_batch - wake_sid = _resolve_async_wake_sid(batch.origin_wake_sid) if wake_sid is None: logger.info("delegate_task: async delivery unsupported on this session runtime; running the batch synchronously instead.") diff --git a/tools/delegate_tool_progress.py b/tools/delegate_tool_progress.py index bf872a17c9..5c7c56c147 100644 --- a/tools/delegate_tool_progress.py +++ b/tools/delegate_tool_progress.py @@ -159,8 +159,7 @@ def _build_child_system_prompt( "your work in this workspace.\n\n" + _ctx_files.strip() ) parts.append( - "\nComplete this task using the tools available to you. " - "When finished, provide a clear, concise summary of:\n" + "\nComplete this task using the tools available to you. When finished, provide a clear, concise summary of:\n" "- What you did\n" "- What you found or accomplished\n" "- Any files you created or modified\n" @@ -189,16 +188,14 @@ def _build_child_system_prompt( "WHEN to delegate:\n" "- The goal decomposes into 2+ independent subtasks that can " "run in parallel (e.g. research A and B simultaneously).\n" - "- A subtask is reasoning-heavy and would flood your context " - "with intermediate data.\n\n" + "- A subtask is reasoning-heavy and would flood your context with intermediate data.\n\n" "WHEN NOT to delegate:\n" "- Single-step mechanical work — do it directly.\n" "- Trivial tasks you can execute in one or two tool calls.\n" "- Re-delegating your entire assigned goal to one worker " "(that's just pass-through with no value added).\n\n" "Coordinate your workers' results and synthesize them before " - "reporting back to your parent. You are responsible for the " - "final summary, not your workers.\n\n" + "reporting back to your parent. You are responsible for the final summary, not your workers.\n\n" f"NOTE: You are at depth {child_depth}. The delegation tree " f"is capped at max_spawn_depth={max_spawn_depth}. {child_note}" ) diff --git a/tools/delegate_tool_registry.py b/tools/delegate_tool_registry.py index cf9a99f4c8..11cebb14b9 100644 --- a/tools/delegate_tool_registry.py +++ b/tools/delegate_tool_registry.py @@ -72,9 +72,7 @@ def _unregister_subagent(subagent_id: str, *, agent: Any = None) -> None: sid = record.get("subagent_id") if not sid: return - _recent_subagents[sid] = { - k: record.get(k) for k in ("goal", "delegation_id", "owner_agent_session_id") - } + _recent_subagents[sid] = {k: record.get(k) for k in ("goal", "delegation_id", "owner_agent_session_id")} while len(_recent_subagents) > _RECENT_SUBAGENTS_CAP: _recent_subagents.pop(next(iter(_recent_subagents)), None) @@ -299,21 +297,16 @@ def _handle_control_action(action: str, subagent_id: Optional[str], message: Opt _CONTROL_OUTCOMES = { "stop": ( "interrupt_requested", - "The subagent stops at its next iteration boundary " - "(in-flight tool calls are asked to cancel). Its " - "partial result still re-enters the conversation as a " - "completion message — do not wait or poll.", + "The subagent stops at its next iteration boundary (in-flight tool calls are asked to cancel). Its " + "partial result still re-enters the conversation as a completion message — do not wait or poll.", "Could not interrupt '{sid}' — it likely finished in the last " "moment. Its result arrives as a normal completion message.", ), "steer": ( "queued", - "Steering text queued. The subagent sees it appended " - "to its next tool result — the current tool call is " - "never cut. If the child finishes before a delivery " - "boundary remains, the text is reported back as " - "missed_steer in its completion entry.", - "Subagent '{sid}' is no longer accepting steering (finishing or " + "Steering text queued. The subagent sees it appended to its next tool result — the current tool call is " + "never cut. If the child finishes before a delivery boundary remains, the text is reported back as " + "missed_steer in its completion entry.", "Subagent '{sid}' is no longer accepting steering (finishing or " "already finished). Its result arrives as a normal completion " "message; re-delegate a follow-up task if more work is needed.", ), diff --git a/tools/delegate_tool_results.py b/tools/delegate_tool_results.py index 35c67530ac..36a84bac61 100644 --- a/tools/delegate_tool_results.py +++ b/tools/delegate_tool_results.py @@ -217,8 +217,7 @@ def _trim_summary_with_footer(summary: str, cap: int, task_index: int) -> tuple[ spill_path = _spill_summary_to_file(task_index, summary) footer_lines = [ - "", - "─" * 8 + " [SUMMARY TRUNCATED] " + "─" * 8, + "", "─" * 8 + " [SUMMARY TRUNCATED] " + "─" * 8, f"Showing {len(head):,} chars (head) + {len(tail):,} chars (tail) " f"of {original_len:,} total — trimmed to protect the parent's context window.", ]