Guides
Tool Development Guide
How to develop tools in Python/TypeScript
Basic Structure
A Tool consists of Input, Output, and a run function.
Python
Define schemas using Pydantic's BaseModel.
from pydantic import BaseModel, Field
class Input(BaseModel):
url: str = Field(description="URL to fetch")
class Output(BaseModel):
title: str
content: str
def run(input: Input) -> Output:
# Implement your logic
return Output(title="...", content="...")TypeScript
Define schemas using Zod.
import { z } from "zod";
export const input = z.object({
url: z.string().describe("URL to fetch"),
});
export const output = z.object({
title: z.string(),
content: z.string(),
});
export async function run(data: z.infer<typeof input>) {
// Implement your logic
return { title: "...", content: "..." };
}External Libraries
Add packages in the ToolSet settings to import them in your code.
import requests # Add "requests" in package settings
from bs4 import BeautifulSoup # Add "beautifulsoup4"
def run(input: Input) -> Output:
html = requests.get(input.url).text
soup = BeautifulSoup(html, "html.parser")
return Output(title=soup.title.string)Version specification is also supported (e.g., requests==2.31.0).
Environment Variables
Pass sensitive information like API keys via environment variables. Register them in the ToolSet settings.
import os
def run(input: Input) -> Output:
api_key = os.environ["SLACK_API_KEY"]
# Use api_key...export async function run(data: z.infer<typeof input>) {
const apiKey = process.env.SLACK_API_KEY;
// Use apiKey...
}Error Handling
Throwing an exception will record the error information.
def run(input: Input) -> Output:
if not input.url.startswith("https://"):
raise ValueError("URL must start with https://")
# ...Practical Examples
Slack Notification
import os
import requests
from pydantic import BaseModel, Field
class Input(BaseModel):
channel: str = Field(description="Target channel")
message: str = Field(description="Message body")
class Output(BaseModel):
success: bool
ts: str = Field(description="Message timestamp")
def run(input: Input) -> Output:
response = requests.post(
"https://slack.com/api/chat.postMessage",
headers={"Authorization": f"Bearer {os.environ['SLACK_BOT_TOKEN']}"},
json={"channel": input.channel, "text": input.message},
)
data = response.json()
if not data["ok"]:
raise Exception(data["error"])
return Output(success=True, ts=data["ts"])Web Page Fetching
import requests
from bs4 import BeautifulSoup
from pydantic import BaseModel
class Input(BaseModel):
url: str
class Output(BaseModel):
title: str
description: str
text: str
def run(input: Input) -> Output:
html = requests.get(input.url).text
soup = BeautifulSoup(html, "html.parser")
title = soup.title.string if soup.title else ""
desc_tag = soup.find("meta", {"name": "description"})
description = desc_tag["content"] if desc_tag else ""
text = soup.get_text()[:2000]
return Output(title=title, description=description, text=text)External API Call
import os
import requests
from pydantic import BaseModel
class Input(BaseModel):
query: str
class Output(BaseModel):
results: list[dict]
def run(input: Input) -> Output:
response = requests.get(
"https://api.example.com/search",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
params={"q": input.query},
)
response.raise_for_status()
return Output(results=response.json()["results"])Schema Best Practices
Add Descriptions
Descriptions help AI choose the right tool.
class Input(BaseModel):
query: str = Field(description="Search keyword")
limit: int = Field(default=10, description="Max results (1-100)")export const input = z.object({
query: z.string().describe("Search keyword"),
limit: z.number().default(10).describe("Max results (1-100)"),
});Optional Types
from typing import Optional
class Input(BaseModel):
query: str
filter: Optional[str] = None # OptionalNested Types
class Address(BaseModel):
city: str
country: str = "JP"
class Input(BaseModel):
name: str
address: AddressTesting
Enter Input in the test panel at the bottom and run with Cmd+Enter.
You can test draft code without publishing, which is convenient for development.