{"id":31828312,"url":"https://github.com/unclecode/tool4ai","last_synced_at":"2025-10-11T19:28:25.219Z","repository":{"id":253247521,"uuid":"842927850","full_name":"unclecode/tool4ai","owner":"unclecode","description":"Tool4AI: A model agnostic, LLM friendly router for tool/function call","archived":false,"fork":false,"pushed_at":"2024-08-19T07:32:38.000Z","size":205,"stargazers_count":18,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-06T10:57:50.389Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unclecode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-15T12:10:17.000Z","updated_at":"2025-10-06T09:29:30.000Z","dependencies_parsed_at":"2024-08-19T05:29:22.035Z","dependency_job_id":"0c3330cd-7b99-4152-ab67-eabb4aa93d59","html_url":"https://github.com/unclecode/tool4ai","commit_stats":null,"previous_names":["unclecode/tool4ai"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/unclecode/tool4ai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unclecode%2Ftool4ai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unclecode%2Ftool4ai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unclecode%2Ftool4ai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unclecode%2Ftool4ai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unclecode","download_url":"https://codeload.github.com/unclecode/tool4ai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unclecode%2Ftool4ai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279008422,"owners_count":26084460,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-11T19:28:16.711Z","updated_at":"2025-10-11T19:28:25.213Z","avatar_url":"https://github.com/unclecode.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tool4AI\n\n**Tool4AI** is a powerful library for **building and executing complex dependency graphs for function calling and tool routing in AI applications**. It excels at breaking down intricate queries, creating optimized execution plans, and managing dynamic scenarios with ease.\n\n\n## Key Features\n\n- **Intelligent Query Decomposition**: Breaks down complex, multi-step queries into atomic sub-queries.\n- **Optimized Execution Graph**: Generates and visualizes dependency-aware execution plans for maximum efficiency.\n- **Parallel Execution**: Executes independent tasks concurrently for optimal performance.\n- **Dynamic Human Interaction**: Supports mid-execution pausing, human feedback, and seamless resumption.\n- **Persistent State Management**: Saves and resumes execution states using JSON or LMDB storage.\n- **Model Agnostic**: Works effectively with various language models, from small to large LLMs.\n\n## Building the Execution Graph\n\nTool4AI's primary strength lies in its ability to construct and visualize complex execution graphs. Here's how to get started:\n\n```python\nfrom tool4ai import Router, Toolkit, Tool\nfrom tool4ai.toolmakers import OpenAIToolMaker\nfrom tool4ai.graph import ToolDependencyGraph\n\n# Assuming you already have your functions and their JSON schemas defined\n# Define your tool functions\nasync def retrieve_favorites(args):\n    # Implementation\n    pass\n\nasync def recommend_similar_movies(args):\n    # Implementation\n    pass\n\n# ... (other tool functions)\n\ntool_functions = {\n    \"retrieve_favorites\": retrieve_favorites,\n    \"recommend_similar_movies\": recommend_similar_movies,\n    # ... (other tool functions)\n}\n\n# Define your toolkit\ntoolkit = Toolkit()\ntoolkit.add_tool(Tool(name=\"retrieve_favorites\", schema=..., description=\"Retrieve movies from a favorite list\", f= tool_functions[\"retrieve_favorites\"]))\ntoolkit.add_tool(Tool(name=\"recommend_similar_movies\", schema=..., description=\"Recommend similar movies\", f= tool_functions[\"recommend_similar_movies\"]))\ntoolkit.add_tool(Tool(name=\"create_favorite_list\", schema=..., description=\"Create a new favorite list\", f= ...))\ntoolkit.add_tool(Tool(name=\"add_to_favorite\", schema=..., description=\"Add movies to a favorite list\", f=...))\ntoolkit.add_tool(Tool(name=\"direct_ask\", schema=..., description=\"Get direct information about movies\", f=...))\n\n# Create a router\ntool_maker = OpenAIToolMaker()\nrouter = Router(toolkit, tool_maker)\n\n# Process a complex query\nquery = \"\"\"Find a horror movie from my 'Scary Nights' list, recommend similar movies, and add them to a new list called 'More Nightmares'. I can't wait to dive into these! Finally, let me know if any of these movies are based on true stories\"\"\"\n\n# Voila! The execution graph is ready\ngraph : ToolDependencyGraph = router.route(query)\n\n# Visualize the execution graph\ngraph.visualize(\"execution_graph\")\n```\n\nThis will generate an execution graph similar to the one shown below. The graph represents the decomposition of the complex query into manageable sub-queries and their dependencies.\n\n### Subquery Node Structure\n\n```py\nclass SubQuery(BaseModel):\n    index: int = 0 # index of the sub-query\n    sub_query: str # original sub-query, exactly as it appears in the input\n    task: str # rewritten task for the sub-query\n    tool: Optional[str] = None # detected tool name for the sub-query\n    dependent_on: int = -1 # index of the sub-query this sub-query is dependent on if any\n    dependency_attr: Optional[str] = \"\" # attribute of the dependent sub-query this sub-query depends on if any\n    arguments: Optional[Dict[str, Any]] = Field(default_factory=dict) # arguments for the tool function, this is populated during execution\n    result: Optional[str] = None # result of the sub-query, this is populated during execution\n    status: Optional[str] = \"pending\" # status of the sub-query, this is updated during execution\n    issue: Optional[str] = None # issue encountered during execution\n    actionable: Optional[bool] = True # whether the sub-query is actionable\n    is_orphan: Optional[bool] = False # whether the sub-query is an orphan, refer to the documentation for more details\n\nclass SubQueryResponse(BaseModel):\n    sub_queries: List[SubQuery] # list of sub-queriesor \n```\n\n### Graph Structure\n\nThe resulting graph structure can be serialized to JSON for storage or visualization:\n\n```json\n{\n  \"sub_queries\": [\n    {\n      \"index\": 0,\n      \"sub_query\": \"Find a horror movie from my 'Scary Nights' list.\",\n      \"task\": \"Retrieve a horror movie from the 'Scary Nights' list.\",\n      \"tool\": \"retrieve_favorites\",\n      \"dependent_on\": -1,\n      \"dependency_attr\": \"\"\n    },\n    {\n      \"index\": 1,\n      \"sub_query\": \"Recommend similar movies.\",\n      \"task\": \"Recommend movies similar to the selected horror movie from the 'Scary Nights' list.\",\n      \"tool\": \"recommend_similar_movies\",\n      \"dependent_on\": 0,\n      \"dependency_attr\": \"movie_title\"\n    },\n    {\n      \"index\": 2,\n      \"sub_query\": \"Create a new list called 'More Nightmares'.\",\n      \"task\": \"Create a new favorite list named 'More Nightmares'.\",\n      \"tool\": \"create_favorite_list\",\n      \"dependent_on\": -1,\n      \"dependency_attr\": \"\"\n    },\n    {\n      \"index\": 3,\n      \"sub_query\": \"Add them to a new list called 'More Nightmares'.\",\n      \"task\": \"Add the recommended movies to the 'More Nightmares' list.\",\n      \"tool\": \"add_to_favorite\",\n      \"dependent_on\": 1,\n      \"dependency_attr\": \"movies\"\n    },\n    {\n      \"index\": 4,\n      \"sub_query\": \"Let me know if any of these movies are based on true stories.\",\n      \"task\": \"Determine if any of the recommended movies are based on true stories.\",\n      \"tool\": \"direct_ask\",\n      \"dependent_on\": 1,\n      \"dependency_attr\": \"movies\"\n    },\n    {\n      \"index\": 5,\n      \"sub_query\": \"I can't wait to dive into these!\",\n      \"task\": \"Acknowledge user's excitement about diving into the new list of movies.\",\n      \"tool\": \"\",\n      \"dependent_on\": -1,\n      \"dependency_attr\": \"\"\n    }\n  ]\n}\n```\n\n![Tool4AI Execution Graph](docs/_assets/graph.png)\n\nThis structure allows for clear visualization of task dependencies and efficient execution planning.\n\n## Executing the Graph\n\nOnce the execution graph is built, Tool4AI provides powerful capabilities to execute it:\n\n```python\n# Execute the graph\nresult : ExecutionResult = await graph.execute(toolkit, context, tool_maker)\n\nprint(result.status)\nprint(result.message)\n```\n\nThe result structure is as follows:\n\n```py\nclass ExecutionStatus(str, Enum):\n    SUCCESS = \"success\"\n    FAILED = \"failed\"\n    PARTIAL = \"partial\"\n    HUMAN = \"human\"\n    ERROR = \"error\"\n    PENDING = \"pending\"\n    NEW_DISCUSSION = \"new_discussion\"\n\nclass ExecutionResult(BaseModel):\n    model_config = ConfigDict(extra='ignore')\n    status: ExecutionStatus\n    message: str\n    memory: List[Dict[str, Any]]\n    sub_queries: List[SubQuery]\n    error_info: Optional[Dict[str, Any]] = None\n```\n\n### Parallel Execution\n\nTool4AI optimizes execution by running independent tasks in parallel. The `get_execution_order()` function divides the graph into layers, where tasks within each layer can be executed concurrently:\n\n```python\nexecution_order = graph.get_execution_order()\nfor layer in execution_order:\n    # Tasks in this layer can be executed in parallel\n    pass\n```\n\n### Human Interaction and Execution Resumption\n\nTool4AI supports dynamic human interaction during execution. Here's an example of how it handles human input and resumes execution. Imagine a user asks the AI assistant to search for horror movies from 2020, but no data is available. The execution pipeline will halt at the related node or subquery with the status `ExecutionStatus.HUMAN`, waiting for user input to proceed. Once the user provides feedback, the execution will resume seamlessly.\n\n```python\n# Initial execution\nresult = await graph.execute(tool_functions, toolkit.to_json_schema(), context, tool_maker)\n\nif result.status == ExecutionStatus.HUMAN:\n    # Simulate human input\n    user_input = \"Yes, please search for comedy movies from 2021 instead.\"\n    result = await graph.resume_execution(user_input, tool_functions, toolkit.to_json_schema(), context, tool_maker)\n\nassert result.status == ExecutionStatus.SUCCESS\n```\n\nThis allows for seamless integration of human feedback into the execution process.\n\n## Persistent State Management\n\nTool4AI can save and resume execution states, allowing for long-running or interruptible processes:\n\n```python\n# Save state\nawait graph.save()\n\n# Load state\nloaded_graph = await ToolDependencyGraph.load(graph.run_id)\n```\n\n## Model Agnostic Design\n\nWhile Tool4AI shines with large language models, it's designed to work effectively even with smaller models that have limited function-calling capabilities.\n\n## Installation\n\nInstall Tool4AI using pip from github:\n\n```bash\npip install git+https://github.com/unclecode/tool4ai.git\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for more details.\n\n## License\n\nTool4AI is released under the [MIT License](LICENSE).\n\n## Support\n\nFor support, please open an issue on the GitHub repository or contact [unclecode@kidocode.com].\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funclecode%2Ftool4ai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funclecode%2Ftool4ai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funclecode%2Ftool4ai/lists"}