Universal tool schema adapter for AI providers (OpenAI, Anthropic, Gemini, Mistral)
npm install ai-tool-adapter



Universal AI tool schema adapter for function calling across multiple LLM providers.
Write your tool definitions once, convert to any provider format instantly. No more duplicating schemas for OpenAI, Anthropic, Google, and Mistral.
- Zero dependencies - Lightweight and secure
- Type-safe - Full TypeScript support with strict typing
- Provider-agnostic - One schema, multiple formats
- Pure functions - Predictable transformations with no side effects
- Well-tested - Comprehensive test coverage across all adapters
- OpenAI - GPT-4, GPT-3.5 function calling
- Anthropic - Claude tool use
- Google Gemini - Gemini function calling
- Mistral - Mistral AI function calling
``bash`
npm install ai-tool-adapter
`typescript
import { adapt } from 'ai-tool-adapter';
// Define your tool once using the universal schema
const weatherTool = {
name: 'get_weather',
description: 'Get current weather for a location',
params: {
location: {
type: 'string',
description: 'City name',
required: true,
},
units: {
type: 'string',
description: 'Temperature units',
enum: ['celsius', 'fahrenheit'],
},
},
};
// Convert to any provider format
const openaiTool = adapt(weatherTool, 'openai');
const anthropicTool = adapt(weatherTool, 'anthropic');
const geminiTool = adapt(weatherTool, 'gemini');
const mistralTool = adapt(weatherTool, 'mistral');
`
Convert a single universal tool definition to a specific provider's format.
Parameters:
- tool (UniversalTool) - Your universal tool definitionprovider
- (Provider) - Target provider: 'openai' | 'anthropic' | 'gemini' | 'mistral'
Returns: Provider-specific tool format
Throws: Error if provider is not supported
`typescript
const tool = {
name: 'calculate',
description: 'Perform arithmetic calculation',
params: {
operation: {
type: 'string',
enum: ['add', 'subtract', 'multiply', 'divide'],
required: true,
},
a: { type: 'number', required: true },
b: { type: 'number', required: true },
},
};
const openaiTool = adapt(tool, 'openai');
`
Convert multiple tools at once.
Parameters:
- tools (UniversalTool[]) - Array of universal tool definitionsprovider
- (Provider) - Target provider
Returns: Array of provider-specific tool formats
`typescript`
const tools = [weatherTool, calculatorTool, searchTool];
const openaiTools = adaptAll(tools, 'openai');
Get list of all supported providers.
Returns: Array of provider names
`typescript`
const providers = getProviders();
console.log(providers); // ['openai', 'anthropic', 'gemini', 'mistral']
`typescript`
interface UniversalTool {
name: string; // Function name
description: string; // What the tool does
params: Record
}
`typescript`
interface ToolParam {
type: 'string' | 'number' | 'boolean' | 'array' | 'object';
description?: string; // Parameter description
required?: boolean; // Whether required (default: false)
default?: unknown; // Default value
enum?: string[]; // Allowed values
items?: { // For array types
type: ParamType;
};
}
`typescript`
const statusTool = {
name: 'get_status',
description: 'Get current system status',
params: {}, // No parameters
};
`typescript`
const searchTool = {
name: 'search',
description: 'Search for items',
params: {
query: {
type: 'string',
description: 'Search query',
required: true,
},
},
};
`typescript`
const sortTool = {
name: 'sort_results',
description: 'Sort search results',
params: {
order: {
type: 'string',
enum: ['asc', 'desc'],
default: 'asc',
},
},
};
`typescript`
const batchTool = {
name: 'process_batch',
description: 'Process multiple items',
params: {
items: {
type: 'array',
description: 'Items to process',
items: { type: 'string' },
required: true,
},
},
};
`typescript`
const apiTool = {
name: 'api_request',
description: 'Make an API request',
params: {
endpoint: {
type: 'string',
description: 'API endpoint path',
required: true,
},
method: {
type: 'string',
description: 'HTTP method',
enum: ['GET', 'POST', 'PUT', 'DELETE'],
default: 'GET',
},
headers: {
type: 'object',
description: 'Request headers',
},
params: {
type: 'array',
description: 'Query parameters',
items: { type: 'string' },
},
timeout: {
type: 'number',
description: 'Request timeout in milliseconds',
default: 5000,
},
},
};
Wraps function definition in a type object:
`json`
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather",
"parameters": {
"type": "object",
"properties": {...},
"required": [...]
}
}
}
Flat structure with input_schema:
`json`
{
"name": "get_weather",
"description": "Get weather",
"input_schema": {
"type": "object",
"properties": {...},
"required": [...]
}
}
Flat structure with UPPERCASE types:
`json`
{
"name": "get_weather",
"description": "Get weather",
"parameters": {
"type": "OBJECT",
"properties": {
"location": { "type": "STRING" }
},
"required": [...]
}
}
OpenAI-compatible format:
`json`
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather",
"parameters": {...}
}
}
`typescript
import OpenAI from 'openai';
import { adapt } from 'ai-tool-adapter';
const client = new OpenAI();
const tools = [weatherTool, calculatorTool].map(tool =>
adapt(tool, 'openai')
);
const response = await client.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'What\'s the weather in Paris?' }],
tools,
});
`
`typescript
import Anthropic from '@anthropic-ai/sdk';
import { adaptAll } from 'ai-tool-adapter';
const client = new Anthropic();
const tools = adaptAll([weatherTool, calculatorTool], 'anthropic');
const response = await client.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: 'What\'s the weather in Paris?' }],
tools,
});
`
`typescript
import { adapt } from 'ai-tool-adapter';
// Single source of truth for your tools
const myTools = [weatherTool, calculatorTool, searchTool];
// Support all providers effortlessly
const providerClients = {
openai: { tools: myTools.map(t => adapt(t, 'openai')) },
anthropic: { tools: myTools.map(t => adapt(t, 'anthropic')) },
gemini: { tools: myTools.map(t => adapt(t, 'gemini')) },
mistral: { tools: myTools.map(t => adapt(t, 'mistral')) },
};
// Use whichever provider you need
function callLLM(provider: string, prompt: string) {
const config = providerClients[provider];
// Make API call with provider-specific tools
}
`
Full type definitions included:
`typescript
import type {
UniversalTool,
ToolParam,
Provider,
ParamType
} from 'ai-tool-adapter';
const tool: UniversalTool = {
name: 'my_tool',
description: 'My custom tool',
params: {
param1: {
type: 'string',
required: true,
},
},
};
`
`bashInstall dependencies
npm install
$3
This project uses Commitizen for standardized commit messages following the Conventional Commits specification.
Instead of
git commit, use:
- git cz or npm run commit - Interactive commit message builderThis ensures all commits follow a consistent format, making it easier to generate changelogs and understand project history.
Architecture
This library follows the Strategy Pattern with each provider adapter as an independent, interchangeable strategy. This design ensures:
- Orthogonality - Adapters are completely independent
- Open/Closed Principle - Easy to add new providers without modifying existing code
- Single Responsibility - Each adapter handles exactly one provider's format
- Pure Functions - Predictable, testable transformations
For detailed architecture documentation, see CLAUDE.md.
Contributing
Contributions are welcome! To add a new provider:
1. Create adapter in
src/adapters/yourprovider.ts
2. Add provider to Provider type in src/types.ts
3. Register adapter in src/index.ts`See CLAUDE.md for detailed guidelines.
ISC
- OpenAI Function Calling
- Anthropic Tool Use
- Google Gemini Function Calling
- Mistral AI Function Calling