@@ -2136,6 +2136,175 @@ def handle_list_contexts(
21362136 }
21372137
21382138
2139+ # Pattern 3: Tool Unloading
2140+ # Define workflow stages and their tool sets
2141+ WORKFLOW_STAGES = {
2142+ "setup" : {
2143+ "description" : "Create collections, graphs, and schemas" ,
2144+ "tools" : [
2145+ ARANGO_CREATE_COLLECTION , ARANGO_CREATE_GRAPH , ARANGO_CREATE_SCHEMA ,
2146+ ARANGO_ADD_VERTEX_COLLECTION , ARANGO_ADD_EDGE_DEFINITION
2147+ ]
2148+ },
2149+ "data_loading" : {
2150+ "description" : "Bulk insert and validate data" ,
2151+ "tools" : [
2152+ ARANGO_BULK_INSERT , ARANGO_INSERT_WITH_VALIDATION ,
2153+ ARANGO_VALIDATE_REFERENCES , ARANGO_INSERT
2154+ ]
2155+ },
2156+ "analysis" : {
2157+ "description" : "Query, traverse, and analyze data" ,
2158+ "tools" : [
2159+ ARANGO_QUERY , ARANGO_TRAVERSE , ARANGO_SHORTEST_PATH ,
2160+ ARANGO_EXPLAIN_QUERY , ARANGO_QUERY_PROFILE , ARANGO_GRAPH_STATISTICS
2161+ ]
2162+ },
2163+ "cleanup" : {
2164+ "description" : "Backup and finalize workflow" ,
2165+ "tools" : [
2166+ ARANGO_BACKUP , ARANGO_BACKUP_GRAPH , ARANGO_BACKUP_NAMED_GRAPHS ,
2167+ ARANGO_VALIDATE_GRAPH_INTEGRITY
2168+ ]
2169+ }
2170+ }
2171+
2172+ # Global state for tool usage tracking (in production, this would be per-session)
2173+ _CURRENT_STAGE = "setup"
2174+ _TOOL_USAGE_STATS = {}
2175+
2176+
2177+ def _track_tool_usage (tool_name : str ):
2178+ """Track tool usage for unloading decisions."""
2179+ if tool_name not in _TOOL_USAGE_STATS :
2180+ _TOOL_USAGE_STATS [tool_name ] = {
2181+ "first_used" : datetime .now ().isoformat (),
2182+ "last_used" : datetime .now ().isoformat (),
2183+ "use_count" : 0 ,
2184+ "stage" : _CURRENT_STAGE
2185+ }
2186+
2187+ _TOOL_USAGE_STATS [tool_name ]["last_used" ] = datetime .now ().isoformat ()
2188+ _TOOL_USAGE_STATS [tool_name ]["use_count" ] += 1
2189+
2190+
2191+ @handle_errors
2192+ @register_tool (
2193+ name = ARANGO_ADVANCE_WORKFLOW_STAGE ,
2194+ description = "Advance to the next workflow stage, automatically unloading tools from previous stage and loading tools for new stage. Enables Tool Unloading pattern." ,
2195+ model = AdvanceWorkflowStageArgs ,
2196+ )
2197+ def handle_advance_workflow_stage (
2198+ db : StandardDatabase , args : Dict [str , Any ]
2199+ ) -> Dict [str , Any ]:
2200+ """Advance to a new workflow stage with automatic tool unloading.
2201+
2202+ This tool enables the Tool Unloading pattern by automatically removing
2203+ tools from completed stages and loading tools for the new stage.
2204+
2205+ Args:
2206+ db: ArangoDB database instance (not used, but required for handler signature)
2207+ args: Validated AdvanceWorkflowStageArgs containing target stage
2208+
2209+ Returns:
2210+ Dictionary with stage transition details
2211+ """
2212+ global _CURRENT_STAGE
2213+
2214+ new_stage = args ["stage" ]
2215+ old_stage = _CURRENT_STAGE
2216+
2217+ if new_stage not in WORKFLOW_STAGES :
2218+ return {
2219+ "error" : f"Unknown stage: { new_stage } " ,
2220+ "available_stages" : list (WORKFLOW_STAGES .keys ())
2221+ }
2222+
2223+ old_tools = set (WORKFLOW_STAGES [old_stage ]["tools" ])
2224+ new_tools = set (WORKFLOW_STAGES [new_stage ]["tools" ])
2225+
2226+ tools_unloaded = list (old_tools - new_tools )
2227+ tools_loaded = list (new_tools - old_tools )
2228+
2229+ _CURRENT_STAGE = new_stage
2230+
2231+ return {
2232+ "from_stage" : old_stage ,
2233+ "to_stage" : new_stage ,
2234+ "description" : WORKFLOW_STAGES [new_stage ]["description" ],
2235+ "tools_unloaded" : tools_unloaded ,
2236+ "tools_loaded" : tools_loaded ,
2237+ "active_tools" : list (new_tools ),
2238+ "total_active_tools" : len (new_tools )
2239+ }
2240+
2241+
2242+ @handle_errors
2243+ @register_tool (
2244+ name = ARANGO_GET_TOOL_USAGE_STATS ,
2245+ description = "Get usage statistics for all tools, including use counts and last used timestamps. Useful for understanding tool usage patterns." ,
2246+ model = GetToolUsageStatsArgs ,
2247+ )
2248+ def handle_get_tool_usage_stats (
2249+ db : StandardDatabase , args : Optional [Dict [str , Any ]] = None
2250+ ) -> Dict [str , Any ]:
2251+ """Get tool usage statistics.
2252+
2253+ Args:
2254+ db: ArangoDB database instance (not used, but required for handler signature)
2255+ args: No arguments required
2256+
2257+ Returns:
2258+ Dictionary with tool usage statistics
2259+ """
2260+ global _TOOL_USAGE_STATS , _CURRENT_STAGE
2261+
2262+ return {
2263+ "current_stage" : _CURRENT_STAGE ,
2264+ "tool_usage" : _TOOL_USAGE_STATS ,
2265+ "total_tools_used" : len (_TOOL_USAGE_STATS ),
2266+ "active_stage_tools" : WORKFLOW_STAGES [_CURRENT_STAGE ]["tools" ]
2267+ }
2268+
2269+
2270+ @handle_errors
2271+ @register_tool (
2272+ name = ARANGO_UNLOAD_TOOLS ,
2273+ description = "Manually unload specific tools from the active context. Useful for fine-grained control over tool lifecycle." ,
2274+ model = UnloadToolsArgs ,
2275+ )
2276+ def handle_unload_tools (
2277+ db : StandardDatabase , args : Dict [str , Any ]
2278+ ) -> Dict [str , Any ]:
2279+ """Manually unload specific tools.
2280+
2281+ Args:
2282+ db: ArangoDB database instance (not used, but required for handler signature)
2283+ args: Validated UnloadToolsArgs containing tool names to unload
2284+
2285+ Returns:
2286+ Dictionary with unload results
2287+ """
2288+ tool_names = args ["tool_names" ]
2289+
2290+ # In a real implementation, this would remove tools from the active context
2291+ # For now, we just track which tools would be unloaded
2292+ unloaded = []
2293+ not_found = []
2294+
2295+ for tool_name in tool_names :
2296+ if tool_name in TOOL_REGISTRY :
2297+ unloaded .append (tool_name )
2298+ else :
2299+ not_found .append (tool_name )
2300+
2301+ return {
2302+ "unloaded" : unloaded ,
2303+ "not_found" : not_found ,
2304+ "total_unloaded" : len (unloaded )
2305+ }
2306+
2307+
21392308# Register aliases for backward compatibility
21402309from .tool_registry import ToolRegistration
21412310
0 commit comments