Install any skill in seconds. Free to start, no credit card required.
Get Started Free →This skill should be used when the user asks to "create a tool", "implement BaseTool", "add tool to agent", "tool orchestration", "external API tool", or needs guidance on tool development, tool configuration, error handling, and integrating tools with agents in Atomic Agents applications.
.claude/skills/majiayu000-atomic-agents-tool-development/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 34% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 33% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 31% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 124% | 0% |
Tools extend agent capabilities by providing access to external services, APIs, databases, and computations. They follow a consistent pattern with input/output schemas and error handling.
┌─────────────────────────────────────┐
│ BaseTool │
├─────────────────────────────────────┤
│ input_schema: BaseIOSchema │
│ output_schema: BaseIOSchema │
│ config: BaseToolConfig │
├─────────────────────────────────────┤
│ run(params) -> Output | Error │
└─────────────────────────────────────┘pythonfrom atomic_agents.lib.base.base_tool import BaseTool, BaseToolConfig from atomic_agents.lib.base.base_io_schema import BaseIOSchema from pydantic import Field from typing import Optional import os # ============================================================ # Schemas # ============================================================ class MyToolInputSchema(BaseIOSchema): """Input for the tool.""" query: str = Field(..., description="The query to process") class MyToolOutputSchema(BaseIOSchema): """Successful output.""" result: str = Field(..., description="The result") class MyToolErrorSchema(BaseIOSchema): """Error output.""" error: str = Field(..., description="Error message") code: Optional[str] = Field(default=None, description="Error code") # ============================================================ # Configuration # ============================================================ class MyToolConfig(BaseToolConfig): """Tool configuration.""" api_key: str = Field( default_factory=lambda: os.getenv("MY_API_KEY", ""), description="API key" ) timeout: int = Field(default=30, description="Timeout in seconds") # ============================================================ # Tool # ============================================================ class MyTool(BaseTool): """Tool description.""" input_schema = MyToolInputSchema output_schema = MyToolOutputSchema def __init__(self, config: MyToolConfig = None): super().__init__(config or MyToolConfig()) self.config: MyToolConfig = self.config def run(self, params: MyToolInputSchema) -> MyToolOutputSchema | MyToolErrorSchema: try: # Tool logic here result = f"Processed: {params.query}" return MyToolOutputSchema(result=result) except Exception as e: return MyToolErrorSchema(error=str(e), code="ERROR") # Convenience instance tool = MyTool()
pythonclass APIToolConfig(BaseToolConfig): """Configuration with environment variables.""" api_key: str = Field( default_factory=lambda: os.getenv("SERVICE_API_KEY", ""), description="API key for the service" ) base_url: str = Field( default="https://api.service.com/v1", description="Base URL for API" ) timeout: int = Field( default=30, ge=1, le=300, description="Request timeout in seconds" ) max_retries: int = Field( default=3, ge=0, le=10, description="Maximum retry attempts" )
Always return error schemas instead of raising exceptions:
pythondef run(self, params: InputSchema) -> OutputSchema | ErrorSchema: # Validate configuration if not self.config.api_key: return ErrorSchema( error="API key not configured", code="CONFIG_ERROR" ) try: # Make external call response = requests.get( f"{self.config.base_url}/endpoint", params={"q": params.query}, headers={"Authorization": f"Bearer {self.config.api_key}"}, timeout=self.config.timeout ) response.raise_for_status() data = response.json() return OutputSchema(result=data["result"]) except requests.Timeout: return ErrorSchema(error="Request timed out", code="TIMEOUT") except requests.HTTPError as e: return ErrorSchema(error=f"HTTP error: {e}", code="HTTP_ERROR") except Exception as e: return ErrorSchema(error=str(e), code="UNKNOWN_ERROR")
pythonfrom my_tools import search_tool, SearchInputSchema # Call tool directly result = search_tool.run(SearchInputSchema(query="atomic agents"))
pythonfrom typing import Union from atomic_agents.agents.base_agent import AtomicAgent, AgentConfig # Define tool selection schema class ToolCallSchema(BaseIOSchema): tool_name: Literal["search", "calculate", "none"] = Field( ..., description="Which tool to use" ) tool_input: Union[SearchInput, CalculateInput, None] = Field( ..., description="Input for the selected tool" ) # Agent decides which tool to use agent = AtomicAgent[UserQuerySchema, ToolCallSchema](config=config) # Orchestration loop user_input = UserQuerySchema(query="What is 2+2?") tool_decision = agent.run(user_input) if tool_decision.tool_name == "calculate": result = calculator_tool.run(tool_decision.tool_input) elif tool_decision.tool_name == "search": result = search_tool.run(tool_decision.tool_input)
Download tools from Atomic Forge:
bashatomic download calculator atomic download searxng atomic download youtube-transcript
Available tools:
See references/ for:
api-integration.md - Patterns for REST API toolsdatabase-tools.md - Database integration patternsSee examples/ for:
simple-tool.py - Minimal tool implementationapi-tool.py - External API integrationOther measured skills in the registry, with their headline benchmark lift.