{
  "version": 1,
  "tools": [
    {
      "name": "subagent_spawn",
      "description": "Spawn an independent subagent to work on a task in parallel. The subagent runs autonomously and its results are reported back when complete.\n\nTwo modes:\n- **Regular sub-agent** (fork: false or omitted): Gets only the objective + context fields. Use for self-contained tasks with clear objectives. Pick its type with role: 'researcher' (read-only, fixed tool list) or 'builder' (write-capable, your whole tool surface).\n- **Fork** (fork: true): Inherits full parent context (messages, system prompt, memory). Shares KV cache for near-free context inheritance. Use when the task benefits from knowing what you've been discussing. A fork that names a role runs scoped to it; a fork that names none keeps your full tool surface. Results are internal by default (send_result_to_user: false). Read with last_n: 1 to get only the final synthesis.\n\nDecision heuristic: Does the task need to know what we've been talking about? Fork. Is it self-contained? Regular sub-agent.\n\nThe 'advisor' role is a synchronous, read-only \"consult a stronger advisor\" mode: it sees ONLY the brief you write in 'objective' plus a snapshot of your environment (available tools, skill catalog, workspace), has read-only workspace tools for checking a decisive fact (file_read, file_list, code_search), and BLOCKS until it returns focused strategic guidance in a single response. It cannot read this conversation, change anything, persist output, or see other conversations, so the quality of its guidance tracks the quality of your brief.",
      "category": "orchestration",
      "risk": "low",
      "input_schema": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "Short human-readable label for this subagent (e.g. \"Research competitor pricing\")"
          },
          "objective": {
            "type": "string",
            "description": "The task objective: what the subagent should accomplish. For role 'advisor' this field IS the brief the advisor reads, and the only account of the work it gets, so write it out in full: the task or goal, the approach you have chosen or the options you are weighing, the key evidence you already gathered (file paths, command output, decisions made), and the specific question you want answered."
          },
          "context": {
            "type": "string",
            "description": "Optional additional context to pass to the subagent. Ignored when fork is true (forks inherit the parent's full context), and ignored for role 'advisor', which reads only the objective brief."
          },
          "fork": {
            "type": "boolean",
            "description": "When true, the subagent inherits the parent's full context (messages, system prompt, memory) instead of receiving only the objective + context fields. A fork honors the role you name; naming none keeps this conversation's full tool surface, since the inherited system prompt describes those tools. Forks default send_result_to_user to false. Use for tasks that benefit from the full conversational context."
          },
          "send_result_to_user": {
            "type": "boolean",
            "description": "Whether to present the subagent's result to the user when it completes. Defaults to true for regular sub-agents, false for forks. Set explicitly to override."
          },
          "role": {
            "type": "string",
            "description": "Which of the three subagent types to run, chosen by two questions: does it need to change anything, and do you need the answer before you can continue? 'researcher': changes nothing, runs in the background, scoped to a fixed read-only list (web_search, web_fetch, file_read, file_list, code_search, recall, skill_execute) for research, exploration, root-cause investigation, and review. 'builder': changes things, runs in the background on this conversation's whole tool surface (shell, file writes and edits, plus every connector, MCP, and browser tool you can reach) for code changes, file output, and anything that must run a command or act on an outside system. 'advisor': changes nothing and BLOCKS your turn until it answers; reads the brief you write in 'objective' plus a snapshot of your environment (available tools, skill catalog, workspace), can read files and search code (file_read, file_list, code_search) to check a decisive fact, and returns focused strategic guidance. It cannot see this conversation, so a thin objective gets thin advice. Default when omitted: 'builder', so a spawn that names no type keeps the full tool surface. The older names are still accepted as aliases ('planner' and 'investigator' run as researcher, 'coder' and 'general' run as builder). Any other text is not a type: the subagent runs as a researcher with that text as its persona, so if the task must write files or run commands, name 'builder' explicitly. A read-only subagent asked to produce a file finishes without producing anything. Roles apply to forks too; a fork that names no role runs as a builder and keeps this conversation's full tool surface, and a fork's persona reaches it through its task framing."
          },
          "inference_profile": {
            "type": "string",
            "description": "Optional llm.profiles key this subagent should run under. When omitted, the subagent takes the subagentSpawn call site's default model selection, never the profile your own turn is running on: a profile pinned on this conversation is a choice about this conversation and does not follow the work you delegate. A profile you name here that the model catalog does not report as tool-capable is replaced by that same default, with a note on the result. An output_contract of 'verdict' takes a cheaper profile unless you name a profile here, or unless the subagentSpawn call site has its own profile pinned in config, which also beats the cheaper preset."
          },
          "confirm_repeat": {
            "type": "boolean",
            "description": "Set true to spawn anyway when the repeat-spawn guard reports that this objective already completed several times in the last day, or that near-identical copies of it are still running with nothing returned yet."
          },
          "output_contract": {
            "type": "string",
            "enum": ["report", "verdict", "artifact"],
            "description": "What the subagent owes back. 'report' (default): prose answering the objective. 'verdict': per-criterion PASS or FAIL with the exact evidence (file path, line, value, or quote), CANNOT VERIFY where evidence is missing, and no prose beyond that list; researcher-only, and it defaults to a cheaper model because checking is mechanical. Use it for completion checks and audits instead of spawning a premium investigator. 'artifact': the deliverable is the thing produced, ending with the exact files created or modified; builder-only. A contract that does not match the role is rejected rather than coerced, and the advisor takes no contract at all."
          }
        },
        "required": ["label", "objective"]
      },
      "executor": "tools/subagent-spawn.ts",
      "execution_target": "host"
    },
    {
      "name": "subagent_status",
      "description": "Get the status of a specific subagent or list all subagents for the current conversation. Only use this when the user explicitly asks about subagent status \u2014 do NOT poll automatically, as you will be notified when subagents complete.",
      "category": "orchestration",
      "risk": "low",
      "input_schema": {
        "type": "object",
        "properties": {
          "subagent_id": {
            "type": "string",
            "description": "Optional subagent ID to query. If omitted, returns all subagents for this conversation."
          },
          "label": {
            "type": "string",
            "description": "The label of the subagent (alternative to subagent_id). Case-insensitive."
          }
        },
        "required": []
      },
      "executor": "tools/subagent-status.ts",
      "execution_target": "host"
    },
    {
      "name": "subagent_abort",
      "description": "Abort a running subagent by ID or label.",
      "category": "orchestration",
      "risk": "low",
      "input_schema": {
        "type": "object",
        "properties": {
          "subagent_id": {
            "type": "string",
            "description": "The ID of the subagent to abort."
          },
          "label": {
            "type": "string",
            "description": "The label of the subagent (alternative to subagent_id). Case-insensitive."
          }
        },
        "required": []
      },
      "executor": "tools/subagent-abort.ts",
      "execution_target": "host"
    },
    {
      "name": "subagent_message",
      "description": "Send a follow-up message to a running subagent.",
      "category": "orchestration",
      "risk": "low",
      "input_schema": {
        "type": "object",
        "properties": {
          "subagent_id": {
            "type": "string",
            "description": "The ID of the subagent to send a message to."
          },
          "label": {
            "type": "string",
            "description": "The label of the subagent (alternative to subagent_id). Case-insensitive."
          },
          "content": {
            "type": "string",
            "description": "The message content to send to the subagent."
          }
        },
        "required": ["content"]
      },
      "executor": "tools/subagent-message.ts",
      "execution_target": "host"
    },
    {
      "name": "subagent_read",
      "description": "NOT a file reader: this returns a subagent's conversation output, addressed by subagent_id or label. To read a file from disk use file_read instead. Use this after a subagent completes to retrieve its full work product; while it is still running you will be notified automatically when it finishes, so there is no need to poll.",
      "category": "orchestration",
      "risk": "low",
      "input_schema": {
        "type": "object",
        "properties": {
          "subagent_id": {
            "type": "string",
            "description": "The ID of the subagent whose output to read."
          },
          "label": {
            "type": "string",
            "description": "The label of the subagent (alternative to subagent_id). Case-insensitive."
          },
          "last_n": {
            "type": "integer",
            "description": "Number of recent assistant messages to return. Omit to return all messages (current behavior)."
          }
        },
        "required": []
      },
      "executor": "tools/subagent-read.ts",
      "execution_target": "host"
    }
  ]
}
