Algolia-Central (Second-Brain)

spectrum/wiki/decisions/2026-07-09-drop-tool-call-handoff-use-native-suggestions.md

ADR: Drop the tool-call handoff design; use Agent Studio's native suggestions feature instead

Date: 2026-07-09 Status: Accepted

Context

The previous session's spike (docs/spikes/2026-07-08-agent-to-agent-tool-VERDICT.md and -findings.md, see sibling v2 research) proved that Algolia Agent Studio supports a real client-side tool call that can pause an agent mid-turn and resume it later with another agent's answer fed back in as a "tool result." That capability is real and correctly verified live.

Following that spike, the plan was to use this exact mechanism to replace the ACS chat's Generic→Technical handoff — today implemented as a fragile **HANDOFF:technical** text sentinel that the frontend regex-scans out of Generic's prose. The idea was: register a consult_technical_specialist tool on Generic, let Generic call it when a deep technical dive is warranted, intercept the pause, call Technical, and resume Generic's turn with Technical's answer.

Walking through this design with Arijit exposed a real mistake: the frontend in this app is already the orchestrator. It already calls Generic, then (on a button click) calls Technical, independently, passing context between them in application code. There was never a need for the model itself to autonomously invoke another agent — that's a different problem (relevant if a single agent needs to decide, mid-reasoning, to delegate to a specialist without app involvement) than what ACS actually has (the app already knows when to call Technical: the user clicked "go deeper").

Using the tool-call/pause/resume mechanism here would have also broken an existing product decision: because a tool call preempts an agent's own answer text in the same turn (confirmed live: "stream ended after tool call with no final answer text, 5/5 runs" in the spike findings), giving Generic that tool on its normal front-door turn would mean Generic sometimes gives NO visible answer at all, silently changing the always-answer-first UX locked in on 2026-07-03.

Decision

Cancel the tool-call handoff design for the Generic↔Technical relationship. Replace the **HANDOFF:technical** sentinel with Agent Studio's native config.suggestions feature (a real, documented, platform-level mechanism — not something invented in this project) as the trigger signal instead.

New flow: 1. User asks a question → Generic answers in full, exactly as it does today. No tool call, no pause. 2. Immediately after, Agent Studio's own suggestions feature fires a suggestions-chunk — a second, small model call the platform runs automatically when config.suggestions.enabled is true. 3. One suggestion is written (via a custom suggestions.system_prompt) to be a "go deeper with the specialist?" offer, shown only when the topic is code/implementation-heavy. 4. The frontend reads that suggestion and shows the offer card — same human-gated UX as today. 5. If the user clicks yes, the frontend calls Technical directly, passing the original question and Generic's answer as context — exactly the same call shape already in production today, unchanged. 6. Technical answers, shown as the specialist's response.

Generic and Technical never call each other directly at any point. The tool-call mechanism proven in the spike is not used anywhere in this flow.

Rationale

  • The app already has full information about when a handoff should be offered to the user (a button click) — no model-mediated tool call is needed to detect or trigger that.
  • Native suggestions are a documented platform feature with a real config schema (enabled, model, system_prompt, generation.max_count/max_words, context.include_tool_outputs) — this replaces both the old **HANDOFF:technical** sentinel AND the old **FOLLOWUP:...** follow-up-question sentinel with one mechanism, since both were the same kind of fragile prose-parsing problem.
  • Preserves the existing "Generic always answers first" UX exactly, because the suggestions call happens strictly after the main answer, per the platform's own documented sequencing — no pause risk.

Alternatives Considered

Option Why rejected
Tool-call pause/resume on Generic's front-door turn (the design walked back in this ADR) Breaks "always answer first" UX; solves a problem (model-driven cross-agent delegation) the app doesn't have, since the app already orchestrates both calls itself.
Tool-call fired only on a second, hidden LLM call dedicated to the yes/no offer decision Works mechanically, but adds a whole extra LLM call per turn just to reproduce what the native suggestions feature already does natively and more cheaply.
Keep the **HANDOFF:technical**/**FOLLOWUP:...** sentinels, just tighten the prompt wording Doesn't fix the structural fragility (regex over free-form prose); native suggestions is a real platform field, not a text convention.

Consequences

  • The two previously separate build jobs ("real tool-call handoff" and "native suggestions for follow-ups") collapse into one: wire up config.suggestions on both agents, remove both prose sentinels, keep the direct Technical call unchanged.
  • The spike's tool-call findings remain valid and are kept on file as a proven platform capability — useful the day a genuine model-driven, app-uninvolved cross-agent decision is actually needed, just not here.
  • Confirmed as a side question during this design pass: multi-turn continuity (user keeps asking follow-ups after a deep dive, with full memory of everything so far) needs no new platform capability — Agent Studio's /completions is stateless, so continuity is purely a frontend bookkeeping question (two accumulating histories, genericHistory/technicalHistory, with Technical's past deep-dive answers folded back into genericHistory so Generic stays aware of what's already been covered in depth). Exact shape of what context to send Technical on repeated deep dives (full transcript vs. summarized) is deferred to the Build stage.

Lesson for future sessions

Before reaching for a platform's agent-to-agent or tool-calling primitive, check whether the orchestration decision is actually being made by the model or by the app's own code in response to a deterministic trigger like a button click. If the app already knows when and what to call, no model-mediated tool call is needed — just call the second agent directly. This mistake was caught only after Arijit pushed back twice ("why will generic be paused?", "why is the second call to completions to generic?") and asked for a plain flow diagram, which is what actually exposed the conflation — worth reaching for a diagram earlier next time a multi-agent flow feels hard to explain in prose.