Best Practices for Implementing Agent Handoff Workflows in Claude Plugins
Agent handoff workflows should validate requests early, explicitly state the subdomain and filters being passed, place URLs on isolated lines, and never include false boolean values to ensure transparent, error-free context transfers between skills.
The anthropics/claude-plugins-community repository establishes concrete patterns for implementing agent handoff workflows that minimize user friction while preserving conversational context. These patterns appear throughout the Tres Finance plugin skills and the generic agent-handoff plugin definition, providing a canonical reference for routing control between skills, UIs, and external services.
Validate Requests Before Initiating Handoffs
Early validation prevents unnecessary API calls and keeps conversations focused. According to the ledger-link skill specification in tres-finance-plugin/skills/tres-ledger-link/SKILL.md (lines 55-59), you must confirm scope, required filters, and optional parameters before proceeding with any handoff. This validation step acts as a gatekeeper that ensures only well-formed requests trigger URL generation or skill transitions.
Structure Handoff Messages for Maximum Clarity
Clean handoff messages reduce copy-paste errors and enable user sanity checks. The following rules from tres-finance-plugin/skills/tres-ledger-link/SKILL.md govern message formatting:
- State the subdomain and filters explicitly – Users must see exactly which context is being passed, as documented in lines 14-15.
- Place the URL on its own line – A clean, copy-ready link reduces errors and simplifies downstream parsing (lines 55-66).
- Include only requested filters – Omit default or false values to prevent target UI misinterpretation (lines 10-12).
- Avoid duplicate keys – Combine multiple values with commas rather than repeating query keys (lines 11-12).
- Never append
=falseto boolean filters – Omitting the flag entirely is the canonical way to express false values (lines 10-11).
Generate URLs Programmatically
Never hand-craft URLs outside the skill logic. The ledger-link skill mandates that all URL generation rely on the skill's internal logic to guarantee correct query-parameter encoding (lines 8-9). This prevents malformed URLs and ensures consistent encoding of special characters across different subdomains.
Route to Appropriate Skills
When a request falls outside the current skill's scope, explicitly hand off to a more suitable skill. In tres-finance-plugin/skills/tres-rollup-rules/SKILL.md (lines 46-52), requests requiring deeper inspection are routed to tres-rollup-review via an explicit "hand off" instruction. This pattern ensures that specialized logic always handles the specific domain it was designed for.
Implement the Three-Stage Workflow
The generic agent-handoff plugin definition in .claude-plugin/marketplace.json (lines 529-533) standardizes a three-stage workflow: plan → execute → verify. This structure ensures consistency across all plugins in the ecosystem. Before responding, the skill must run a "Step 4 checklist" validating filters, URL format, and message structure (as required in tres-finance-plugin/skills/tres-ledger-link/SKILL.md, lines 57-64).
Code Implementation Examples
Constructing Filter-Safe Handoff Messages
The following Python implementation follows the ledger-link skill requirements: it omits false booleans, prevents duplicate keys, and isolates the URL on its own line.
import urllib.parse
def build_handoff(subdomain: str, filters: dict) -> str:
"""
Returns a hand-off string that:
• States the subdomain and the filters used
• Places the URL on its own line
"""
# 1. Encode parameters – omit any key whose value is False or None
encoded = "&".join(
f"{k}={urllib.parse.quote(str(v))}"
for k, v in filters.items()
if v not in (False, None, "")
)
url = f"https://{subdomain}.tres.finance/ledger?{encoded}"
# 2. Human-readable description
filter_desc = ", ".join(f"{k}={v}" for k, v in filters.items() if v)
return (
f"Built for org `{subdomain}`: filters are {filter_desc}.\n"
f"{url}"
)
Declarative Skill Routing
When a request requires capabilities from another skill, use a declarative handoff structure. This YAML fragment mirrors the routing pattern found in tres-finance-plugin/skills/tres-rollup-rules/SKILL.md (lines 46-52):
name: tres-rollup-rules
description: Create and manage roll-up rules for transaction data.
steps:
- name: "Routing"
actions:
- type: "handoff"
target: "tres-rollup-review"
reason: "User asked to see what a specific rule would match"
Pre-Handoff Validation Checklist
Implement the required Step 4 checklist before emitting any handoff message. This shell script validates the constraints documented in tres-finance-plugin/skills/tres-ledger-link/SKILL.md (lines 57-64):
# Step 4 checklist (simplified)
if [[ -z "$SUBDOMAIN" ]]; then echo "Missing subdomain"; exit 1; fi
if [[ "${#FILTERS[@]}" -eq 0 ]]; then echo "No filters supplied"; exit 1; fi
# Ensure no duplicate keys
declare -A seen
for k in "${!FILTERS[@]}"; do
[[ -n "${seen[$k]}" ]] && { echo "Duplicate key: $k"; exit 1; }
seen[$k]=1
done
# If all checks pass → hand off
hand_off_message=$(python -c "import handoff; print(handoff.build_handoff('$SUBDOMAIN', $FILTERS))")
echo "$hand_off_message"
Summary
- Validate early to prevent unnecessary API calls and maintain conversation focus.
- Use programmatic URL generation rather than string concatenation to ensure proper encoding.
- Omit false boolean values entirely rather than setting them to
=false. - Place URLs on isolated lines to facilitate copying and parsing.
- Route to specialized skills when requests fall outside the current scope.
- Run the Step 4 checklist before finalizing any handoff message.
Frequently Asked Questions
What is an agent handoff workflow in Claude plugins?
An agent handoff workflow is a structured pattern for transferring control between skills, UIs, or external services within the Claude plugin ecosystem. According to the agent-handoff entry in .claude-plugin/marketplace.json (lines 529-533), it follows a three-stage process of planning, executing, and verifying the transfer to preserve context and minimize user friction.
Why should boolean filters omit =false in handoff URLs?
Omitting the flag entirely is the canonical way to express "false" in the Tres Finance plugin specifications. Including =false adds noise to the URL and can cause target UIs to misinterpret the intent, as documented in tres-finance-plugin/skills/tres-ledger-link/SKILL.md (lines 10-11).
How do I route a request to a different skill?
Emit an explicit handoff instruction specifying the target skill name and reason. The tres-rollup-rules skill demonstrates this pattern by routing detailed rule reviews to tres-rollup-review via a declarative handoff action (see tres-finance-plugin/skills/tres-rollup-rules/SKILL.md, lines 46-52).
Where is the agent handoff workflow documented in the repository?
The primary documentation resides in three locations: the ledger-link skill (tres-finance-plugin/skills/tres-ledger-link/SKILL.md) defines concrete formatting rules, the rollup-rules skill (tres-finance-plugin/skills/tres-rollup-rules/SKILL.md) shows inter-skill routing, and the marketplace configuration (.claude-plugin/marketplace.json, lines 529-533) documents the generic three-stage workflow structure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →