4.8 KiB
4.8 KiB
title, task, lineage_type, upstream_source, upstream_sha, imported_at, prompt_class, upstream_changes, author, validated
| title | task | lineage_type | upstream_source | upstream_sha | imported_at | prompt_class | upstream_changes | author | validated |
|---|---|---|---|---|---|---|---|---|---|
| Tool Creation Templates | import | https://github.com/mims-harvard/ToolUniverse/blob/e2520a96/skills/devtu-auto-discover-apis/references/tool-templates.md | e2520a96 | 2026-06-26 | prompt | accepted | upstream | false |
Tool Creation Templates
Python Tool Class Template
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
[
{
"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):
self.api_key = os.environ.get("API_KEY_NAME", "")
# JSON: "optional_api_keys": ["API_KEY_NAME"]
API Key (Required):
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)