From b0b85cbb773ac777c41afa68b1aa9558ccbc269e Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Fri, 11 Sep 2026 21:18:57 -0500 Subject: [PATCH] fix(ai): omit empty Bedrock tool descriptions (#48582) --- packages/ai/src/protocols/bedrock-converse.ts | 4 +- .../ai/test/provider/bedrock-converse.test.ts | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/protocols/bedrock-converse.ts b/packages/ai/src/protocols/bedrock-converse.ts index 1bb29128544..520b8b934c5 100644 --- a/packages/ai/src/protocols/bedrock-converse.ts +++ b/packages/ai/src/protocols/bedrock-converse.ts @@ -106,7 +106,7 @@ type BedrockSystemBlock = Schema.Schema.Type const BedrockToolSpec = Schema.Struct({ toolSpec: Schema.Struct({ name: Schema.String, - description: Schema.String, + description: Schema.optional(Schema.String), inputSchema: Schema.Struct({ json: JsonObject, }), @@ -222,7 +222,7 @@ type BedrockEvent = Schema.Schema.Type const lowerToolSpec = (tool: ToolDefinition, inputSchema: JsonSchema): BedrockToolSpec => ({ toolSpec: { name: tool.name, - description: tool.description, + ...(tool.description.trim().length > 0 ? { description: tool.description } : {}), inputSchema: { json: inputSchema }, }, }) diff --git a/packages/ai/test/provider/bedrock-converse.test.ts b/packages/ai/test/provider/bedrock-converse.test.ts index 26d552fb216..bc6cc35f88b 100644 --- a/packages/ai/test/provider/bedrock-converse.test.ts +++ b/packages/ai/test/provider/bedrock-converse.test.ts @@ -279,6 +279,52 @@ describe("Bedrock Converse route", () => { }) }), ) + ;["", " \t\r\n"].forEach((description) => { + it.effect(`omits blank tool description ${JSON.stringify(description)}`, () => + Effect.gen(function* () { + const prepared = yield* compileRequest( + LLMRequest.update(baseRequest, { + tools: [ + ToolDefinition.make({ + name: "lookup", + description, + inputSchema: { type: "object", properties: { query: { type: "string" } } }, + }), + ], + }), + ) + + expect(prepared.body.toolConfig.tools).toEqual([ + { + toolSpec: { + name: "lookup", + inputSchema: { json: { type: "object", properties: { query: { type: "string" } } } }, + }, + }, + ]) + expect(prepared.body.toolConfig.tools[0].toolSpec).not.toHaveProperty("description") + }), + ) + }) + + it.effect("preserves meaningful tool descriptions including surrounding whitespace", () => + Effect.gen(function* () { + const description = " \tLookup data.\n" + const prepared = yield* compileRequest( + LLMRequest.update(baseRequest, { + tools: [ + ToolDefinition.make({ + name: "lookup", + description, + inputSchema: { type: "object" }, + }), + ], + }), + ) + + expect(prepared.body.toolConfig.tools[0].toolSpec.description).toBe(description) + }), + ) it.effect("keeps tools and omits the unsupported choice when tool choice is none", () => Effect.gen(function* () {