diff --git a/packages/proxy/src/providers/anthropic.test.ts b/packages/proxy/src/providers/anthropic.test.ts index 070bcf61..4df3ee4a 100644 --- a/packages/proxy/src/providers/anthropic.test.ts +++ b/packages/proxy/src/providers/anthropic.test.ts @@ -575,3 +575,33 @@ it("should use 128000 max_tokens and add beta header for claude-3-7-sonnet when "output-128k-2025-02-19", ); }); + +it("should translate json_object response format to tool-based structured output", async () => { + // This test verifies BRA-3896: json_object response format should be translated + // to a tool-based workaround for Anthropic, similar to how json_schema is handled. + const { fetch, requests } = createCapturingFetch({ captureOnly: true }); + + await callProxyV1({ + body: { + model: "claude-3-haiku-20240307", + messages: [{ role: "user", content: "Return JSON" }], + response_format: { type: "json_object" }, + stream: false, + max_tokens: 150, + }, + fetch, + }); + + expect(requests).toHaveLength(1); + // Verify the proxy created a tool with generic object schema + expect(requests[0].body).toMatchObject({ + tools: [ + { + name: "json", + description: "Output the result in JSON format", + input_schema: { type: "object" }, + }, + ], + tool_choice: { type: "tool", name: "json" }, + }); +}); diff --git a/packages/proxy/src/proxy.ts b/packages/proxy/src/proxy.ts index a29a4b9a..247b5322 100644 --- a/packages/proxy/src/proxy.ts +++ b/packages/proxy/src/proxy.ts @@ -2597,7 +2597,10 @@ async function fetchAnthropicChatCompletions({ let isStructuredOutput = false; const parsed = responseFormatSchema.safeParse(oaiParams.response_format); - if (parsed.success && parsed.data.type === "json_schema") { + if ( + parsed.success && + (parsed.data.type === "json_schema" || parsed.data.type === "json_object") + ) { isStructuredOutput = true; if (params.tools || params.tool_choice) { throw new ProxyBadRequestError( @@ -2608,7 +2611,10 @@ async function fetchAnthropicChatCompletions({ { name: "json", description: "Output the result in JSON format", - input_schema: parsed.data.json_schema.schema, + input_schema: + parsed.data.type === "json_schema" + ? parsed.data.json_schema.schema + : { type: "object" }, }, ];