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* () {