# handover_to_specialist – Tool Documentation > **Status:** Phase 1 (read-only spike). The tool prepares a stage-1 handover > package and appends a per-specialist briefing file. It does **not** yet > invoke the subagent – the orchestrator follows up with `call_subordinate()`. --- ## Purpose The Software-Orchestrator plugin exposes a single specialist hand-off tool that follows the **3-stage context-transfer pattern** documented in `/usr/workdir/handover-spike.md` (sections 4 and 5): 1. **Stage 1 (default):** token-bounded package = `summary` + last N turns + decisions + artifacts. Cost ≈ 1 500 – 4 000 tokens. 2. **Stage 2 (opt-in):** specialist calls `request_full_history()` for the full chat context, capped at 50 000 tokens with automatic compaction. 3. **Stage 3 (persistent):** briefing file in `/.a0proj/handover/--.md`, append-only Markdown, readable on demand by the specialist. The goal is to give the user the experience of talking to a named specialist (frontend designer, planner, architect, …) while keeping token usage low and context safe. --- ## Tool signature ```python handover_to_specialist( specialist_profile: str, # required, must be in the allow-list topic: str, # required, short slug for the briefing file summary: str, # LLM-curated summary of the older turns recent_turns: list[str], # verbatim last turns (auto-trimmed to N) decisions: list[str], # decisions made so far artifacts: list[str], # paths / references to relevant files return_condition: str, # when the specialist should hand back handover_reason: str, # logged into the briefing file project_root: str, # absolute path to the project root max_context_tokens: int, # default 3000; warning if exceeded include_recent_turns: int, # default 5 ) ``` ### Argument notes | Argument | Required | Notes | |----------|----------|-------| | `specialist_profile` | ✅ | One of the 11 known profiles (see below). | | `topic` | ✅ | Short slug. Used in the briefing filename. | | `summary` | recommended | LLM-curated; max 300 tokens recommended. | | `recent_turns` | optional | Auto-trimmed to `include_recent_turns`. | | `decisions` | optional | Free-form bullet points. | | `artifacts` | optional | File paths or other references. | | `return_condition` | optional | Default `user_request`. | | `handover_reason` | optional | Logged in the briefing. | | `project_root` | ✅ | Must be absolute. Used for the briefing file path. | | `max_context_tokens` | optional | Default 3000. | | `include_recent_turns` | optional | Default 5. | --- ## Known specialist profiles The tool accepts only the following profile names. This is an explicit allow-list (defence-in-depth): a typo in the profile name produces a clear `ERROR` response, not a silent miss. - `a0_software_orchestrator` - `codebase_explorer` - `implementation_engineer` - `quality_reviewer` - `release_auditor` - `requirements_analyst` - `runtime_devops_engineer` - `security_data_engineer` - `solution_architect` - `test_debug_engineer` - `hacker` `frontend_designer` is **not** a known profile in Phase 1. It is on the roadmap for Phase 2. --- ## Return value The tool returns a JSON object with three top-level keys: ```json { "status": "ok", "persona_marker": "[frontend designer]", "package": { "specialist": "frontend_designer", "topic": "landing-page-hero", "summary": "...", "briefing_file": "/abs/path/.a0proj/handover/frontend-designer-landing-page-hero-2026-06-05.md", "estimated_tokens": 2143, "max_context_tokens": 3000, "oversize_warning": false }, "briefing": { "path": "/abs/path/.a0proj/handover/frontend-designer-landing-page-hero-2026-06-05.md", "existed_before": false, "newly_created": true, "size_bytes": 1789 }, "next_step": "Orchestrator: review the package, then call_subordinate(...)" } ``` If the package exceeds `max_context_tokens`, a `WARNING:` line is appended to the response so the orchestrator can decide whether to truncate. --- ## Errors The tool never raises an unhandled exception. All error paths return a `Response(message="ERROR: …", error=True)` so the orchestrator can decide how to react. Common error cases: | Error | Cause | |-------|-------| | `specialist_profile is required` | missing or empty | | `unknown specialist profile` | not in the allow-list | | `topic is required` | missing or empty | | `project_root is required` | missing or empty | | `project_root must be absolute` | relative path | | `max_context_tokens must be positive` | ≤ 0 | | `failed to append briefing file` | OSError (permissions, disk full, …) | --- ## What the tool does NOT do (Phase 1 limits) - ❌ Does **not** call `call_subordinate()`. The orchestrator is expected to do that in a follow-up reasoning step. - ❌ Does **not** LLM-summarise the older turns. The orchestrator must pass a pre-computed `summary` argument. - ❌ Does **not** update the `state_store`. A future phase will add a `state_store.snapshot()` call before the briefing is written. - ❌ Does **not** modify the chat loop or any framework core. - ❌ Does **not** expose a UI persona marker yet. Phase 3 will add the `🖌️ Designer` style marker to the chat output. --- ## Phase-2 plan (forward-looking) - `request_full_history()` tool for specialists (stage 2). - `call_subordinate()` wired into the orchestrator flow with persona marker. - Loop guard: `max_handover_depth = 3` to prevent bouncing. - Integration with `state_store.snapshot()` for crash safety. - Add `frontend_designer` (and any other missing) profile to the allow-list. - UI persona marker in the webui chat output. --- ## Related files - Helper: `helpers/handover_protocol.py` - Helper: `helpers/briefing_file.py` - Tool: `tools/handover_to_specialist.py` - Spike design doc: `/usr/workdir/handover-spike.md` - Memory-protection rules: enforced inside `handover_protocol.py` (no mid-subagent compaction, no overwrite, briefing ≠ chat history).