Skip to main content

Custom Tools

Custom tools are functions you write in Python or TypeScript that extend what your agents can do. They’re deployed alongside your code and can perform any action — query databases, call APIs, integrate with your systems.
Looking for platform tools? Reminix also provides pre-built Platform Tools (web search, memory, knowledge base, KV storage) that require no code. This page covers custom tools you build yourself.
Custom tools let you:
  • Fetch data: Query your databases, call your APIs, read from your systems
  • Take actions: Send emails, create records, trigger workflows
  • Integrate: Connect to CRMs, payment processors, internal services

How Tools Work

When an agent needs to use a tool:
  1. Agent decides which tool to call based on the task
  2. Agent provides the input (API request body: { input: { ... } })
  3. Tool executes and returns a result
  4. Agent uses the result to continue processing

Tool Schema

Tools are defined with a schema that describes their inputs and outputs:
{
    "name": "get_weather",
    "description": "Get current weather for a city",
    "input": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "The city name"
            },
            "units": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"],
                "default": "fahrenheit"
            }
        },
        "required": ["city"]
    },
    "output": {
        "type": "object",
        "properties": {
            "location": { "type": "string", "description": "City name" },
            "temperature": { "type": "integer", "description": "Temperature value" },
            "condition": { "type": "string", "description": "Weather condition" }
        },
        "required": ["location", "temperature", "condition"]
    }
}
In Python, use Pydantic models for rich output schemas with property descriptions. In TypeScript, define schemas explicitly.

Creating Tools with Reminix

Reminix provides native tool APIs for both Python and TypeScript. These tools can be served as standalone HTTP endpoints.

Python

Use the @tool decorator:
from pydantic import BaseModel, Field
from reminix_runtime import tool, serve


class WeatherOutput(BaseModel):
    location: str = Field(description="City name")
    temperature: int = Field(description="Temperature value")
    units: str = Field(description="Temperature units")
    condition: str = Field(description="Weather condition")


@tool
async def get_weather(location: str, units: str = "celsius") -> WeatherOutput:
    """Get the current weather for a city.

    Args:
        location: City name to look up
        units: Temperature units (celsius or fahrenheit)
    """
    return WeatherOutput(
        location=location,
        temperature=22,
        units=units,
        condition="sunny"
    )

serve(tools=[get_weather], port=8080)
The decorator automatically extracts:
  • Input schema from type hints
  • Input field descriptions from docstring Args: section
  • Output schema from return type (Pydantic models, TypedDict, or basic types)

Python Tools Guide

Complete guide to creating tools in Python

TypeScript

Use the tool() factory function:
import { tool, serve } from '@reminix/runtime';

const getWeather = tool('get_weather', {
  description: 'Get current weather for a location',
  input: {
    type: 'object',
    properties: {
      location: { type: 'string', description: 'City name' },
      units: { type: 'string', default: 'celsius' },
    },
    required: ['location'],
  },
  handler: async (input) => {
    return {
      location: input.location as string,
      temperature: 22,
      condition: 'sunny',
    };
  },
});

serve({ tools: [getWeather], port: 8080 });

TypeScript Tools Guide

Complete guide to creating tools in TypeScript

Tool Endpoints

When tools are served, these endpoints are available:
EndpointMethodDescription
/healthGETHealth check
/infoGETDiscovery (lists all tools with schemas)
/tools/{name}/callPOSTCall a tool
Call a tool via cURL:
curl -X POST http://localhost:8080/tools/get_weather/call \
  -H "Content-Type: application/json" \
  -d '{"input": {"location": "San Francisco"}}'

Executing Tools via SDK

You can call deployed tools directly using the Reminix SDK:
import Reminix from '@reminix/sdk';

const client = new Reminix();

const response = await client.tools.call('get_weather', {
  input: {
    location: 'San Francisco',
    units: 'celsius'
  }
});

console.log(response.output);
// { location: "San Francisco", temperature: 22, condition: "sunny" }
This is useful when you need to:
  • Test tools independently of agents
  • Build custom orchestration logic
  • Call tools from external systems

Using Tools with Frameworks

Reminix also works with popular AI frameworks that have their own tool systems. Here’s how to use tools with each:

LangChain (Python)

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate

from reminix_langchain import wrap_agent
from reminix_runtime import serve

# Define tools
@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    # Your implementation
    return f"72°F and sunny in {city}"

@tool
def search_products(query: str) -> list:
    """Search the product catalog."""
    # Your implementation
    return [{"name": "Widget", "price": 9.99}]

# Create agent with tools
llm = ChatOpenAI(model="gpt-4")
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_tool_calling_agent(llm, [get_weather, search_products], prompt)
executor = AgentExecutor(agent=agent, tools=[get_weather, search_products])

# Serve with Reminix
serve(agents=[wrap_agent(executor, "assistant")], port=8080)

Vercel AI SDK (TypeScript)

import { openai } from '@ai-sdk/openai';
import { generateText, tool } from 'ai';
import { z } from 'zod';

import { wrapAgent } from '@reminix/vercel-ai';
import { serve } from '@reminix/runtime';

// Define tools
const weatherTool = tool({
  description: 'Get the current weather for a city',
  parameters: z.object({
    city: z.string().describe('The city name'),
  }),
  handler: async ({ city }) => {
    // Your implementation
    return `72°F and sunny in ${city}`;
  },
});

const searchTool = tool({
  description: 'Search the product catalog',
  parameters: z.object({
    query: z.string().describe('Search query'),
  }),
  handler: async ({ query }) => {
    // Your implementation
    return [{ name: 'Widget', price: 9.99 }];
  },
});

// Create agent function with tools
async function agent(input: string) {
  const result = await generateText({
    model: openai('gpt-4'),
    tools: { weather: weatherTool, search: searchTool },
    prompt: input,
  });
  return result.text;
}

// Serve with Reminix
serve({ agents: [wrapAgent(agent, 'assistant')], port: 8080 });

Custom vs Platform Tools

Custom ToolsPlatform Tools
DefinitionCode you writePre-built by Reminix
SetupDeploy with your codeEnable in UI
Use caseDomain-specific logicCommon capabilities
ExamplesCRM lookup, payment processingWeb search, memory, knowledge base
Custom tools are discovered via the /info endpoint when you deploy. The tool type reflects the language used:
TypeDescription
pythonPython tool (decorator-based)
typescriptTypeScript tool (factory-based)

Platform Tools

Learn about pre-built platform tools (web, memory, knowledge, storage)

Tool Best Practices

Each tool should do one thing well. Instead of a do_everything tool, create search_products, get_product_details, add_to_cart.
The agent uses descriptions to decide which tool to call. Be specific about what the tool does and when to use it.
Tools should return meaningful error messages that help the agent recover or inform the user.
Validate input before processing. Don’t assume the agent will always provide perfect inputs.

Next Steps