How to Execute Composio Tools with Specific Versions and Version Pinning

Pin toolkit versions globally via the toolkitVersions constructor option or override per execution using the version parameter in ToolExecuteParams to ensure deterministic behavior and prevent breaking changes from automatic updates.

Production AI agents require stable tool definitions to avoid unexpected failures when upstream APIs change. The Composio SDK (from the ComposioHQ/composio repository) provides a robust versioning system that lets you lock toolkit versions either across your entire application or for individual tool calls. This guide explains how to execute tools with specific versions using the TypeScript SDK, referencing the actual implementation in ts/packages/core/src/models/Tools.ts and supporting utilities.

Understanding Version Resolution

Composio resolves tool versions through a strict hierarchy designed to prevent accidental execution of unpinned code. The resolution flow implemented in executeComposioTool (ts/packages/core/src/models/Tools.ts, lines 78–90) follows this priority:

  1. Explicit per-call version – The version field in ToolExecuteParams takes highest precedence
  2. Global toolkit mapping – The SDK checks getToolkitVersion(toolkitSlug, this.toolkitVersions) (defined in ts/packages/core/src/utils/toolkitVersion.ts)
  3. Safety validation – If the resolved version equals "latest" and dangerouslySkipVersionCheck is false, the SDK throws ComposioToolVersionRequiredError

This architecture ensures that unversioned tool calls fail loudly in production rather than silently adopting potentially breaking changes.

Setting Global Toolkit Versions

Configure version pinning at SDK initialization to apply defaults across all tool executions. Pass a toolkitVersions map to the Composio constructor, mapping toolkit slugs to specific version strings:

import { Composio } from '@composio/core';
import 'dotenv/config';

const composio = new Composio({
  apiKey: process.env.COMPOSIO_API_KEY,
  // Pin GitHub toolkit to a known stable version
  toolkitVersions: { 
    github: '20250909_00',
    gmail: '20241001_00' 
  },
});

console.log('Active version mapping:', composio.getConfig());

Source: [ts/examples/versioning/src/index.ts](https://github.com/ComposioHQ/composio/blob/next/ts/examples/versioning/src/index.ts)

When you call tools.execute() without an explicit version parameter, the SDK automatically injects the mapped version from this.toolkitVersions via the getToolkitVersion utility.

Executing Tools with Specific Versions Per Call

Override global defaults for individual executions by including the version field in your execution parameters. This approach is essential when testing new toolkit versions in staging while keeping production pinned to stable releases:

// Global map pins GitHub to 20250909_00, but we need a newer version for this call
const result = await composio.tools.execute('GITHUB_GET_REPOS', {
  userId: 'default',
  version: '20251115_01',  // Overrides global mapping for this execution only
  arguments: { owner: 'composio' },
});

The version parameter maps directly to the version query parameter in the /tools/execute API request, ensuring the specific tool definition is loaded server-side.

Bypassing Version Checks for Development

To execute against the latest toolkit version without explicit pinning, set dangerouslySkipVersionCheck: true. Only use this in development environments:

const result = await composio.tools.execute('HACKERNEWS_GET_USER', {
  userId: 'default',
  arguments: { userId: 'pg' },
  dangerouslySkipVersionCheck: true,  // Allows "latest" without error
});

Source: Version safety check in executeComposioTool (ts/packages/core/src/models/Tools.ts, lines 78–83)

Inspecting Available Versions Before Execution

Before pinning a version, inspect what versions are available for a specific tool. The getRawComposioToolBySlug method retrieves tool metadata including the availableVersions array:

const tool = await composio.tools.getRawComposioToolBySlug('GITHUB_GET_REPOS');
console.log('Available versions:', tool.availableVersions);
// Output: ['20250909_00', '20251115_01', 'latest']

Source: getRawComposioToolBySlug implementation (ts/packages/core/src/models/Tools.ts, lines 507–527)

This allows you to programmatically select appropriate versions or validate that a pinned version still exists before deployment.

Production Best Practices for Version Pinning

Pin versions at the SDK level for baseline stability across your application, then use per-call overrides only for specific edge cases or A/B testing new toolkit releases.

Never set dangerouslySkipVersionCheck: true in production. The ComposioToolVersionRequiredError exists specifically to prevent deployments from accidentally depending on mutable "latest" versions that can change without warning.

Version your toolkitVersions configuration alongside your application code. Treat version pins as dependencies—review changelogs when upgrading pinned versions, and test thoroughly in staging environments before promoting to production.

Summary

  • Global pinning uses the toolkitVersions constructor option to set default versions for entire toolkits across all executions
  • Per-call pinning overrides globals via the version field in execution parameters, targeting ts/packages/core/src/models/Tools.ts
  • Safety enforcement prevents accidental "latest" usage via ComposioToolVersionRequiredError unless dangerouslySkipVersionCheck is explicitly enabled
  • Version discovery is available through getRawComposioToolBySlug, which exposes availableVersions from the tool metadata

Frequently Asked Questions

What happens if I don't specify a version and haven't set global toolkit versions?

The SDK calls getToolkitVersion (in ts/packages/core/src/utils/toolkitVersion.ts), which returns "latest" for unmapped toolkits. Since "latest" is not an explicit version, executeComposioTool throws ComposioToolVersionRequiredError unless you set dangerouslySkipVersionCheck: true.

Can I mix global and per-call version pinning?

Yes. The version parameter in individual tools.execute() calls always takes precedence over the global toolkitVersions map. This allows you to maintain stable defaults while testing newer versions on specific tool calls.

How do I find the correct version string to pin?

Use getRawComposioToolBySlug('TOOL_NAME') to inspect the availableVersions property. This returns an array of valid version strings (e.g., ['20250909_00', '20251115_01']) that you can then reference in your configuration.

Is it safe to use dangerouslySkipVersionCheck in production?

No. This flag bypasses the safety check that prevents execution against mutable "latest" versions. Only use it during local development or CI testing. Production systems should always use explicit version pins to ensure deterministic behavior and prevent breaking changes from automatic toolkit updates.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →