BrainBlend-AI

atomic-tools

@BrainBlend-AI/atomic-tools
BrainBlend-AI
5,459
447 forks
Updated 1/7/2026
View on GitHub

Atomic Agents Tool Development: 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.

Installation

$skills install @BrainBlend-AI/atomic-tools
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Pathclaude-plugin/atomic-agents/skills/atomic-tools/SKILL.md
Branchmain
Scoped Name@BrainBlend-AI/atomic-tools

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


description: 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.

Atomic Agents Tool Development

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.

Tool Architecture

┌─────────────────────────────────────┐
│           BaseTool                  │
├─────────────────────────────────────┤
│ input_schema: BaseIOSchema          │
│ output_schema: BaseIOSchema         │
│ config: BaseToolConfig              │
├─────────────────────────────────────┤
│ run(params) -> Output | Error       │
└─────────────────────────────────────┘

Basic Tool Template

from 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()

Tool Configuration Pattern

class 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"
    )

Error Handling Pattern

Always return error schemas instead of raising exceptions:

def 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")

Using Tools with Agents

Direct Tool Usage

from my_tools import search_tool, SearchInputSchema

# Call tool directly
result = search_tool.run(SearchInputSchema(query="atomic agents"))

Tool Orchestration Pattern

from 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)

Pre-Built Tools (Atomic Forge)

Download tools from Atomic Forge:

atomic download calculator
atomic download searxng
atomic download youtube-transcript

Available tools:

  • Calculator - Mathematical operations
  • SearXNG - Web search
  • Tavily - AI-powered search
  • YouTube Transcript - Video transcripts
  • Webpage Scraper - HTML content extraction

Tool Best Practices

  1. Always use BaseToolConfig - For consistent configuration
  2. Environment variables for secrets - Never hardcode API keys
  3. Return errors, don't raise - Caller can handle gracefully
  4. Set timeouts - Prevent hanging on external calls
  5. Validate inputs - Check parameters before processing
  6. Include error codes - Help with debugging and handling
  7. Document thoroughly - Input/output schemas need descriptions

References

See references/ for:

  • api-integration.md - Patterns for REST API tools
  • database-tools.md - Database integration patterns

See examples/ for:

  • simple-tool.py - Minimal tool implementation
  • api-tool.py - External API integration