153 lines
4.8 KiB
Markdown
153 lines
4.8 KiB
Markdown
---
|
|
title: "Tool Creation Templates"
|
|
task: ""
|
|
lineage_type: import
|
|
upstream_source: https://github.com/mims-harvard/ToolUniverse/blob/e2520a96/skills/devtu-auto-discover-apis/references/tool-templates.md
|
|
upstream_sha: e2520a96
|
|
imported_at: 2026-06-26
|
|
prompt_class: prompt
|
|
upstream_changes: accepted
|
|
author: upstream
|
|
validated: false
|
|
---
|
|
|
|
# Tool Creation Templates
|
|
|
|
## Python Tool Class Template
|
|
|
|
```python
|
|
from typing import Dict, Any
|
|
from tooluniverse.tool import BaseTool
|
|
from tooluniverse.tool_utils import register_tool
|
|
import requests
|
|
import os
|
|
|
|
@register_tool("[APIName]Tool")
|
|
class [APIName]Tool(BaseTool):
|
|
"""Tool for [API Name] - [brief description]."""
|
|
|
|
BASE_URL = "[API base URL]"
|
|
|
|
def __init__(self, tool_config):
|
|
super().__init__(tool_config)
|
|
self.parameter = tool_config.get("parameter", {})
|
|
self.required = self.parameter.get("required", [])
|
|
self.api_key = os.environ.get("[API_KEY_NAME]", "")
|
|
|
|
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
operation = arguments.get("operation")
|
|
if not operation:
|
|
return {"status": "error", "error": "Missing required parameter: operation"}
|
|
|
|
if operation == "operation1":
|
|
return self._operation1(arguments)
|
|
else:
|
|
return {"status": "error", "error": f"Unknown operation: {operation}"}
|
|
|
|
def _operation1(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
param1 = arguments.get("param1")
|
|
if not param1:
|
|
return {"status": "error", "error": "Missing required parameter: param1"}
|
|
|
|
try:
|
|
headers = {}
|
|
if self.api_key:
|
|
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
|
|
response = requests.get(
|
|
f"{self.BASE_URL}/endpoint",
|
|
params={"param1": param1},
|
|
headers=headers,
|
|
timeout=30
|
|
)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
|
|
return {
|
|
"status": "success",
|
|
"data": data.get("results", []),
|
|
"metadata": {"total": data.get("total", 0), "source": "[API Name]"}
|
|
}
|
|
except requests.exceptions.Timeout:
|
|
return {"status": "error", "error": "API timeout after 30 seconds"}
|
|
except requests.exceptions.HTTPError as e:
|
|
return {"status": "error", "error": f"HTTP {e.response.status_code}: {e.response.text[:200]}"}
|
|
except Exception as e:
|
|
return {"status": "error", "error": f"Unexpected error: {str(e)}"}
|
|
```
|
|
|
|
## JSON Configuration Template
|
|
|
|
```json
|
|
[
|
|
{
|
|
"name": "[APIName]_operation1",
|
|
"class": "[APIName]Tool",
|
|
"description": "[What it does]. Returns [format]. [Input]. Example: [usage]. [Notes].",
|
|
"parameter": {
|
|
"type": "object",
|
|
"required": ["operation", "param1"],
|
|
"properties": {
|
|
"operation": {"const": "operation1", "description": "Operation identifier (fixed)"},
|
|
"param1": {"type": "string", "description": "Description with format/constraints"}
|
|
}
|
|
},
|
|
"return_schema": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"data": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}}}},
|
|
"metadata": {"type": "object", "properties": {"total": {"type": "integer"}, "source": {"type": "string"}}}
|
|
}
|
|
},
|
|
{"type": "object", "properties": {"error": {"type": "string"}}, "required": ["error"]}
|
|
]
|
|
},
|
|
"test_examples": [{"operation": "operation1", "param1": "real_value_from_api_docs"}]
|
|
}
|
|
]
|
|
```
|
|
|
|
## Authentication Patterns
|
|
|
|
**Public**: No special handling.
|
|
|
|
**API Key (Optional)**:
|
|
```python
|
|
self.api_key = os.environ.get("API_KEY_NAME", "")
|
|
# JSON: "optional_api_keys": ["API_KEY_NAME"]
|
|
```
|
|
|
|
**API Key (Required)**:
|
|
```python
|
|
self.api_key = os.environ.get("API_KEY_NAME")
|
|
if not self.api_key:
|
|
raise ValueError("API_KEY_NAME environment variable required")
|
|
# JSON: "required_api_keys": ["API_KEY_NAME"]
|
|
```
|
|
|
|
## Advanced Patterns
|
|
|
|
### Async Polling (job-based APIs)
|
|
Submit → poll → retrieve. Max 60 attempts, 2s interval = 2min timeout.
|
|
|
|
### SOAP APIs
|
|
Require `operation` parameter (e.g., `"operation": "search_genes"`).
|
|
|
|
### Pagination
|
|
Fetch pages until empty or partial page. Track total_pages and total_items.
|
|
|
|
## File Naming
|
|
- Python: `src/tooluniverse/[api_name]_tool.py`
|
|
- JSON: `src/tooluniverse/data/[api_name]_tools.json`
|
|
- Register in: `src/tooluniverse/default_config.py`
|
|
|
|
## Critical Requirements
|
|
- return_schema MUST have oneOf (success + error)
|
|
- test_examples MUST use real IDs (NO placeholders)
|
|
- Tool name <= 55 characters
|
|
- Description 150-250 chars
|
|
- NEVER raise exceptions in run() — return error dict
|
|
- Set timeout on all HTTP requests (30s)
|