Universal OpenAPI toolkit for AI agents. Load, search, and execute any API from OpenAPI specs.
Works with OpenAI, Anthropic, Vercel AI SDK, and any provider that supports function calling. One toolkit for every API.
git clone https://github.com/philippe-page/openapi-toolkit.git
cd openapi-toolkit/openapi-toolkit
npm install
npm run buildThen in your project:
npm install /path/to/openapi-toolkit/openapi-toolkitimport { getOpenAPITools, executeFunction } from 'openapi-toolkit';
import OpenAI from 'openai';
const client = new OpenAI();
const tools = await getOpenAPITools();
const messages = [{ role: 'user', content: 'Load GitHub API and search for repo endpoints' }];
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages,
tools
});
for (const toolCall of response.choices[0].message.tool_calls || []) {
const result = await executeFunction(toolCall.function.name, JSON.parse(toolCall.function.arguments));
console.log(result.content);
}import { getAnthropicTools, executeFunction } from 'openapi-toolkit';
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const tools = await getAnthropicTools();
const response = await client.messages.create({
model: 'claude-haiku-4-5',
max_tokens: 4096,
messages: [{ role: 'user', content: 'Load GitHub API' }],
tools
});
for (const block of response.content) {
if (block.type === 'tool_use') {
const result = await executeFunction(block.name, block.input);
console.log(result.content);
}
}import { createAISDKTools } from 'openapi-toolkit';
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const tools = await createAISDKTools();
const result = await generateText({
model: openai('gpt-4o'),
tools,
prompt: 'Load GitHub API and search endpoints'
});load_openapi_spec- Load any OpenAPI spec by URL or JSONsearch_operations- Find API endpoints with fuzzy searchget_operation_details- Get full parameter info for any endpointget_categories- Browse APIs by organized categoriesget_resources_in_category- List resources within a categoryget_service_info- Get API metadata and base URLexecute_http_request- Make authenticated API calls with filteringexecute_chained_http_request- Chain multiple API calls with variable substitution
The toolkit automatically finds API tokens from environment variables. When you load "github", it looks for GITHUB_TOKEN, GITHUB_API_KEY, etc.
Create a .env file:
GITHUB_TOKEN=ghp_your_token
STRIPE_SECRET_KEY=sk_your_key
OPENAI_API_KEY=sk-your_keyThen load with dotenv:
import 'dotenv/config';Module-level cache persists loaded specs across all function calls in the same process:
import { executeFunction, getAllServiceNames } from 'openapi-toolkit';
await executeFunction('load_openapi_spec', {
service_name: 'github',
source:
'https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json'
});
console.log(getAllServiceNames()); // ['github']
await executeFunction('search_operations', {
query: 'repository',
service_name: 'github'
});Once loaded, the spec stays cached.
Use response_filter to extract only what you need from API responses:
await executeFunction('execute_http_request', {
service_name: 'github',
method: 'GET',
url: '/repos/microsoft/typescript',
response_filter: '$[name,description,stargazers_count]'
});Filter Options:
- Field projection:
$[name,id,status] - JSONPath:
$.items[0:10] - Nested:
$.data.items[name,price] - Structured:
{ jsonpath: "$.items", fields: ["id","name"], limit: 10 }
Saves tokens and reduces noise.
Execute multi-step workflows where each call can reference previous results:
await executeFunction('execute_chained_http_request', {
steps: [
{
step_id: 'search',
service_name: 'github',
method: 'GET',
url: '/search/repositories',
parameters: { q: 'AI agents', sort: 'stars' },
response_filter: '$.items[0][full_name,name,owner]'
},
{
step_id: 'readme',
service_name: 'github',
method: 'GET',
url: '/repos/${search.full_name}/readme',
headers: { Accept: 'application/vnd.github.raw+json' }
}
],
stop_on_error: true
});Reference previous steps with ${step_id.field} syntax. Combine multiple APIs in one operation.
The toolkit tracks successful patterns and creates shortcuts:
const tools = await getOpenAPITools({ includeLearned: true });Agents see learned tools like:
learned_a3f2b1c5: Learned: GET /repos/owner/repo (github, used 5x)chain_f1e2d3c4: Chain: search → details → process (success: 100%, used 3x)
Top 5 by frequency + top 5 by recency. Session-scoped and ephemeral.
Restrict which endpoints can be called. Access rules can be configured via a JSON file or programmatically.
Create a openapi_access_config.json file in your working directory:
{
"github": {
"allowlist": ["GET *", "HEAD *"]
},
"stripe": {
"denylist": ["DELETE *"]
}
}The toolkit will automatically load this file when loadAccessRules() is called.
import { loadAccessRules } from 'openapi-toolkit';
process.env.OPENAPI_ACCESS_RULES = JSON.stringify({
github: { allowlist: ['GET *', 'HEAD *'] }
});
loadAccessRules();import { setAccessRules } from 'openapi-toolkit';
setAccessRules({
github: {
allowlist: ['GET *', 'HEAD *']
}
});Rules apply to both search results and HTTP request execution.
Common OpenAPI spec URLs:
- GitHub:
https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json - Stripe:
https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json - Figma:
https://github.com/figma/rest-api-spec/blob/main/openapi/openapi.yaml - Strava:
https://developers.strava.com/swagger/swagger.json
import { getOpenAPITools } from 'openapi-toolkit';OpenRouter uses the same format as OpenAI.
import { getAnthropicTools } from 'openapi-toolkit';import { createAISDKTools } from 'openapi-toolkit';All providers share the same state and use executeFunction for execution.
Core (5 packages, ~50KB):
- js-yaml
- jsonpath-plus
- openapi-types
- zod
- node-fetch
Peer dependencies:
openai- for OpenAI/OpenRouter@anthropic-ai/sdk- for Anthropicai- for Vercel AI SDK
See test files for complete examples:
test-aisdk-functions.ts- Vercel AI SDK with cachingtest-anthropic-functions.ts- Anthropic with iteration looptest-learned-chains.ts- Learned tools demotest-cache-demo.ts- State persistence
Authentication failing?
- Check
.envfile exists and has correct token format - Import
dotenv/configbefore any toolkit code - Service name should match token prefix (github → GITHUB_TOKEN)
Specs not loading?
- Verify URL is accessible
- Check for YAML parsing errors in console
- Some specs require specific base URLs
Learned tools not showing?
- Only appear after successful executions in the same process
- Pass
{ includeLearned: true }to tool getter functions - Top 5 by frequency + top 5 by recency (max 10 total per type)
PRs welcome. Whether it's:
- New authentication schemes
- Better error handling
- Provider integrations
- Performance improvements
- Documentation