Files
composiohq__composio/.changeset
Abir Taheer f6df489c0b Release: update version (#3429)
> [!WARNING]
> ## ⚠️ Breaking change — `@composio/core@0.11.0` (minor bump, pre-1.0)
>
> The legacy in-memory custom-tools registry
**`composio.tools.createCustomTool(...)` has been removed** (changeset
`44e5458`). Because `@composio/core` is pre-1.0, this ships as a
**minor** bump per semver convention — but it **is breaking**: any code
calling `composio.tools.createCustomTool(...)` will fail to compile/run
after upgrading. Consumers pinned to `^0.10.0` will **not** auto-upgrade
to `0.11.0` and must opt in explicitly.

### Migration: use Tool Router custom tools

Custom tools are now standalone factories bound to a **Tool Router
session**, instead of being registered into an in-memory registry on the
`composio.tools` namespace.

**Before (removed):**

```ts
// ❌ No longer available in 0.11.0
const tool = composio.tools.createCustomTool({ /* ... */ });
```

**After — a standalone tool (no auth):**

```ts
import { Composio, experimental_createTool } from '@composio/core';
import { z } from 'zod';

const composio = new Composio();

const grep = experimental_createTool('GREP', {
  name: 'Grep Search',
  description: 'Search for patterns in files',
  inputParams: z.object({ pattern: z.string(), path: z.string() }),
  execute: async (input) => ({ matches: [] }),
});

// Bind the custom tool(s) to a Tool Router session
const session = await composio.create(userId, {
  experimental: { customTools: [grep] },
});
```

**After — a tool that extends a Composio toolkit (inherits that
toolkit's auth):**

```ts
const getImportantEmails = experimental_createTool('GET_IMPORTANT_EMAILS', {
  name: 'Get Important Emails',
  description: 'Fetch high-priority emails',
  extendsToolkit: 'gmail',
  inputParams: z.object({ limit: z.number().default(10) }),
  execute: async (input, ctx) => {
    // ctx.execute() returns the standard { data, error, logId } shape
    const result = await ctx.execute('GMAIL_SEARCH', { query: 'is:important' });
    return { emails: result.data };
  },
});

const session = await composio.create(userId, {
  experimental: { customTools: [getImportantEmails] },
});
```

**After — grouping related tools into a custom toolkit:**

```ts
import { experimental_createToolkit } from '@composio/core';

const devTools = experimental_createToolkit('DEV_TOOLS', {
  name: 'Dev Tools',
  description: 'Local developer utilities',
  tools: [grep], // tools here must NOT set `extendsToolkit`
});

const session = await composio.create(userId, {
  experimental: { customToolkits: [devTools] },
});
```

> Notes:
> - `experimental_createTool` / `experimental_createToolkit` are also
available from the dedicated `@composio/core/experimental` entry point.
> - Tool slugs are auto-prefixed with `LOCAL_` when exposed to the agent
(e.g. `GREP` → `LOCAL_GREP`; inside a toolkit, `DEV_TOOLS` + `GREP` →
`LOCAL_DEV_TOOLS_GREP`).
> - These APIs are intentionally namespaced `experimental_*` — they are
not yet stable and may change.

---

This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to next, this PR will
be updated.


# Releases
## @composio/core@0.11.0

### Minor Changes

- a94715f: Forward `userId` when creating trigger instances so trigger
2FA flows can verify connected account ownership.
- 44e5458: Remove the legacy `composio.tools.createCustomTool(...)`
in-memory registry API. Use Tool Router custom tools via
`experimental_createTool`, `experimental_createToolkit`, and
`composio.create(..., { experimental: { customTools, customToolkits }
})` instead.

### Patch Changes

- 22a9171: Defer telemetry batch and error sends so instrumentation does
not wait for telemetry network requests before returning SDK results or
rethrowing SDK errors.
- 93b67e8: Fix automatic file upload/download substitution for file
schemas that accept either a single file or a list of files.

The file modifier now selects composed-schema branches by runtime value
shape, so `anyOf(file, array<file>)` uploads or downloads each file when
the tool receives a list while preserving existing single-file behavior.

- b69cef1: Tolerate dangling `$ref` pointers in tool schemas the
Composio API ships without a matching `$defs` entry. Some toolkits (e.g.
`GMAIL_FETCH_EMAILS`) emit `outputParameters` with `"$ref":
"#/$defs/FetchEmailsResponse"` while never declaring a top-level `$defs`
block. After the strict resolver shipped with the previous Mastra fix,
this caused `composio.tools.get(...)` to throw
`JsonSchemaRefResolutionError` upfront, making every Gmail / Slack /
Google-Calendar tool unusable through `MastraProvider`. The SDK now
degrades the unresolvable branch to a permissive object schema and
surfaces a single observability warning per `(toolSlug, ref)` pair
instead of crashing.
- `dereferenceJsonSchema` accepts a new optional second argument `{
onUnresolved?: 'throw' | 'sentinel'; onReplace?: (ref, reason) => void
}`. Default behavior is unchanged (`'throw'`) — first-party /
custom-tool schemas with a typo'd `$ref` still surface as a hard error.
Pass `'sentinel'` to replace unresolved branches with the cycle-break
sentinel (`{ type: 'object', additionalProperties: true }`) that the
resolver already uses for `$ref` cycles. The replaced sentinel carries a
default `description` hint so LLMs consuming the wrapped tool's schema
get an in-band signal that the branch is opaque; a caller-provided
`description` sibling overrides the default (Draft 2020-12
sibling-keyword merge). Safety caps (`MAX_REF_CHAIN_DEPTH`,
`MAX_NODE_DEPTH`) keep throwing in both modes. New
`UnresolvedRefStrategy`, `UnresolvedRefReason`, and
`DereferenceJsonSchemaOptions` type exports.
- `MastraProvider.wrapTool` opts both `inputParameters` and
`outputParameters` into `'sentinel'` mode and emits one `logger.warn`
per `(toolSlug, ref)` pair via the provider-scoped dedup `Set`.
User-controlled segments in the warning (`tool.slug`, `toolkit.slug`,
`ref`) are `JSON.stringify`d to neutralize embedded newlines / ANSI
escapes / control bytes that could otherwise forge log lines (CWE-117).
A matching one-shot telemetry event
(`composio.mastra.wrapTool.danglingRef`) fires next to the warn so the
Composio team has aggregate visibility into which toolkits are affected;
the event respects `COMPOSIO_DISABLE_TELEMETRY=true`.
- The `telemetry` instance from `@composio/core` is now publicly
re-exported alongside `logger`, so providers can emit aggregate signals
without reaching into the package's internals.
- Resolvable `$defs` / `definitions` continue to be inlined exactly as
before — no regression in the type-info preservation contract introduced
by the previous Mastra fix.

- 1ba66ca: Fix `tools.execute` (and `tools.get` / `tools.list`) failing
with a `ZodError` for every tool from an MCP-backed toolkit (e.g.
`granola_mcp`, `apify_mcp`, `tavily_mcp`).

MCP toolkits don't declare an output schema, and the Composio API
serializes that as `output_parameters: {}`. The SDK's `ParametersSchema`
required `{ type: 'object', properties: {...} }`, so
`transformToolCases` rejected the response and
`getRawComposioToolBySlug` — called by `execute` and the list path —
threw.

The SDK now normalizes empty (`{}`), `null`, and missing
`input_parameters` / `output_parameters` payloads to `undefined` before
validation. `outputParameters` was already declared `.optional()` in the
public `Tool` type, so this preserves the contract: "undefined means no
declared schema." Tools that _do_ declare a schema continue to be
validated strictly.

  No public API change; no toolkit allow-list.

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/cli-local-tools@0.0.5

### Patch Changes

- Updated dependencies [22a9171]
- Updated dependencies [93b67e8]
- Updated dependencies [b69cef1]
- Updated dependencies [1ba66ca]
- Updated dependencies [a94715f]
- Updated dependencies [ce4b213]
- Updated dependencies [44e5458]
  - @composio/core@0.11.0
## @composio/anthropic@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/claude-agent-sdk@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/cloudflare@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/google@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/langchain@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/llamaindex@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/mastra@0.9.3

### Patch Changes

- b69cef1: Tolerate dangling `$ref` pointers in tool schemas the
Composio API ships without a matching `$defs` entry. Some toolkits (e.g.
`GMAIL_FETCH_EMAILS`) emit `outputParameters` with `"$ref":
"#/$defs/FetchEmailsResponse"` while never declaring a top-level `$defs`
block. After the strict resolver shipped with the previous Mastra fix,
this caused `composio.tools.get(...)` to throw
`JsonSchemaRefResolutionError` upfront, making every Gmail / Slack /
Google-Calendar tool unusable through `MastraProvider`. The SDK now
degrades the unresolvable branch to a permissive object schema and
surfaces a single observability warning per `(toolSlug, ref)` pair
instead of crashing.
- `dereferenceJsonSchema` accepts a new optional second argument `{
onUnresolved?: 'throw' | 'sentinel'; onReplace?: (ref, reason) => void
}`. Default behavior is unchanged (`'throw'`) — first-party /
custom-tool schemas with a typo'd `$ref` still surface as a hard error.
Pass `'sentinel'` to replace unresolved branches with the cycle-break
sentinel (`{ type: 'object', additionalProperties: true }`) that the
resolver already uses for `$ref` cycles. The replaced sentinel carries a
default `description` hint so LLMs consuming the wrapped tool's schema
get an in-band signal that the branch is opaque; a caller-provided
`description` sibling overrides the default (Draft 2020-12
sibling-keyword merge). Safety caps (`MAX_REF_CHAIN_DEPTH`,
`MAX_NODE_DEPTH`) keep throwing in both modes. New
`UnresolvedRefStrategy`, `UnresolvedRefReason`, and
`DereferenceJsonSchemaOptions` type exports.
- `MastraProvider.wrapTool` opts both `inputParameters` and
`outputParameters` into `'sentinel'` mode and emits one `logger.warn`
per `(toolSlug, ref)` pair via the provider-scoped dedup `Set`.
User-controlled segments in the warning (`tool.slug`, `toolkit.slug`,
`ref`) are `JSON.stringify`d to neutralize embedded newlines / ANSI
escapes / control bytes that could otherwise forge log lines (CWE-117).
A matching one-shot telemetry event
(`composio.mastra.wrapTool.danglingRef`) fires next to the warn so the
Composio team has aggregate visibility into which toolkits are affected;
the event respects `COMPOSIO_DISABLE_TELEMETRY=true`.
- The `telemetry` instance from `@composio/core` is now publicly
re-exported alongside `logger`, so providers can emit aggregate signals
without reaching into the package's internals.
- Resolvable `$defs` / `definitions` continue to be inlined exactly as
before — no regression in the type-info preservation contract introduced
by the previous Mastra fix.

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/openai@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/openai-agents@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/vercel@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/cli@0.2.32

### Patch Changes

- Updated dependencies [22a9171]
- Updated dependencies [93b67e8]
- Updated dependencies [b69cef1]
- Updated dependencies [1ba66ca]
- Updated dependencies [a94715f]
- Updated dependencies [ce4b213]
- Updated dependencies [44e5458]
  - @composio/core@0.11.0
  - @composio/cli-local-tools@0.0.5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-19 17:12:38 +04:00
..
2025-05-19 19:30:29 +05:30

Changesets

Hello and welcome! This folder has been automatically generated by @changesets/cli, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it in our repository

We have a quick list of common questions to get you started engaging with this project in our documentation