{
  "name": "wait_for_workstream",
  "description": "Block until one or all named child workstreams reach a terminal state. Prefer this over busy-polling inspect_workstream after a fan-out: the tool absorbs the wait, so you get one call + one result regardless of duration. Returns `{results: {ws_id: {state, tokens, updated, message, truncated}}, elapsed, complete, mode}` — `results` is keyed by ws_id (not top-level), `complete` is true when the wait condition fired before the timeout. `message` is the child's last assistant text for `idle`/`error`, a short sentinel for `closed`/`denied`, and `null` for non-terminal rows so a follow-up read knows which children still need work; capped at 10 KiB UTF-8, with `truncated=true` when the cap fires (call inspect_workstream for the rest). Real terminal states: `idle`, `error`, `closed`, `deleted` (the last is unobservable since hard-delete cascades the row out of storage). `mode='any'` returns when the first child hits a real terminal — a `denied` id alone never satisfies the condition, so a typo'd / foreign / nonexistent id can't false-positive a wait. `mode='all'` returns once every id has settled (real terminal OR denied). Cross-tenant guard: only the coordinator's own children (or itself) are visible; everything else is reported `state='denied'`. Capped at 32 ws_ids and 600s; both overflows error rather than silently truncating.",
  "parameters": {
    "type": "object",
    "properties": {
      "ws_ids": {
        "type": "array",
        "items": { "type": "string" },
        "description": "Workstream ids to wait on. Accepts 1 or more; capped at 32 per call."
      },
      "timeout": {
        "type": "number",
        "description": "Maximum seconds to block. Default 60. Capped at 600 — for longer waits, call again with the same ws_ids."
      },
      "mode": {
        "type": "string",
        "enum": ["any", "all"],
        "default": "any",
        "description": "'any' (default) returns when the first child reaches a real terminal state (idle / error / closed / deleted); 'all' returns once every named child has settled (real terminal OR denied). A pure-denied list with mode='any' short-circuits to complete=false rather than spinning the timeout."
      },
      "since": {
        "type": "object",
        "description": "Optional prior snapshot (typically the `results` dict from an earlier wait_for_workstream call). When provided, the wait exits as soon as ANY polled ws_id that ALSO has a `since` entry differs from that prior snapshot (state/tokens/updated), regardless of mode. Skip re-counting already-terminal children on follow-up waits. ws_ids absent from `since` do NOT trigger the diff-based early exit — they fall back to the normal `mode` condition, so a disjoint `since` dict doesn't silently exit on tick one. Omit for the default terminal-state behaviour.",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "state": { "type": "string" },
            "tokens": { "type": "integer" },
            "updated": { "type": "string" }
          }
        }
      }
    },
    "required": ["ws_ids"]
  },
  "coordinator": true,
  "auto_approve": true
}
