{
  "name": "spawn_workstream",
  "description": "Create a new child workstream, optionally dispatching an initial message. Kick off a focused sub-task on a different skill / model / node while the coordinator stays in charge. The child runs independently — drive it with send_to_workstream / inspect_workstream / close_workstream. Returns `{ws_id, name, node_id, routing_strategy}`. `routing_strategy` is `rendezvous` (default placement on the live-node set), `target_node` (your hint was honored), or `resume` (rebound to a still-alive prior owner on rehydrate). The returned `node_id` is the spawn-time binding; subsequent ops re-route via rendezvous over the live-node set, so a node join or drop after spawn can shift the active owner. Conversation state lives in storage (the new owner rehydrates lazily). Don't cache `node_id` for long-running callbacks — re-read with inspect_workstream. Lifecycle state (idle / running / etc.) is not in this response — read it via inspect_workstream.",
  "parameters": {
    "type": "object",
    "properties": {
      "initial_message": {
        "type": "string",
        "description": "First user message to dispatch to the new workstream. If empty, the workstream is created idle and waits for send_to_workstream."
      },
      "skill": {
        "type": "string",
        "description": "Optional skill name to apply to the new workstream (overrides default skills, may select a model)."
      },
      "name": {
        "type": "string",
        "description": "Optional display name for the new workstream. Auto-generated when empty."
      },
      "model": {
        "type": "string",
        "description": "Optional model alias from the registry. Omit to use the coordinator's default model (or the one the skill prescribes)."
      },
      "target_node": {
        "type": "string",
        "description": "Optional node_id hint. When provided, the routing proxy pins the workstream to that node by generating a ws_id that rendezvous-hashes onto it. Otherwise rendezvous picks deterministically from the live-node set. CAVEAT: pinning is a hard constraint — if the named node has dropped out of the 120s service-registry heartbeat window between your `list_nodes` call and this spawn, the spawn fails with \"No available node for routing\" rather than falling back. Omit `target_node` if you can tolerate landing on any node; pin only when the workload truly requires that specific node's capabilities/region/tenancy."
      }
    },
    "required": []
  },
  "coordinator": true,
  "primary_key": "initial_message"
}
