Skip to content

Creating Tools

from astromesh_adk import tool
@tool(description="Search the web for information")
async def web_search(query: str, max_results: int = 5) -> str:
# JSON schema auto-generated from type hints
return f"Results for {query}"

Supported types: str, int, float, bool, list, dict, Optional, X | None.

For tools with state or lifecycle management:

from astromesh_adk import Tool
class DatabaseTool(Tool):
name = "query_db"
description = "Query the database"
def __init__(self, connection_string: str):
self.conn = connection_string
def parameters(self):
return {"sql": {"type": "string", "description": "SQL query"}}
async def execute(self, args, ctx=None):
return f"Results for: {args['sql']}"
async def cleanup(self):
pass # Close connections

The runner calls execute(args), but it does not read parameters() (the model sees the tool with an empty schema) and never calls cleanup(). Prefer @tool when the model needs the argument schema.

mcp_tools() builds a lazy MCPToolSet, but the runner does not run its discovery yet: the set reaches the model as a single tool with no schema, and the server’s tools are not called. The API is shown for reference.

from astromesh_adk import mcp_tools
github = mcp_tools(
transport="stdio",
command="npx",
args=["-y", "@modelcontextprotocol/server-github"],
env={"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
)
@agent(name="dev", model="openai/gpt-4o", tools=[web_search, *github])
async def dev_agent(ctx):
"""Developer agent."""
return None
ParameterTypeDescription
descriptionstrDescription for the LLM
rate_limitdict{"max_calls": N, "window_seconds": N}
requires_approvalboolRequire approval before execution. Default False
timeoutintTimeout in seconds. Default 30

rate_limit, requires_approval and timeout are stored on the tool but not enforced by the ADK runner.