
Research
/Security News
Laravel Lang Compromised with RCE Backdoor Across 700+ Versions
Laravel Lang packages were compromised with an RCE backdoor across hundreds of versions, exposing cloud, CI/CD, and developer secrets.
@stackone/ai
Advanced tools
A unified interface for performing actions on SaaS tools through AI-friendly APIs.
The StackOne AI SDK provides the StackOneToolSet class, which fetches tools dynamically from StackOne's MCP (Model Context Protocol) endpoint. This ensures you always have access to the latest tool definitions.
# Using npm
npm install @stackone/ai zod
# Using yarn
yarn add @stackone/ai zod
# Using pnpm
pnpm add @stackone/ai zod
# Using bun
bun add @stackone/ai zod
Note:
zodis a peer dependency required for AI SDK integrations and internal schema validation. Version>=3.25.0 <5is supported.
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
const employeeTool = tools.getTool('workday_list_workers');
const employees = await employeeTool.execute();
Set the STACKONE_API_KEY environment variable:
export STACKONE_API_KEY=<your-api-key>
or load from a .env file using your preferred environment variable library.
StackOne uses account IDs to identify different integrations. You can specify the account ID at different levels:
import { StackOneToolSet } from '@stackone/ai';
// Simplest: set STACKONE_ACCOUNT_ID environment variable
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
// Explicit single account
const explicitToolset = new StackOneToolSet({ accountId: 'your-workday-account' });
const explicitTools = await explicitToolset.fetchTools();
// Multiple accounts - returns tools from both integrations
const multiAccountToolset = new StackOneToolSet();
const allTools = await multiAccountToolset.fetchTools({
accountIds: ['workday-account-123', 'hibob-account-456'],
});
// Filter to specific integration when using multiple accounts
const workdayOnly = await multiAccountToolset.fetchTools({
accountIds: ['workday-account-123', 'hibob-account-456'],
actions: ['workday_*'], // Only Workday tools
});
// Set directly on a tool instance
tools.setAccountId('direct-account-id');
const currentAccountId = tools.getAccountId(); // Get the current account ID
The StackOneToolSet makes it super easy to use StackOne APIs as tools in your AI applications.
npm install @stackone/ai openai # or: yarn/pnpm/bun add
import { OpenAI } from 'openai';
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
await openai.chat.completions.create({
model: 'gpt-5.1',
messages: [
{
role: 'system',
content: 'You are a helpful HR assistant using Workday.',
},
{
role: 'user',
content: 'Create a time-off request for employee id cxIQ5764hj2',
},
],
tools: tools.toOpenAI(),
});
npm install @stackone/ai openai # or: yarn/pnpm/bun add
import OpenAI from 'openai';
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
const openai = new OpenAI();
await openai.responses.create({
model: 'gpt-5.1',
instructions: 'You are a helpful HR assistant.',
input: 'What is the phone number for employee c28xIQ?',
tools: tools.toOpenAIResponses(),
});
npm install @stackone/ai @anthropic-ai/sdk # or: yarn/pnpm/bun add
import Anthropic from '@anthropic-ai/sdk';
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
const anthropic = new Anthropic();
await anthropic.messages.create({
model: 'claude-haiku-4-5-20241022',
max_tokens: 1024,
system: 'You are a helpful HR assistant.',
messages: [
{
role: 'user',
content: 'What is the phone number for employee c28xIQ?',
},
],
tools: tools.toAnthropic(),
});
npm install @stackone/ai ai @ai-sdk/openai # or: yarn/pnpm/bun add
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
await generateText({
model: openai('gpt-5.1'),
tools: await tools.toAISDK(),
maxSteps: 3,
});
npm install @stackone/ai @anthropic-ai/claude-agent-sdk zod # or: yarn/pnpm/bun add
import { query } from '@anthropic-ai/claude-agent-sdk';
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
// Fetch tools and convert to Claude Agent SDK format
const tools = await toolset.fetchTools();
const mcpServer = await tools.toClaudeAgentSdk();
// Use with Claude Agent SDK query
const result = query({
prompt: 'Get the employee with id: abc123',
options: {
model: 'claude-sonnet-4-5-20250929',
mcpServers: { 'stackone-tools': mcpServer },
tools: [], // Disable built-in tools
maxTurns: 3,
},
});
for await (const message of result) {
// Process streaming messages
}
You can filter tools by account IDs, providers, and action patterns:
// Filter by account IDs
toolset.setAccounts(['account-123', 'account-456']);
const tools = await toolset.fetchTools();
// OR
const tools = await toolset.fetchTools({
accountIds: ['account-123', 'account-456'],
});
// Filter by providers
const tools = await toolset.fetchTools({ providers: ['hibob', 'workday'] });
// Filter by actions with exact match
const tools = await toolset.fetchTools({
actions: ['hibob_list_employees', 'hibob_create_employees'],
});
// Filter by actions with glob patterns
const tools = await toolset.fetchTools({ actions: ['*_list_employees'] });
// Combine multiple filters
const tools = await toolset.fetchTools({
accountIds: ['account-123'],
providers: ['hibob'],
actions: ['*_list_*'],
});
This is especially useful when you want to:
Search for tools using natural language queries. Works with both semantic (cloud) and local BM25+TF-IDF search.
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
const searchTool = toolset.getSearchTool();
// Search for relevant tools — returns a Tools collection
const tools = await searchTool.search('manage employees', { topK: 5 });
// Execute a discovered tool directly
const listTool = tools.getTool('workday_list_workers');
const result = await listTool.execute({ query: { limit: 10 } });
Discover tools using natural language instead of exact names. Queries like "onboard new hire" resolve to the right actions even when the tool is called workday_create_employee.
import { StackOneToolSet } from '@stackone/ai';
// Reads STACKONE_API_KEY and STACKONE_ACCOUNT_ID from environment
const toolset = new StackOneToolSet();
// Search by intent — returns Tools collection ready for any framework
const tools = await toolset.searchTools('manage employee records', { topK: 5 });
const openAITools = tools.toOpenAI();
// Lightweight: inspect results without fetching full tool definitions
const results = await toolset.searchActionNames('time off requests', { topK: 5 });
Control which search backend searchTools() uses via the search option:
// 'auto' (default) — tries semantic search first, falls back to local
const tools = await toolset.searchTools('manage employees', { search: 'auto' });
// 'semantic' — semantic API only, throws if unavailable
const tools = await toolset.searchTools('manage employees', { search: 'semantic' });
// 'local' — local BM25+TF-IDF only, no semantic API call
const tools = await toolset.searchTools('manage employees', { search: 'local' });
Results are automatically scoped to connectors in your linked accounts. See Search Tools Example for SearchTool (getSearchTool) integration, AI SDK, and agent loop patterns.
import { StackOneToolSet } from '@stackone/ai';
const toolset = new StackOneToolSet({ baseUrl: 'https://api.example-dev.com' });
The SDK includes built-in prompt injection protection via StackOne Defender. It runs on every tool call result before the content reaches your LLM, detecting and sanitizing injection attacks hidden in external data (emails, documents, CRM notes, etc.).
By default, the SDK defers to your project's dashboard defender setting. Pass an explicit defender config to override the project setting per toolset.
defender option | Effective behavior |
|---|---|
| omitted (default) | Project dashboard setting controls — SDK adds nothing |
{ useProjectSettings: true } | Same as omitting; explicit, self-documenting form |
{ enabled, blockHighRisk, ... } | SDK-level config wins, overrides the project setting |
null | Defender forcibly disabled, overrides the project setting |
When passing an explicit object, missing fields fall back to DEFAULT_DEFENDER_CONFIG (exported from @stackone/ai): enabled: true, blockHighRisk: false, both tiers on.
import { StackOneToolSet, DEFAULT_DEFENDER_CONFIG } from '@stackone/ai';
// Default — defer to project dashboard setting
const toolset = new StackOneToolSet({ apiKey: '...' });
// Same as default, explicit form
const toolset = new StackOneToolSet({
apiKey: '...',
defender: { useProjectSettings: true },
});
// Explicitly disabled — overrides any project setting
const toolset = new StackOneToolSet({
apiKey: '...',
defender: null,
});
// Opt in with safe defaults, but block on HIGH/CRITICAL — overrides project setting
const toolset = new StackOneToolSet({
apiKey: '...',
defender: { ...DEFAULT_DEFENDER_CONFIG, blockHighRisk: true },
});
// Fully explicit SDK-level config
const toolset = new StackOneToolSet({
apiKey: '...',
defender: {
enabled: true,
blockHighRisk: true, // throw on HIGH or CRITICAL risk
useTier1Classification: true, // pattern-based (regex, role markers)
useTier2Classification: true, // ML-based (ONNX model)
},
});
Use the defenderMode getter to check how a toolset will behave at runtime:
const toolset = new StackOneToolSet({ apiKey: '...', defender: null });
toolset.defenderMode; // 'disabled' | 'explicit' | 'project'
When the SDK overrides the project dashboard (mode disabled or explicit), it emits a yellow console.warn line once per process per distinct override shape so the override is visible at runtime without spamming logs. Pass NO_COLOR=1 to suppress color, or FORCE_COLOR=1 to force it when piping output. The project mode is silent.
Defender assigns a risk level to each scanned result:
| Level | Meaning |
|---|---|
low | No threats detected |
medium | Suspicious patterns detected, role markers stripped |
high | Injection patterns found, content redacted |
critical | Severe injection attempt with multiple indicators |
When blockHighRisk: false (default), high and critical results are annotated and returned — the LLM sees the sanitized content. When blockHighRisk: true, those results are blocked entirely.
For more detail on how the detection pipeline works, see the @stackone/defender package.
You can use the dryRun option to return the api arguments from a tool call without making the actual api call:
import { StackOneToolSet } from '@stackone/ai';
// Initialize the toolset
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
const employeeTool = tools.getTool('workday_list_workers');
// Use dryRun to see the request details
const dryRunResult = await employeeTool.execute({ query: { limit: 5 } }, { dryRun: true });
console.log(dryRunResult);
// {
// url: "https://api.stackone.com/actions/rpc",
// method: "POST",
// headers: { ... },
// body: "...",
// mappedParams: { ... }
// }
The dryRun option returns an object containing:
url: The full URL with query parametersmethod: The HTTP methodheaders: The request headersbody: The request bodymappedParams: The parameters after mapping and derivationThe StackOne AI SDK includes a built-in feedback collection tool (tool_feedback) that allows users to provide feedback on their experience with StackOne tools. This tool is automatically included when using fetchTools() and helps improve the SDK based on user input.
The feedback tool:
/ai/tool-feedback endpointThe feedback tool is automatically available when using StackOneToolSet:
import { StackOneToolSet } from '@stackone/ai';
const toolset = new StackOneToolSet();
const tools = await toolset.fetchTools();
// The feedback tool is automatically included
const feedbackTool = tools.getTool('tool_feedback');
// Use with AI agents - they will ask for user consent first
const openAITools = tools.toOpenAI();
// or
const aiSdkTools = await tools.toAISDK();
You can also use the feedback tool directly:
// Get the feedback tool
const feedbackTool = tools.getTool('tool_feedback');
// Submit feedback (after getting user consent)
const result = await feedbackTool.execute({
feedback: 'The tools worked great! Very easy to use.',
account_id: 'acc_123456',
tool_names: ['workday_list_workers', 'workday_create_time_off_request'],
});
The feedback tool supports both single and multiple account IDs. When you provide an array of account IDs, the feedback will be sent to each account individually:
// Single account ID (string)
await feedbackTool.execute({
feedback: 'The tools worked great! Very easy to use.',
account_id: 'acc_123456',
tool_names: ['workday_list_workers', 'workday_create_time_off_request'],
});
// Multiple account IDs (array)
await feedbackTool.execute({
feedback: 'The tools worked great! Very easy to use.',
account_id: ['acc_123456', 'acc_789012'],
tool_names: ['workday_list_workers', 'workday_create_time_off_request'],
});
Response Format: When using multiple account IDs, the tool returns a summary of all submissions:
{
message: "Feedback sent to 2 account(s)",
total_accounts: 2,
successful: 2,
failed: 0,
results: [
{
account_id: "acc_123456",
status: "success",
result: { message: "Feedback successfully stored", ... }
},
{
account_id: "acc_789012",
status: "success",
result: { message: "Feedback successfully stored", ... }
}
]
}
When AI agents use this tool, they will:
The tool description includes clear instructions for AI agents to always ask for explicit user consent before submitting feedback.
# 1. Set up credentials
cp .env.example .env
# Edit .env with your API keys
# 2. Install dependencies
pnpm install
# 3. Run any example
pnpm run:example examples/openai-integration.ts
See the examples/ directory for the full list.
This project includes a Nix flake for reproducible development environments. All development tools are defined in flake.nix and provided via Nix.
# Install Nix with flakes enabled (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf -L https://artifacts.nixos.org/experimental-installer | \
sh -s -- install
# If flakes are not enabled, enable them with:
mkdir -p ~/.config/nix && echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
# Automatic activation with direnv (recommended)
direnv allow
# Or manual activation
nix develop
The flake provides all necessary development dependencies including Node.js, pnpm, and other build tools.
FAQs
Tools for agents to perform actions on your SaaS
The npm package @stackone/ai receives a total of 5,118 weekly downloads. As such, @stackone/ai popularity was classified as popular.
We found that @stackone/ai demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers 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.

Research
/Security News
Laravel Lang packages were compromised with an RCE backdoor across hundreds of versions, exposing cloud, CI/CD, and developer secrets.

Security News
Socket found a malicious postinstall hook across 700+ GitHub repos, including PHP packages on Packagist and Node.js project repositories.

Security News
Vibe coding at scale is reshaping how packages are created, contributed, and selected across the software supply chain