add-blocking-tool

Implements blocking agent tools that pause execution until the user or frontend replies.

10|1|Updated Jul 7, 2026
One-click install
npx skills add https://github.com/catalystctl/catcode --skill add-blocking-tool-catalystctl
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: add-blocking-tool
Source: https://github.com/catalystctl/catcode/tree/main/.catalyst-code/skills/add-blocking-tool
Command: npx skills add https://github.com/catalystctl/catcode --skill add-blocking-tool-catalystctl

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Adding a tool that must wait for a human answer (approval, intercom, ask) before the model can continue requires a full round-trip pattern: an event out, a command back, and a Notify to wake the awaiting future. Without guidance, developers wire only half the pattern and the tool silently returns an error string instead of blocking, or the session wedges after a restart. ## Core Features & Use Cases - Five-piece blocking pattern: Pending struct with State map, event/command protocol pair, async request function with tokio::select on notify vs cancel, command handler, and tool-loop dispatch in run_turn. - Frontend wiring for TUI and web: Priority key handlers and modal rendering in the TUI, CoreEvent/CoreCommand union cases and reducer state in the web app, with field-name matching rules to avoid silent hangs. - Restart-resume correctness: Detects trailing unanswered tool_calls after a core restart and re-presents the prompt or synthesizes a result so sessions never wedge. - Use Case: You want to add a new confirmation tool that asks the user before deleting files. Follow the pattern to add the pending state, emit the request event, handle the reply command, and wire the TUI and web prompts. ## Quick Start Add a new blocking tool to the core that asks the user for confirmation and waits for their reply before continuing the agent loop.

Frequently Asked Questions about add-blocking-tool

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I add a tool that waits for user input in an agent loop?

Create a Pending struct with a Notify and result Mutex, store it in a State map keyed by request_id, emit a request event, and await the notify in a tokio::select against cancellation. A command handler sets the result and calls notify_one to resume the awaiting future.

What is the difference between a blocking tool and a regular core tool?

Regular tools are sync or async fire-and-forget and return their result immediately. Blocking tools need a round-trip: an event out to the frontend, a command back with the answer, and a Notify to wake the awaiting future before the model continues.

Why does my blocking tool return an error instead of waiting?

The tool is only wired in execute() without the sentinel and async dispatch in the tool loop, so its error string becomes the tool_result and the model thinks it ran. Wire both the sentinel and the request function in the run_turn dispatch chain.

Why does the prompt hang forever after wiring the web frontend?

The wire field names likely mismatch between core and frontend, such as the core emitting id while the web reads request_id. Ensure the event and reply command use identical field names on both sides.

What happens to a blocking tool if the core restarts mid-prompt?

Pending state lives only in memory, but the assistant tool_call is persisted, so a restart leaves an orphaned tool_call that wedges the session. On load, detect the trailing unanswered tool_call and re-present the prompt or synthesize a result.

Can subagents use blocking tools to ask the user questions?

Keep blocking tools orchestrator-only by not adding them to subagent::all_tool_names(). Subagents that need human input use contact_supervisor, which is a blocking tool scoped to subagents.