refactor(api/nlq): convert UI actions from marker system to tool definitions#307
Merged
SimplicityGuy merged 2 commits intomainfrom Apr 15, 2026
Merged
refactor(api/nlq): convert UI actions from marker system to tool definitions#307SimplicityGuy merged 2 commits intomainfrom
SimplicityGuy merged 2 commits intomainfrom
Conversation
…nitions Previously the NLQ engine emitted UI mutation actions via a markdown HTML comment marker (<!--actions:[...]-->) appended to the LLM's response text. This design was load-bearing on LLM discipline and failed on complex queries (e.g. "what's the biggest Trance label") — users got perfect answers but zero actions fired because the marker was missing or malformed. Each of the ten action types is now a real Anthropic tool definition: seed_graph, highlight_path, focus_node, filter_graph, ui_find_path, show_credits, switch_pane, open_insight_tile, set_trend_range, and suggest_followups. The tool loop validates each invocation via pydantic and records the resulting Action into a per-request list that populates NLQResult.actions. Client wire format is unchanged. The ui_find_path tool records actions as client type "find_path" — the tool name is distinct because the data tool find_path already owns that name in the Anthropic tool namespace. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
PR #307 introduced action tools with unprefixed names (seed_graph, switch_pane, etc.) and resolved the find_path collision by prefixing only that one as ui_find_path. Review feedback: prefer a consistent ui_ prefix on all 10 action tools for visual clarity in the model's tool list. Client wire types (NLQResult.actions[i].type) stay unprefixed so the frontend applier contract is unchanged — _ACTION_TOOL_TO_TYPE maps each ui_* tool name to its wire type. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
Contributor
Contributor
Contributor
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
The marker system was load-bearing on LLM discipline and failed on complex queries in practice. Users asked things like "what's the biggest Trance label" and got a perfect markdown answer but zero actions fired — the model forgot the marker, or the regex silently dropped malformed JSON. Tool-use makes the action emission a structural contract: the model sees each action as a first-class tool with a JSON schema, and the engine assembles `NLQResult.actions` from the actual tool invocations instead of scraping text.
Contract preservation
Test plan
🤖 Generated with Claude Code