Minor Changes
- a94715f: Forward
userIdwhen 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 viaexperimental_createTool,experimental_createToolkit, andcomposio.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
$refpointers in tool schemas the Composio API ships without a matching$defsentry. Some toolkits (e.g.GMAIL_FETCH_EMAILS) emitoutputParameterswith"$ref": "#/$defs/FetchEmailsResponse"while never declaring a top-level$defsblock. After the strict resolver shipped with the previous Mastra fix, this causedcomposio.tools.get(...)to throwJsonSchemaRefResolutionErrorupfront, making every Gmail / Slack / Google-Calendar tool unusable throughMastraProvider. 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.dereferenceJsonSchemaaccepts 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$refstill 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$refcycles. The replaced sentinel carries a defaultdescriptionhint so LLMs consuming the wrapped tool's schema get an in-band signal that the branch is opaque; a caller-provideddescriptionsibling overrides the default (Draft 2020-12 sibling-keyword merge). Safety caps (MAX_REF_CHAIN_DEPTH,MAX_NODE_DEPTH) keep throwing in both modes. NewUnresolvedRefStrategy,UnresolvedRefReason, andDereferenceJsonSchemaOptionstype exports.MastraProvider.wrapToolopts bothinputParametersandoutputParametersinto'sentinel'mode and emits onelogger.warnper(toolSlug, ref)pair via the provider-scoped dedupSet. User-controlled segments in the warning (tool.slug,toolkit.slug,ref) areJSON.stringifyd 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 respectsCOMPOSIO_DISABLE_TELEMETRY=true.- The
telemetryinstance from@composio/coreis now publicly re-exported alongsidelogger, so providers can emit aggregate signals without reaching into the package's internals. - Resolvable
$defs/definitionscontinue to be inlined exactly as before — no regression in the type-info preservation contract introduced by the previous Mastra fix.
-
1ba66ca: Fix
tools.execute(andtools.get/tools.list) failing with aZodErrorfor 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'sParametersSchemarequired{ type: 'object', properties: {...} }, sotransformToolCasesrejected the response andgetRawComposioToolBySlug— called byexecuteand the list path — threw.The SDK now normalizes empty (
{}),null, and missinginput_parameters/output_parameterspayloads toundefinedbefore validation.outputParameterswas already declared.optional()in the publicTooltype, 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 withCOMPOSIO_MULTI_EXECUTE_TOOLon the Vercel AI SDK),
which broke downstream validation with errors like
tool_use.input: Input should be a valid dictionary.@composio/corenow exposes a singlenormalizeToolArgumentshelper, and every
provider routes model-supplied arguments through it. Object payloads pass
through unchanged, JSON strings are parsed, empty/nullpayloads become{},
and anything that cannot resolve to an object throws a typed
ComposioInvalidToolArgumentsErrorinstead of a rawSyntaxErroror a silently
forwarded malformed string. This replaces the inconsistent per-provider guards
that previously existed only in vercel, cloudflare and openai-agents.