
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
ai-code-tools
Advanced tools
Wrap your AI SDK tools with code execution capabilities - discover and execute multiple tools in a single step
Supercharge your AI SDK tools with code execution capabilities. Discover and execute multiple tools in a single step through JavaScript code generation.
AI Code Tools wraps your existing Vercel AI SDK tools and adds two powerful meta-tools:
discover_tools - Let the LLM search through available tools by name and schemaexecute_tools - Let the LLM write JavaScript code to orchestrate multiple tool calls in one stepThis allows LLMs to be more efficient by composing multiple operations together instead of making sequential tool calls with round-trips.
npm install ai-code-tools
Simply wrap your existing AI SDK tools with createCodeTools():
import { createCodeTools } from 'ai-code-tools';
import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
// Your existing tools
const myTools = {
getCurrentWeather: {
description: 'Get the current weather in a location',
inputSchema: z.object({
location: z.string().describe('The city name'),
}),
execute: async ({ location }) => {
// Your weather API call
return { temperature: 72, condition: 'sunny' };
},
},
sendEmail: {
description: 'Send an email',
inputSchema: z.object({
to: z.string().describe('Email address'),
subject: z.string().describe('Email subject'),
body: z.string().describe('Email body'),
}),
execute: async ({ to, subject, body }) => {
// Your email sending logic
return { sent: true };
},
},
};
// Wrap your tools - that's it!
const tools = createCodeTools(myTools);
// Use with AI SDK as normal
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
prompt: 'Get the weather in San Francisco and email it to user@example.com',
tools,
});
Instead of the LLM making multiple sequential tool calls:
1. Call getCurrentWeather({ location: "San Francisco" })
2. Wait for response...
3. Call sendEmail({ to: "user@example.com", subject: "Weather", body: "72°F, sunny" })
4. Wait for response...
The LLM can now discover available tools and execute them together:
// Generated by the LLM via execute_tools
const weather = await tools.getCurrentWeather({ location: "San Francisco" });
const emailResult = await tools.sendEmail({
to: "user@example.com",
subject: "Weather Update",
body: `The weather in San Francisco is ${weather.temperature}°F and ${weather.condition}`
});
return emailResult;
All in a single step!
createCodeTools(tools)Takes your tools object and returns a new tools object with two additional meta-tools:
type Tool = {
description?: string;
inputSchema: z.ZodType<any>;
execute: (params: any) => Promise<any> | any;
};
function createCodeTools(tools: Record<string, Tool>): Record<string, Tool>;
discover_toolsAllows the LLM to search for available tools by name and schema:
{
description: "Discover available tools by searching tool names and schemas with a query pattern",
inputSchema: z.object({
query: z.string().describe("The search query to find relevant tools")
})
}
execute_toolsAllows the LLM to execute JavaScript code with access to your tools:
{
description: "Execute JavaScript code with access to tools via the 'tools' object. Return the result you want access to. IMPORTANT: Only use this tool to call the available tools and return their results.",
inputSchema: z.object({
code: z.string().describe("The JavaScript code to execute")
})
}
Security is a top priority. The generated JavaScript code goes through AST-based validation using Acorn before execution.
The code validation blocks all potentially dangerous operations:
require(), import, dynamic importseval(), Function constructor, setTimeout, setInterval, setImmediateprocess, global, globalThis, module, exports__dirname, __filename{}.constructor.constructorBefore executing any code, it's parsed into an Abstract Syntax Tree (AST) and validated:
// ❌ This will be blocked before execution
const code = `
const fs = require('fs');
return fs.readFileSync('/etc/passwd');
`;
// Error: "Code validation failed: Forbidden identifier: require"
// ✅ This is allowed
const code = `
const weather = await tools.getCurrentWeather({ location: "NYC" });
return weather.temperature;
`;
// Returns: 72
The library includes comprehensive security tests covering:
All 19 security tests pass. See src/execute_tools.test.ts for details.
const tools = createCodeTools({
searchProducts: {
description: 'Search for products',
inputSchema: z.object({
query: z.string(),
}),
execute: async ({ query }) => {
return [
{ id: 1, name: 'Laptop', price: 999 },
{ id: 2, name: 'Mouse', price: 29 },
];
},
},
getProductDetails: {
description: 'Get detailed product information',
inputSchema: z.object({
productId: z.number(),
}),
execute: async ({ productId }) => {
return { id: productId, stock: 10, rating: 4.5 };
},
},
addToCart: {
description: 'Add product to shopping cart',
inputSchema: z.object({
productId: z.number(),
quantity: z.number(),
}),
execute: async ({ productId, quantity }) => {
return { success: true, cartTotal: 999 };
},
},
});
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
prompt: 'Search for laptops, find the one with the best rating, and add it to my cart',
tools,
});
// The LLM can execute_tools with code like:
// const products = await tools.searchProducts({ query: "laptops" });
// const details = await Promise.all(
// products.map(p => tools.getProductDetails({ productId: p.id }))
// );
// const best = details.sort((a, b) => b.rating - a.rating)[0];
// return await tools.addToCart({ productId: best.id, quantity: 1 });
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Run unit tests with Vitest
npm run test:unit
MIT
Contributions are welcome! Please ensure all security tests pass before submitting PRs.
FAQs
Wrap your AI SDK tools with code execution capabilities - discover and execute multiple tools in a single step
We found that ai-code-tools demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.