diff --git a/.changeset/violet-vans-design.md b/.changeset/violet-vans-design.md new file mode 100644 index 000000000..f63f63729 --- /dev/null +++ b/.changeset/violet-vans-design.md @@ -0,0 +1,5 @@ +--- +"braintrust": minor +--- + +feat(ai-sdk): Add Workflow Agent instrumentation diff --git a/e2e/helpers/provider-runtime.mjs b/e2e/helpers/provider-runtime.mjs index 1f63898d1..e14119a20 100644 --- a/e2e/helpers/provider-runtime.mjs +++ b/e2e/helpers/provider-runtime.mjs @@ -75,11 +75,43 @@ export async function runTracedScenario(options) { } export async function getInstalledPackageVersion(importMetaUrl, packageName) { - let currentDir = path.dirname( - require.resolve(packageName, { - paths: [path.dirname(fileURLToPath(importMetaUrl))], - }), - ); + let currentDir; + + try { + currentDir = path.dirname( + require.resolve(packageName, { + paths: [path.dirname(fileURLToPath(importMetaUrl))], + }), + ); + } catch { + currentDir = path.dirname(fileURLToPath(importMetaUrl)); + + while (true) { + const manifestPath = path.join( + currentDir, + "node_modules", + ...packageName.split("/"), + "package.json", + ); + + try { + const manifest = JSON.parse(await fs.readFile(manifestPath, "utf8")); + if (manifest && typeof manifest.version === "string") { + return manifest.version; + } + } catch { + // Keep walking upward until we find the package root. + } + + const parentDir = path.dirname(currentDir); + if (parentDir === currentDir) { + break; + } + currentDir = parentDir; + } + + throw new Error(`Could not resolve installed version for ${packageName}`); + } while (true) { const manifestPath = path.join(currentDir, "package.json"); diff --git a/e2e/helpers/scenario-runtime.ts b/e2e/helpers/scenario-runtime.ts index 82e799669..eeadea2f1 100644 --- a/e2e/helpers/scenario-runtime.ts +++ b/e2e/helpers/scenario-runtime.ts @@ -2,6 +2,7 @@ import { spawn } from "node:child_process"; import { promises as fs } from "node:fs"; import { createRequire } from "node:module"; import * as path from "node:path"; +import { fileURLToPath } from "node:url"; import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base"; export interface SubprocessResult { @@ -121,7 +122,41 @@ export async function getInstalledPackageVersion( packageName: string, ): Promise { const require = createRequire(importMetaUrl); - let currentDir = path.dirname(require.resolve(packageName)); + let currentDir: string; + + try { + currentDir = path.dirname(require.resolve(packageName)); + } catch { + currentDir = path.dirname(fileURLToPath(importMetaUrl)); + + while (true) { + const manifestPath = path.join( + currentDir, + "node_modules", + ...packageName.split("/"), + "package.json", + ); + + try { + const manifestRaw = await fs.readFile(manifestPath, "utf8"); + const manifest = JSON.parse(manifestRaw) as { version?: string }; + + if (typeof manifest.version === "string") { + return manifest.version; + } + } catch { + // Keep walking upward until we find the package root. + } + + const parentDir = path.dirname(currentDir); + if (parentDir === currentDir) { + break; + } + currentDir = parentDir; + } + + throw new Error(`Could not resolve installed version for ${packageName}`); + } while (true) { const manifestPath = path.join(currentDir, "package.json"); diff --git a/e2e/scenarios/ai-sdk-instrumentation/__cassettes__/ai-sdk-v7.cassette.json b/e2e/scenarios/ai-sdk-instrumentation/__cassettes__/ai-sdk-v7.cassette.json index 02fa0373c..704556497 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__cassettes__/ai-sdk-v7.cassette.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__cassettes__/ai-sdk-v7.cassette.json @@ -4,7 +4,7 @@ "callIndex": 0, "id": "9aa262365558ebc2", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:50.233Z", + "recordedAt": "2026-07-06T08:53:25.361Z", "request": { "body": { "kind": "json", @@ -37,11 +37,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905810, - "created_at": 1782905809, + "completed_at": 1783328005, + "created_at": 1783328004, "error": null, "frequency_penalty": 0, - "id": "resp_0348ef0bcf29c7a9006a44fbd19e6481a1a6bf4c1982861b47", + "id": "resp_08330a3aa71fd2ea006a4b6d04d31c81a2adc1b192c3d86d36", "incomplete_details": null, "instructions": null, "max_output_tokens": 24, @@ -60,7 +60,7 @@ "type": "output_text" } ], - "id": "msg_0348ef0bcf29c7a9006a44fbd2130c81a1b57271d385ab73b6", + "id": "msg_08330a3aa71fd2ea006a4b6d05328881a29690b891c24d255f", "role": "assistant", "status": "completed", "type": "message" @@ -128,13 +128,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d7d7b4a5a6b-VIE", + "cf-ray": "a16d60fd79765aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:50 GMT", + "date": "Mon, 06 Jul 2026 08:53:25 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "655", + "openai-processing-ms": "559", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -148,7 +148,7 @@ "x-ratelimit-remaining-tokens": "149999962", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "f1d6c868-7785-4ae3-9ea0-d60be05b745f" + "x-request-id": "ac58db47-746a-47f9-856d-429423dea797" }, "status": 200, "statusText": "OK" @@ -158,7 +158,7 @@ "callIndex": 1, "id": "9e077c56377ca81c", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:51.426Z", + "recordedAt": "2026-07-06T08:53:26.245Z", "request": { "body": { "kind": "json", @@ -209,11 +209,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905811, - "created_at": 1782905810, + "completed_at": 1783328006, + "created_at": 1783328005, "error": null, "frequency_penalty": 0, - "id": "resp_04b05ea9abbdaf41006a44fbd27738819ebae857af0d3bd794", + "id": "resp_0bdf0712f92a4636006a4b6d058d7c8191872b5e6b8eb3cc01", "incomplete_details": null, "instructions": null, "max_output_tokens": 32, @@ -232,7 +232,7 @@ "type": "output_text" } ], - "id": "msg_04b05ea9abbdaf41006a44fbd30c24819e97d83368a212ffa5", + "id": "msg_0bdf0712f92a4636006a4b6d0610cc8191ad947e13c4143eed", "role": "assistant", "status": "completed", "type": "message" @@ -313,13 +313,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d82dd1d5a6b-VIE", + "cf-ray": "a16d61021d465aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:51 GMT", + "date": "Mon, 06 Jul 2026 08:53:26 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "1000", + "openai-processing-ms": "700", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -330,10 +330,10 @@ "x-ratelimit-limit-requests": "30000", "x-ratelimit-limit-tokens": "150000000", "x-ratelimit-remaining-requests": "29999", - "x-ratelimit-remaining-tokens": "149999937", + "x-ratelimit-remaining-tokens": "149999935", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "1737e2b1-3b49-477b-8287-d7627795ae57" + "x-request-id": "a27dc479-aba2-4323-9c85-42370a8f489c" }, "status": 200, "statusText": "OK" @@ -343,7 +343,7 @@ "callIndex": 2, "id": "bdbf85bb8f9015c8", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:52.400Z", + "recordedAt": "2026-07-06T08:53:27.526Z", "request": { "body": { "kind": "json", @@ -372,20 +372,20 @@ "response": { "body": { "chunks": [ - "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0b9c56d090cafe02006a44fbd3a5b481a0809da4876a70b3e5\",\"object\":\"response\",\"created_at\":1782905811,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", - "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0b9c56d090cafe02006a44fbd3a5b481a0809da4876a70b3e5\",\"object\":\"response\",\"created_at\":1782905811,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", - "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":2}", - "event: response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"content_index\":0,\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"},\"sequence_number\":3}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"One\",\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"obfuscation\":\"TS0gW9dnuWRap\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"obfuscation\":\"VFJbHuFkWkWaejM\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" two\",\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"obfuscation\":\"R9NsOD2ZrAhK\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"obfuscation\":\"OzoL78ZCdl4i2i0\",\"output_index\":0,\"sequence_number\":7}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" three\",\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"obfuscation\":\"avL7DCNlgv\",\"output_index\":0,\"sequence_number\":8}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\".\",\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"obfuscation\":\"qxurc5sy78vmaLj\",\"output_index\":0,\"sequence_number\":9}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":10,\"text\":\"One, two, three.\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"One, two, three.\"},\"sequence_number\":11}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"One, two, three.\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":12}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0b9c56d090cafe02006a44fbd3a5b481a0809da4876a70b3e5\",\"object\":\"response\",\"created_at\":1782905811,\"status\":\"completed\",\"background\":false,\"completed_at\":1782905812,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0b9c56d090cafe02006a44fbd42e8c81a08c65b55aaeef3780\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"One, two, three.\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":22,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":7,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":29},\"user\":null,\"metadata\":{}},\"sequence_number\":13}" + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_059c6f0039554967006a4b6d06ca1481a1a05e6f1c4f213ec4\",\"object\":\"response\",\"created_at\":1783328006,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_059c6f0039554967006a4b6d06ca1481a1a05e6f1c4f213ec4\",\"object\":\"response\",\"created_at\":1783328006,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"content_index\":0,\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"},\"sequence_number\":3}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"One\",\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"obfuscation\":\"1i0hcTX0rW78S\",\"output_index\":0,\"sequence_number\":4}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"obfuscation\":\"r1z2uLpHvpRmlMy\",\"output_index\":0,\"sequence_number\":5}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" two\",\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"obfuscation\":\"mAYuxm3oQlOt\",\"output_index\":0,\"sequence_number\":6}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"obfuscation\":\"gG6yrC9dYOXPnfu\",\"output_index\":0,\"sequence_number\":7}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" three\",\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"obfuscation\":\"hLETIrXwkM\",\"output_index\":0,\"sequence_number\":8}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\".\",\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"obfuscation\":\"LrlAfYpXpmv76Gy\",\"output_index\":0,\"sequence_number\":9}", + "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":10,\"text\":\"One, two, three.\"}", + "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"One, two, three.\"},\"sequence_number\":11}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"One, two, three.\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":12}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_059c6f0039554967006a4b6d06ca1481a1a05e6f1c4f213ec4\",\"object\":\"response\",\"created_at\":1783328006,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328007,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_059c6f0039554967006a4b6d073e7081a1a9700578a824d5be\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"One, two, three.\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":22,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":7,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":29},\"user\":null,\"metadata\":{}},\"sequence_number\":13}" ], "kind": "sse" }, @@ -393,12 +393,12 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d8a3f5a5a6b-VIE", + "cf-ray": "a16d6107a9995aad-VIE", "connection": "keep-alive", "content-type": "text/event-stream; charset=utf-8", - "date": "Wed, 01 Jul 2026 11:36:51 GMT", + "date": "Mon, 06 Jul 2026 08:53:26 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "129", + "openai-processing-ms": "343", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -406,7 +406,7 @@ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-request-id": "83e34dc6-c6b7-4bd7-be80-bb48ac896348" + "x-request-id": "b9bea91a-bab9-971d-ba50-6a5dcb1a54bf" }, "status": 200, "statusText": "OK" @@ -416,7 +416,7 @@ "callIndex": 0, "id": "49a95bf2b3466013", "matchKey": "POST api.openai.com/v1/embeddings", - "recordedAt": "2026-07-01T11:36:52.623Z", + "recordedAt": "2026-07-06T08:53:27.757Z", "request": { "body": { "kind": "json", @@ -1004,13 +1004,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d9079245a6b-VIE", + "cf-ray": "a16d610fa80c5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:52 GMT", + "date": "Mon, 06 Jul 2026 08:53:27 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "68", + "openai-processing-ms": "75", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -1025,7 +1025,7 @@ "x-ratelimit-remaining-tokens": "9999993", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "b4a842ba-4420-4fd0-be72-cc00164c83d9" + "x-request-id": "ff774c96-46e7-4109-8347-79e71b35cec4" }, "status": 200, "statusText": "OK" @@ -1035,7 +1035,7 @@ "callIndex": 1, "id": "fcc3d17c88f1552b", "matchKey": "POST api.openai.com/v1/embeddings", - "recordedAt": "2026-07-01T11:36:52.837Z", + "recordedAt": "2026-07-06T08:53:28.014Z", "request": { "body": { "kind": "json", @@ -1064,13 +1064,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d91c9875a6b-VIE", + "cf-ray": "a16d611119235aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:52 GMT", + "date": "Mon, 06 Jul 2026 08:53:28 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "76", + "openai-processing-ms": "83", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -1085,7 +1085,7 @@ "x-ratelimit-remaining-tokens": "9999985", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "cd17b8fe-5d3f-4b3a-8e19-965528fa7643" + "x-request-id": "352d49f9-cdf2-4cb5-97f9-e6ae7cfe793e" }, "status": 200, "statusText": "OK" @@ -1095,7 +1095,7 @@ "callIndex": 3, "id": "e09f32cc805b35e9", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:53.803Z", + "recordedAt": "2026-07-06T08:53:28.994Z", "request": { "body": { "kind": "json", @@ -1152,11 +1152,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905813, - "created_at": 1782905813, + "completed_at": 1783328008, + "created_at": 1783328008, "error": null, "frequency_penalty": 0, - "id": "resp_0d1670a4a982ae06006a44fbd50dd4819ca2bc96afa7993544", + "id": "resp_0caab4837986b3f6006a4b6d0835dc81a29648f60128b5682c", "incomplete_details": null, "instructions": null, "max_output_tokens": 128, @@ -1168,8 +1168,8 @@ "output": [ { "arguments": "{\"location\":\"Paris, France\"}", - "call_id": "call_2Q7v9joZrNYZM7MGcOJ7m0Kr", - "id": "fc_0d1670a4a982ae06006a44fbd5a3bc819c94f9d101027baa9c", + "call_id": "call_uPHoh5wVkNKZDjSCr3lPK1Z5", + "id": "fc_0caab4837986b3f6006a4b6d08c37c81a2bb30cd909a4d987c", "name": "get_weather", "status": "completed", "type": "function_call" @@ -1256,13 +1256,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d9309eb5a6b-VIE", + "cf-ray": "a16d6112aa355aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:53 GMT", + "date": "Mon, 06 Jul 2026 08:53:29 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "780", + "openai-processing-ms": "784", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -1273,10 +1273,10 @@ "x-ratelimit-limit-requests": "30000", "x-ratelimit-limit-tokens": "150000000", "x-ratelimit-remaining-requests": "29999", - "x-ratelimit-remaining-tokens": "149999687", + "x-ratelimit-remaining-tokens": "149999690", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "f7672a23-8157-4391-9117-b7a2795d1198" + "x-request-id": "d0f4cc66-d61f-4bb8-be06-3a834aeebcd0" }, "status": 200, "statusText": "OK" @@ -1284,9 +1284,9 @@ }, { "callIndex": 4, - "id": "ac165a19d6cc00c6", + "id": "9b6a4c88a394b4f0", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:54.765Z", + "recordedAt": "2026-07-06T08:53:29.923Z", "request": { "body": { "kind": "json", @@ -1306,11 +1306,11 @@ "role": "user" }, { - "id": "fc_0d1670a4a982ae06006a44fbd5a3bc819c94f9d101027baa9c", + "id": "fc_0caab4837986b3f6006a4b6d08c37c81a2bb30cd909a4d987c", "type": "item_reference" }, { - "call_id": "call_2Q7v9joZrNYZM7MGcOJ7m0Kr", + "call_id": "call_uPHoh5wVkNKZDjSCr3lPK1Z5", "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", "type": "function_call_output" } @@ -1352,11 +1352,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905814, - "created_at": 1782905814, + "completed_at": 1783328009, + "created_at": 1783328009, "error": null, "frequency_penalty": 0, - "id": "resp_0d1670a4a982ae06006a44fbd5ff34819c86ef100a58b377b5", + "id": "resp_0caab4837986b3f6006a4b6d09332481a288cca120db162bd0", "incomplete_details": null, "instructions": null, "max_output_tokens": 128, @@ -1368,8 +1368,8 @@ "output": [ { "arguments": "{\"location\":\"Paris, France\"}", - "call_id": "call_J2mBiH5mXs6wRrpj5za8jTbl", - "id": "fc_0d1670a4a982ae06006a44fbd69938819cbce2cd7ca7e4aa82", + "call_id": "call_b2lYM8hPhHxrfckl6q6sCCTM", + "id": "fc_0caab4837986b3f6006a4b6d09a92c81a281d78cc11a7c1ee6", "name": "get_weather", "status": "completed", "type": "function_call" @@ -1456,13 +1456,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d98fba15a6b-VIE", + "cf-ray": "a16d6118bfca5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:54 GMT", + "date": "Mon, 06 Jul 2026 08:53:29 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "803", + "openai-processing-ms": "724", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -1476,7 +1476,7 @@ "x-ratelimit-remaining-tokens": "149999650", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "e58ea406-fd31-408a-8dca-9a98622087d1" + "x-request-id": "211242b1-c91a-4d2d-ba76-441c83f3aaa9" }, "status": 200, "statusText": "OK" @@ -1484,9 +1484,9 @@ }, { "callIndex": 5, - "id": "9953f150c1ffa8a0", + "id": "ae415b8842be2ef3", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:56.030Z", + "recordedAt": "2026-07-06T08:53:31.120Z", "request": { "body": { "kind": "json", @@ -1506,20 +1506,20 @@ "role": "user" }, { - "id": "fc_0d1670a4a982ae06006a44fbd5a3bc819c94f9d101027baa9c", + "id": "fc_0caab4837986b3f6006a4b6d08c37c81a2bb30cd909a4d987c", "type": "item_reference" }, { - "call_id": "call_2Q7v9joZrNYZM7MGcOJ7m0Kr", + "call_id": "call_uPHoh5wVkNKZDjSCr3lPK1Z5", "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", "type": "function_call_output" }, { - "id": "fc_0d1670a4a982ae06006a44fbd69938819cbce2cd7ca7e4aa82", + "id": "fc_0caab4837986b3f6006a4b6d09a92c81a281d78cc11a7c1ee6", "type": "item_reference" }, { - "call_id": "call_J2mBiH5mXs6wRrpj5za8jTbl", + "call_id": "call_b2lYM8hPhHxrfckl6q6sCCTM", "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", "type": "function_call_output" } @@ -1561,11 +1561,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905815, - "created_at": 1782905815, + "completed_at": 1783328010, + "created_at": 1783328010, "error": null, "frequency_penalty": 0, - "id": "resp_0d1670a4a982ae06006a44fbd6f700819cb7ac7acf214ce1d8", + "id": "resp_0caab4837986b3f6006a4b6d0a212481a2a92808d995b1e13e", "incomplete_details": null, "instructions": null, "max_output_tokens": 128, @@ -1577,8 +1577,8 @@ "output": [ { "arguments": "{\"location\":\"Paris, France\"}", - "call_id": "call_EyyNRQfPYeHhb9lc8TNZ6WtZ", - "id": "fc_0d1670a4a982ae06006a44fbd7c610819cb4841356f23c3429", + "call_id": "call_tlq2OdrQF8d7RsHw1f9kOjgm", + "id": "fc_0caab4837986b3f6006a4b6d0aacdc81a2be14bc16ed684d76", "name": "get_weather", "status": "completed", "type": "function_call" @@ -1665,13 +1665,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451d9efdf95a6b-VIE", + "cf-ray": "a16d611eac8e5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:56 GMT", + "date": "Mon, 06 Jul 2026 08:53:31 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "1099", + "openai-processing-ms": "999", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -1682,10 +1682,10 @@ "x-ratelimit-limit-requests": "30000", "x-ratelimit-limit-tokens": "150000000", "x-ratelimit-remaining-requests": "29999", - "x-ratelimit-remaining-tokens": "149999612", + "x-ratelimit-remaining-tokens": "149999610", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "f29f86b4-fa2a-4168-8945-db203ca8ca05" + "x-request-id": "dcca3c6a-9195-4a30-a312-1ff18980bd0a" }, "status": 200, "statusText": "OK" @@ -1693,9 +1693,9 @@ }, { "callIndex": 6, - "id": "bf0ae6643e03845d", + "id": "9f78724fde1e3868", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:57.177Z", + "recordedAt": "2026-07-06T08:53:32.169Z", "request": { "body": { "kind": "json", @@ -1715,29 +1715,29 @@ "role": "user" }, { - "id": "fc_0d1670a4a982ae06006a44fbd5a3bc819c94f9d101027baa9c", + "id": "fc_0caab4837986b3f6006a4b6d08c37c81a2bb30cd909a4d987c", "type": "item_reference" }, { - "call_id": "call_2Q7v9joZrNYZM7MGcOJ7m0Kr", + "call_id": "call_uPHoh5wVkNKZDjSCr3lPK1Z5", "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", "type": "function_call_output" }, { - "id": "fc_0d1670a4a982ae06006a44fbd69938819cbce2cd7ca7e4aa82", + "id": "fc_0caab4837986b3f6006a4b6d09a92c81a281d78cc11a7c1ee6", "type": "item_reference" }, { - "call_id": "call_J2mBiH5mXs6wRrpj5za8jTbl", + "call_id": "call_b2lYM8hPhHxrfckl6q6sCCTM", "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", "type": "function_call_output" }, { - "id": "fc_0d1670a4a982ae06006a44fbd7c610819cb4841356f23c3429", + "id": "fc_0caab4837986b3f6006a4b6d0aacdc81a2be14bc16ed684d76", "type": "item_reference" }, { - "call_id": "call_EyyNRQfPYeHhb9lc8TNZ6WtZ", + "call_id": "call_tlq2OdrQF8d7RsHw1f9kOjgm", "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", "type": "function_call_output" } @@ -1779,11 +1779,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905817, - "created_at": 1782905816, + "completed_at": 1783328012, + "created_at": 1783328011, "error": null, "frequency_penalty": 0, - "id": "resp_0d1670a4a982ae06006a44fbd8401c819ca9812b93377bfe47", + "id": "resp_0caab4837986b3f6006a4b6d0b5a9881a2930159c9c160222f", "incomplete_details": null, "instructions": null, "max_output_tokens": 128, @@ -1795,8 +1795,8 @@ "output": [ { "arguments": "{\"location\":\"Paris, France\"}", - "call_id": "call_m9y7HRD5gRKrWDTEZXJOTdm6", - "id": "fc_0d1670a4a982ae06006a44fbd8efd4819cb6b504cf8fbc2cfc", + "call_id": "call_KYYvnyVTxE0db1wyzGVFcYU8", + "id": "fc_0caab4837986b3f6006a4b6d0bf69481a28e1594f775c219ba", "name": "get_weather", "status": "completed", "type": "function_call" @@ -1883,13 +1883,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451da6f9325a6b-VIE", + "cf-ray": "a16d61263b0b5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:57 GMT", + "date": "Mon, 06 Jul 2026 08:53:32 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "964", + "openai-processing-ms": "826", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -1903,7 +1903,7 @@ "x-ratelimit-remaining-tokens": "149999572", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "063a6d44-dea2-4039-88c5-257076e01b2d" + "x-request-id": "92470d24-a2e0-47b9-a2b4-5d4479b92169" }, "status": 200, "statusText": "OK" @@ -1913,7 +1913,7 @@ "callIndex": 7, "id": "d22bae6c42006c81", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:57.945Z", + "recordedAt": "2026-07-06T08:53:33.095Z", "request": { "body": { "kind": "json", @@ -1964,11 +1964,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905817, - "created_at": 1782905817, + "completed_at": 1783328012, + "created_at": 1783328012, "error": null, "frequency_penalty": 0, - "id": "resp_07d0eacb5e020f19006a44fbd9638c8191bf06a3346592d6d4", + "id": "resp_003585194981413b006a4b6d0c5fb481a2ba6831476429edaf", "incomplete_details": null, "instructions": null, "max_output_tokens": 32, @@ -1987,7 +1987,7 @@ "type": "output_text" } ], - "id": "msg_07d0eacb5e020f19006a44fbd9cd088191a86403d6e5e83780", + "id": "msg_003585194981413b006a4b6d0cd2ec81a2a5bd89e6f6b8a596", "role": "assistant", "status": "completed", "type": "message" @@ -2068,13 +2068,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451dae0b145a6b-VIE", + "cf-ray": "a16d612ca8305aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:36:58 GMT", + "date": "Mon, 06 Jul 2026 08:53:33 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "588", + "openai-processing-ms": "731", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -2088,7 +2088,7 @@ "x-ratelimit-remaining-tokens": "149999942", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "0c9b409a-3a76-498e-847f-a6f8b8b0a32b" + "x-request-id": "fb0920af-5187-4814-a672-0f116571ab5a" }, "status": 200, "statusText": "OK" @@ -2098,7 +2098,7 @@ "callIndex": 8, "id": "6d0eec1cfcef015d", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:36:58.917Z", + "recordedAt": "2026-07-06T08:53:34.025Z", "request": { "body": { "kind": "json", @@ -2145,19 +2145,19 @@ "response": { "body": { "chunks": [ - "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0f2b6bcc380a0fa0006a44fbda2d208192a2aadb0ba544e277\",\"object\":\"response\",\"created_at\":1782905818,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"json_schema\",\"description\":null,\"name\":\"response\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false},\"strict\":true},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", - "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0f2b6bcc380a0fa0006a44fbda2d208192a2aadb0ba544e277\",\"object\":\"response\",\"created_at\":1782905818,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"json_schema\",\"description\":null,\"name\":\"response\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false},\"strict\":true},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", - "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":2}", - "event: response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"content_index\":0,\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"},\"sequence_number\":3}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"{\\\"\",\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"logprobs\":[],\"obfuscation\":\"2DliUQjkuLhdNV\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"city\",\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"logprobs\":[],\"obfuscation\":\"1HdUFHZ9vH30\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\\":\\\"\",\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"logprobs\":[],\"obfuscation\":\"dvUetfHZwh9cp\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"Paris\",\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"logprobs\":[],\"obfuscation\":\"EUsYDfvOvNR\",\"output_index\":0,\"sequence_number\":7}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\\"}\",\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"logprobs\":[],\"obfuscation\":\"gpCUzuQR1TaHJZ\",\"output_index\":0,\"sequence_number\":8}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":9,\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"},\"sequence_number\":10}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":11}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0f2b6bcc380a0fa0006a44fbda2d208192a2aadb0ba544e277\",\"object\":\"response\",\"created_at\":1782905818,\"status\":\"completed\",\"background\":false,\"completed_at\":1782905818,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0f2b6bcc380a0fa0006a44fbdac0f88192a9cf5e86637b442d\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"json_schema\",\"description\":null,\"name\":\"response\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false},\"strict\":true},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":38,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":6,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":44},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0e3e39a329d01370006a4b6d0d47d0819db59a5d3fc8acd6b1\",\"object\":\"response\",\"created_at\":1783328013,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"json_schema\",\"description\":null,\"name\":\"response\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false},\"strict\":true},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0e3e39a329d01370006a4b6d0d47d0819db59a5d3fc8acd6b1\",\"object\":\"response\",\"created_at\":1783328013,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"json_schema\",\"description\":null,\"name\":\"response\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false},\"strict\":true},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"content_index\":0,\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"},\"sequence_number\":3}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"{\\\"\",\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"logprobs\":[],\"obfuscation\":\"yWGpZd99sDs70T\",\"output_index\":0,\"sequence_number\":4}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"city\",\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"logprobs\":[],\"obfuscation\":\"16GhzskcFZTK\",\"output_index\":0,\"sequence_number\":5}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\\":\\\"\",\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"logprobs\":[],\"obfuscation\":\"LCim3MlHAEzck\",\"output_index\":0,\"sequence_number\":6}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"Paris\",\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"logprobs\":[],\"obfuscation\":\"DymF0o0Tv1u\",\"output_index\":0,\"sequence_number\":7}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\\"}\",\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"logprobs\":[],\"obfuscation\":\"GcdTqXNYXaZcHR\",\"output_index\":0,\"sequence_number\":8}", + "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":9,\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"}", + "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"},\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0e3e39a329d01370006a4b6d0d47d0819db59a5d3fc8acd6b1\",\"object\":\"response\",\"created_at\":1783328013,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328013,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0e3e39a329d01370006a4b6d0dd8ec819db912cdc945eafd3a\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"{\\\"city\\\":\\\"Paris\\\"}\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"json_schema\",\"description\":null,\"name\":\"response\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false},\"strict\":true},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":38,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":6,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":44},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" ], "kind": "sse" }, @@ -2165,12 +2165,12 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451db2ec825a6b-VIE", + "cf-ray": "a16d61326cea5aad-VIE", "connection": "keep-alive", "content-type": "text/event-stream; charset=utf-8", - "date": "Wed, 01 Jul 2026 11:36:58 GMT", + "date": "Mon, 06 Jul 2026 08:53:33 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "183", + "openai-processing-ms": "153", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -2178,7 +2178,7 @@ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-request-id": "038452fa-ef3f-4fa7-9905-b960091f7fb9" + "x-request-id": "fde2d8bf-fcf0-45ae-a8ad-cea0c9518525" }, "status": 200, "statusText": "OK" @@ -2188,7 +2188,7 @@ "callIndex": 9, "id": "3f08b53881e505ce", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:37:00.098Z", + "recordedAt": "2026-07-06T08:53:34.935Z", "request": { "body": { "kind": "json", @@ -2224,11 +2224,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905819, - "created_at": 1782905819, + "completed_at": 1783328014, + "created_at": 1783328014, "error": null, "frequency_penalty": 0, - "id": "resp_0a0c15d796c6a34f006a44fbdb2284819fb736e3e820c1a23b", + "id": "resp_04dc557d9132a956006a4b6d0e412481a38f3691b337903577", "incomplete_details": null, "instructions": null, "max_output_tokens": 24, @@ -2247,7 +2247,7 @@ "type": "output_text" } ], - "id": "msg_0a0c15d796c6a34f006a44fbdbc284819fb41f32c54acf1f53", + "id": "msg_04dc557d9132a956006a4b6d0eb4ac81a386e45b83baf9f982", "role": "assistant", "status": "completed", "type": "message" @@ -2315,13 +2315,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451db8fe9d5a6b-VIE", + "cf-ray": "a16d61382a4f5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:37:00 GMT", + "date": "Mon, 06 Jul 2026 08:53:34 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "908", + "openai-processing-ms": "727", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -2335,7 +2335,7 @@ "x-ratelimit-remaining-tokens": "149999955", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "04232a6b-5e31-45df-82dd-a90abcd939c6" + "x-request-id": "5c886032-1b82-493f-b6c4-5163897458d5" }, "status": 200, "statusText": "OK" @@ -2345,7 +2345,7 @@ "callIndex": 10, "id": "d026123ce87dfbca", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:37:01.278Z", + "recordedAt": "2026-07-06T08:53:35.966Z", "request": { "body": { "kind": "json", @@ -2377,17 +2377,17 @@ "response": { "body": { "chunks": [ - "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0e769a01cfb03e99006a44fbdc61dc819fb50fcb4e64cab6ba\",\"object\":\"response\",\"created_at\":1782905820,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":24,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", - "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0e769a01cfb03e99006a44fbdc61dc819fb50fcb4e64cab6ba\",\"object\":\"response\",\"created_at\":1782905820,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":24,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", - "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":2}", - "event: response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"content_index\":0,\"item_id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"},\"sequence_number\":3}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"STREAM\",\"item_id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"logprobs\":[],\"obfuscation\":\"hTnuV2wiJV\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" HEL\",\"item_id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"logprobs\":[],\"obfuscation\":\"BHAgzgld0ZoK\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"LO\",\"item_id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"logprobs\":[],\"obfuscation\":\"XjE1Ce8MJwWqVW\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":7,\"text\":\"STREAM HELLO\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"STREAM HELLO\"},\"sequence_number\":8}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"STREAM HELLO\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":9}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0e769a01cfb03e99006a44fbdc61dc819fb50fcb4e64cab6ba\",\"object\":\"response\",\"created_at\":1782905820,\"status\":\"completed\",\"background\":false,\"completed_at\":1782905821,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":24,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0e769a01cfb03e99006a44fbdd1c34819f847b257326c553a3\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"STREAM HELLO\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":27,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":4,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":31},\"user\":null,\"metadata\":{}},\"sequence_number\":10}" + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0fdfc89918dfb647006a4b6d0f1c448191be0936749c3a47eb\",\"object\":\"response\",\"created_at\":1783328015,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":24,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0fdfc89918dfb647006a4b6d0f1c448191be0936749c3a47eb\",\"object\":\"response\",\"created_at\":1783328015,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":24,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"type\":\"message\",\"status\":\"in_progress\",\"content\":[],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.content_part.added\ndata: {\"type\":\"response.content_part.added\",\"content_index\":0,\"item_id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"\"},\"sequence_number\":3}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"STREAM\",\"item_id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"logprobs\":[],\"obfuscation\":\"EpB2gtNkAs\",\"output_index\":0,\"sequence_number\":4}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" HEL\",\"item_id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"logprobs\":[],\"obfuscation\":\"SSohZL0w9RNn\",\"output_index\":0,\"sequence_number\":5}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"LO\",\"item_id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"logprobs\":[],\"obfuscation\":\"UtKesBmgN7Wvvm\",\"output_index\":0,\"sequence_number\":6}", + "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":7,\"text\":\"STREAM HELLO\"}", + "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"STREAM HELLO\"},\"sequence_number\":8}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"STREAM HELLO\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":9}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0fdfc89918dfb647006a4b6d0f1c448191be0936749c3a47eb\",\"object\":\"response\",\"created_at\":1783328015,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328015,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":24,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0fdfc89918dfb647006a4b6d0fc00c8191aa908f3f0ef2c92c\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"STREAM HELLO\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":27,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":4,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":31},\"user\":null,\"metadata\":{}},\"sequence_number\":10}" ], "kind": "sse" }, @@ -2395,12 +2395,12 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451dc058b05a6b-VIE", + "cf-ray": "a16d613ddef85aad-VIE", "connection": "keep-alive", "content-type": "text/event-stream; charset=utf-8", - "date": "Wed, 01 Jul 2026 11:37:00 GMT", + "date": "Mon, 06 Jul 2026 08:53:35 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "245", + "openai-processing-ms": "215", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -2408,7 +2408,7 @@ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-request-id": "470f07ce-d6bf-49d8-9e80-3e076c946f99" + "x-request-id": "6af124a7-87b3-47d0-a7b8-901c2998a309" }, "status": 200, "statusText": "OK" @@ -2418,7 +2418,7 @@ "callIndex": 11, "id": "34ad62d7c96775e7", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:37:04.625Z", + "recordedAt": "2026-07-06T08:53:37.756Z", "request": { "body": { "kind": "json", @@ -2518,11 +2518,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905824, - "created_at": 1782905821, + "completed_at": 1783328017, + "created_at": 1783328016, "error": null, "frequency_penalty": 0, - "id": "resp_05a90b95f7a788b5006a44fbdd814c81a3baad795e58c3a0e1", + "id": "resp_0e66d4cf3b44aa7f006a4b6d10291481a2b12b390c95d5211a", "incomplete_details": null, "instructions": null, "max_output_tokens": 256, @@ -2534,16 +2534,16 @@ "output": [ { "arguments": "{\"item\":\"laptop\",\"store\":\"StoreA\"}", - "call_id": "call_8GGuS9G3qXOu0uQjVEsKgw1t", - "id": "fc_05a90b95f7a788b5006a44fbe05b4c81a3b5987ee6fd97b39f", + "call_id": "call_qRuXzm1GdT1ybr2tWRFjAvX7", + "id": "fc_0e66d4cf3b44aa7f006a4b6d11a20481a2861ceb3b6811d1b6", "name": "get_store_price", "status": "completed", "type": "function_call" }, { "arguments": "{\"item\":\"laptop\",\"store\":\"StoreB\"}", - "call_id": "call_lLjZSipWvTnUgrfgIhcwNsBk", - "id": "fc_05a90b95f7a788b5006a44fbe05b6481a38c617a786b550ef3", + "call_id": "call_hITB5sbet06fDK494deB5ZIz", + "id": "fc_0e66d4cf3b44aa7f006a4b6d11a21881a28cbf7de8a8e33987", "name": "get_store_price", "status": "completed", "type": "function_call" @@ -2656,13 +2656,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451dc7cb805a6b-VIE", + "cf-ray": "a16d61445cdc5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:37:04 GMT", + "date": "Mon, 06 Jul 2026 08:53:37 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "3170", + "openai-processing-ms": "1604", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -2676,7 +2676,7 @@ "x-ratelimit-remaining-tokens": "149999610", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "0d0edd0f-d34b-41f6-bf81-c4924d539f1f" + "x-request-id": "f9f16014-5e8d-4941-8e99-1df4baae54be" }, "status": 200, "statusText": "OK" @@ -2684,9 +2684,9 @@ }, { "callIndex": 12, - "id": "9f95a51ba8770b2c", + "id": "6ddea796e2e4a7cc", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:37:06.632Z", + "recordedAt": "2026-07-06T08:53:38.809Z", "request": { "body": { "kind": "json", @@ -2724,20 +2724,20 @@ "role": "user" }, { - "id": "fc_05a90b95f7a788b5006a44fbe05b4c81a3b5987ee6fd97b39f", + "id": "fc_0e66d4cf3b44aa7f006a4b6d11a20481a2861ceb3b6811d1b6", "type": "item_reference" }, { - "id": "fc_05a90b95f7a788b5006a44fbe05b6481a38c617a786b550ef3", + "id": "fc_0e66d4cf3b44aa7f006a4b6d11a21881a28cbf7de8a8e33987", "type": "item_reference" }, { - "call_id": "call_8GGuS9G3qXOu0uQjVEsKgw1t", + "call_id": "call_qRuXzm1GdT1ybr2tWRFjAvX7", "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", "type": "function_call_output" }, { - "call_id": "call_lLjZSipWvTnUgrfgIhcwNsBk", + "call_id": "call_hITB5sbet06fDK494deB5ZIz", "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", "type": "function_call_output" } @@ -2804,11 +2804,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905826, - "created_at": 1782905825, + "completed_at": 1783328018, + "created_at": 1783328017, "error": null, "frequency_penalty": 0, - "id": "resp_05a90b95f7a788b5006a44fbe111fc81a3af1e565785a2640c", + "id": "resp_0e66d4cf3b44aa7f006a4b6d11edcc81a289056b28896bd29b", "incomplete_details": null, "instructions": null, "max_output_tokens": 256, @@ -2820,8 +2820,8 @@ "output": [ { "arguments": "{\"discountCode\":\"SAVE20\",\"total\":999}", - "call_id": "call_1fMn3W7IWFXGflea0D6gbIW0", - "id": "fc_05a90b95f7a788b5006a44fbe210fc81a3b1afb5c0bda84357", + "call_id": "call_ctBQl0V8LZYr2ghBNzEbmtNW", + "id": "fc_0e66d4cf3b44aa7f006a4b6d128a6481a2a78d18759b1ec966", "name": "apply_discount", "status": "completed", "type": "function_call" @@ -2934,13 +2934,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451ddcaa4e5a6b-VIE", + "cf-ray": "a16d614f7ddc5aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:37:06 GMT", + "date": "Mon, 06 Jul 2026 08:53:38 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "1806", + "openai-processing-ms": "887", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -2954,7 +2954,7 @@ "x-ratelimit-remaining-tokens": "149999522", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "459dc5f6-acb9-474b-991a-5181e7dac227" + "x-request-id": "66efab58-48de-4948-b683-79d1232307ff" }, "status": 200, "statusText": "OK" @@ -2962,9 +2962,9 @@ }, { "callIndex": 13, - "id": "058eaddbb1690160", + "id": "0e183332ea3f5ed7", "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-07-01T11:37:09.462Z", + "recordedAt": "2026-07-06T08:53:46.606Z", "request": { "body": { "kind": "json", @@ -3002,29 +3002,29 @@ "role": "user" }, { - "id": "fc_05a90b95f7a788b5006a44fbe05b4c81a3b5987ee6fd97b39f", + "id": "fc_0e66d4cf3b44aa7f006a4b6d11a20481a2861ceb3b6811d1b6", "type": "item_reference" }, { - "id": "fc_05a90b95f7a788b5006a44fbe05b6481a38c617a786b550ef3", + "id": "fc_0e66d4cf3b44aa7f006a4b6d11a21881a28cbf7de8a8e33987", "type": "item_reference" }, { - "call_id": "call_8GGuS9G3qXOu0uQjVEsKgw1t", + "call_id": "call_qRuXzm1GdT1ybr2tWRFjAvX7", "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", "type": "function_call_output" }, { - "call_id": "call_lLjZSipWvTnUgrfgIhcwNsBk", + "call_id": "call_hITB5sbet06fDK494deB5ZIz", "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", "type": "function_call_output" }, { - "id": "fc_05a90b95f7a788b5006a44fbe210fc81a3b1afb5c0bda84357", + "id": "fc_0e66d4cf3b44aa7f006a4b6d128a6481a2a78d18759b1ec966", "type": "item_reference" }, { - "call_id": "call_1fMn3W7IWFXGflea0D6gbIW0", + "call_id": "call_ctBQl0V8LZYr2ghBNzEbmtNW", "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", "type": "function_call_output" } @@ -3091,11 +3091,11 @@ "billing": { "payer": "developer" }, - "completed_at": 1782905829, - "created_at": 1782905827, + "completed_at": 1783328025, + "created_at": 1783328021, "error": null, "frequency_penalty": 0, - "id": "resp_05a90b95f7a788b5006a44fbe30f2081a38db9d8811b348009", + "id": "resp_0e66d4cf3b44aa7f006a4b6d1415ec81a2b2537cecc1b12662", "incomplete_details": null, "instructions": null, "max_output_tokens": 256, @@ -3114,7 +3114,7 @@ "type": "output_text" } ], - "id": "msg_05a90b95f7a788b5006a44fbe3dc2c81a39292caa71b0ff248", + "id": "msg_0e66d4cf3b44aa7f006a4b6d16b89881a2b76a79a154e36a02", "role": "assistant", "status": "completed", "type": "message" @@ -3227,13 +3227,13 @@ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "a1451de93ec35a6b-VIE", + "cf-ray": "a16d61562c445aad-VIE", "connection": "keep-alive", "content-encoding": "gzip", "content-type": "application/json", - "date": "Wed, 01 Jul 2026 11:37:09 GMT", + "date": "Mon, 06 Jul 2026 08:53:46 GMT", "openai-organization": "braintrust-data", - "openai-processing-ms": "2552", + "openai-processing-ms": "7482", "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", "openai-version": "2020-10-01", "server": "cloudflare", @@ -3247,7 +3247,907 @@ "x-ratelimit-remaining-tokens": "149999475", "x-ratelimit-reset-requests": "2ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "e566f085-89cd-4852-a34c-b7d7e0b2f196" + "x-request-id": "59075f75-1ca7-44e1-a648-4094286b2f6e" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 14, + "id": "cab5f9a41efafafd", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:48.116Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "input_text" + } + ], + "role": "user" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_064eb500041e3d7b006a4b6d1acd6081a08258b83417ce9fea\",\"object\":\"response\",\"created_at\":1783328026,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_064eb500041e3d7b006a4b6d1acd6081a08258b83417ce9fea\",\"object\":\"response\",\"created_at\":1783328026,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_5AIVB5vSHGUszN8aascCN8xJ\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"OkuRaQCX5s9HFg\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"UdRdArKv\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"V1MNXf2yt4ich\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"dCuDgR1QoJr\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"5XSVdLtobTnwyKv\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"FypA4Jpk7\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"obfuscation\":\"LLZuT9mLU2fgid\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_5AIVB5vSHGUszN8aascCN8xJ\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_064eb500041e3d7b006a4b6d1acd6081a08258b83417ce9fea\",\"object\":\"response\",\"created_at\":1783328026,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328027,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_064eb500041e3d7b006a4b6d1be13081a0965472c3d4cdeff5\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_5AIVB5vSHGUszN8aascCN8xJ\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":84,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":92},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d6186ef795aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:46 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "112", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "cbf329cf-f33a-42fd-bc9f-69aa7673b468" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 15, + "id": "0b49ee234aab4656", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:49.035Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "input_text" + } + ], + "role": "user" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_5AIVB5vSHGUszN8aascCN8xJ", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_5AIVB5vSHGUszN8aascCN8xJ", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0c20e36e3e222036006a4b6d1c52988192bce54ff9da85f125\",\"object\":\"response\",\"created_at\":1783328028,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0c20e36e3e222036006a4b6d1c52988192bce54ff9da85f125\",\"object\":\"response\",\"created_at\":1783328028,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_LSPBIYKfl1M6FSlK9XJtVeiO\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"fiqSASpwbqFt6d\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"ZPKYMXVG\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"xcrfyU4FLZkzA\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"j6zpXowyrUA\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"2psGeVqqoQUxvHR\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"iZqyReECw\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"obfuscation\":\"ORjPzay7MM7dI0\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_LSPBIYKfl1M6FSlK9XJtVeiO\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0c20e36e3e222036006a4b6d1c52988192bce54ff9da85f125\",\"object\":\"response\",\"created_at\":1783328028,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328028,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_0c20e36e3e222036006a4b6d1cd5548192a1dd0eeffc1c7eab\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_LSPBIYKfl1M6FSlK9XJtVeiO\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":123,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":131},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d61905ff95aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:48 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "112", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "5c6a35fd-3014-4b59-b63a-ddf7fbd24ca4" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 16, + "id": "f52dd9eeb4304bc1", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:50.079Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "input_text" + } + ], + "role": "user" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_5AIVB5vSHGUszN8aascCN8xJ", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_5AIVB5vSHGUszN8aascCN8xJ", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_LSPBIYKfl1M6FSlK9XJtVeiO", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_LSPBIYKfl1M6FSlK9XJtVeiO", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_00f354b569648596006a4b6d1d3c8c81a1bd90c2ff82573f85\",\"object\":\"response\",\"created_at\":1783328029,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_00f354b569648596006a4b6d1d3c8c81a1bd90c2ff82573f85\",\"object\":\"response\",\"created_at\":1783328029,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_nORuCt6uo5JHX9qQgL4igzTH\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"Bkl8hB7JcIpkJv\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"Wbc07vFJ\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"Rz2QqSRblCxeQ\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"kc7vNgvuGDC\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"icn1uVdX2nxbX27\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"v7VRHR8uj\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"obfuscation\":\"I9jJZhJjwV0e1A\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_nORuCt6uo5JHX9qQgL4igzTH\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_00f354b569648596006a4b6d1d3c8c81a1bd90c2ff82573f85\",\"object\":\"response\",\"created_at\":1783328029,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328029,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_00f354b569648596006a4b6d1dc0a081a181f1e59301707eb3\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_nORuCt6uo5JHX9qQgL4igzTH\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":162,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":170},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d61961cf75aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:49 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "121", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "1eaf27f7-d77c-4f57-8505-47f5d28d73eb" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 17, + "id": "a68527dff479ce1a", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:51.156Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "input_text" + } + ], + "role": "user" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_5AIVB5vSHGUszN8aascCN8xJ", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_5AIVB5vSHGUszN8aascCN8xJ", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_LSPBIYKfl1M6FSlK9XJtVeiO", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_LSPBIYKfl1M6FSlK9XJtVeiO", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_nORuCt6uo5JHX9qQgL4igzTH", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_nORuCt6uo5JHX9qQgL4igzTH", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_00b42cb4bbd1b388006a4b6d1e497881918894594cf169c226\",\"object\":\"response\",\"created_at\":1783328030,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_00b42cb4bbd1b388006a4b6d1e497881918894594cf169c226\",\"object\":\"response\",\"created_at\":1783328030,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_jjs2MC18QafQPqZemWS4kXgw\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"j0mi4UlzeMphQv\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"dj6dKDu6\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"zkhqEwGsI6aX8\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"fgfoKAiUD70\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"huBJPyXcDzjNAXs\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"a4L6zHdTD\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"obfuscation\":\"nXfk1UxRowa3sY\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_jjs2MC18QafQPqZemWS4kXgw\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_00b42cb4bbd1b388006a4b6d1e497881918894594cf169c226\",\"object\":\"response\",\"created_at\":1783328030,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328031,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_00b42cb4bbd1b388006a4b6d1ee5d481918c41445b056cc967\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_jjs2MC18QafQPqZemWS4kXgw\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":201,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":209},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d619caa8a5aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:50 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "126", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "e76ad19e-2fa6-43dd-b11e-7fa17b1ac4c5" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 18, + "id": "68b95c3d415edc61", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:52.253Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "input_text" + } + ], + "role": "user" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_01586087756ed932006a4b6d1f6028819faeca3634812ce6ea\",\"object\":\"response\",\"created_at\":1783328031,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_01586087756ed932006a4b6d1f6028819faeca3634812ce6ea\",\"object\":\"response\",\"created_at\":1783328031,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_gFUshjUsV3Ngpz52OkpiA6kM\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"2dRqBFyzkrMyXG\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"wmcABcZF\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"QUCDK79DMSMwo\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"POTokfq76ok\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"Y07a5VP6ioyMzme\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"RcvOEUy4p\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"obfuscation\":\"o3IPdeAUOkuBI1\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_gFUshjUsV3Ngpz52OkpiA6kM\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_01586087756ed932006a4b6d1f6028819faeca3634812ce6ea\",\"object\":\"response\",\"created_at\":1783328031,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328032,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_01586087756ed932006a4b6d1fe184819f81f81da643dbb253\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_gFUshjUsV3Ngpz52OkpiA6kM\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":70,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":78},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d61a36f965aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:51 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "170", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "7bd3cd02-c866-4902-bdc9-844672f3b94d" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 19, + "id": "f9284ed3b3492200", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:53.596Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "input_text" + } + ], + "role": "user" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_gFUshjUsV3Ngpz52OkpiA6kM", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_gFUshjUsV3Ngpz52OkpiA6kM", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0f0a2a2ca33b9910006a4b6d2070b4819d82eaf124a4e9ff1c\",\"object\":\"response\",\"created_at\":1783328032,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0f0a2a2ca33b9910006a4b6d2070b4819d82eaf124a4e9ff1c\",\"object\":\"response\",\"created_at\":1783328032,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_uWdCfipoF3A6UyD5Qb5OQ3LG\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"bFC2GcoaJerSGU\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"l57tHvPW\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"vPFgU0VShWpoH\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"3L11DWI7m37\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"ggklGwtzU5dQSUu\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"TjVD8Y728\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"obfuscation\":\"c1ikOAGhuk5kCi\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_uWdCfipoF3A6UyD5Qb5OQ3LG\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0f0a2a2ca33b9910006a4b6d2070b4819d82eaf124a4e9ff1c\",\"object\":\"response\",\"created_at\":1783328032,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328033,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_0f0a2a2ca33b9910006a4b6d20f694819d922848ed49f521d0\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_uWdCfipoF3A6UyD5Qb5OQ3LG\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":109,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":117},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d61aa1d175aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:52 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "105", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "f920f0b6-c64c-4732-a4d5-3b44a7835cc0" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 20, + "id": "6eb37c8b04f90420", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:54.498Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "input_text" + } + ], + "role": "user" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_gFUshjUsV3Ngpz52OkpiA6kM", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_gFUshjUsV3Ngpz52OkpiA6kM", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_uWdCfipoF3A6UyD5Qb5OQ3LG", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_uWdCfipoF3A6UyD5Qb5OQ3LG", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_02179691be6473eb006a4b6d21cd5c81a3ac76d5467f556bb8\",\"object\":\"response\",\"created_at\":1783328033,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_02179691be6473eb006a4b6d21cd5c81a3ac76d5467f556bb8\",\"object\":\"response\",\"created_at\":1783328033,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_NGVAl0rG3LkwBJ4UnY1JdIZC\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"cf8jnM4GOr6Tg3\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"BUaoGkre\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"kZXu6Yj5BO3M4\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"pKeRQKSy05f\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"ZPA18WwZAyjiRPF\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"ZOoayP7MD\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"obfuscation\":\"sa0sqp8sLoRR8z\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_NGVAl0rG3LkwBJ4UnY1JdIZC\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_02179691be6473eb006a4b6d21cd5c81a3ac76d5467f556bb8\",\"object\":\"response\",\"created_at\":1783328033,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328034,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_02179691be6473eb006a4b6d22483081a3a921fdee1de11029\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_NGVAl0rG3LkwBJ4UnY1JdIZC\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":148,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":156},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d61b28ccc5aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:54 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "176", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "fc2f8882-bee5-430c-977e-474aa9c4aac8" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 21, + "id": "6594f6ae56bdc869", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-07-06T08:53:55.553Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "input_text" + } + ], + "role": "user" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_gFUshjUsV3Ngpz52OkpiA6kM", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_gFUshjUsV3Ngpz52OkpiA6kM", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_uWdCfipoF3A6UyD5Qb5OQ3LG", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_uWdCfipoF3A6UyD5Qb5OQ3LG", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + }, + { + "arguments": "{\"location\":\"Paris, France\"}", + "call_id": "call_NGVAl0rG3LkwBJ4UnY1JdIZC", + "name": "get_weather", + "type": "function_call" + }, + { + "call_id": "call_NGVAl0rG3LkwBJ4UnY1JdIZC", + "output": "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}", + "type": "function_call_output" + } + ], + "max_output_tokens": 96, + "model": "gpt-4o-mini-2024-07-18", + "stream": true, + "temperature": 0, + "tool_choice": "required", + "tools": [ + { + "description": "Get the weather for a location", + "name": "get_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": ["location"], + "type": "object" + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0338e52f512e684a006a4b6d22bb28819facf63544413e5d52\",\"object\":\"response\",\"created_at\":1783328034,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":0}", + "event: response.in_progress\ndata: {\"type\":\"response.in_progress\",\"response\":{\"id\":\"resp_0338e52f512e684a006a4b6d22bb28819facf63544413e5d52\",\"object\":\"response\",\"created_at\":1783328034,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":null,\"user\":null,\"metadata\":{}},\"sequence_number\":1}", + "event: response.output_item.added\ndata: {\"type\":\"response.output_item.added\",\"item\":{\"id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_ZUgQJ3wz7qrugXUvrpsLkOmF\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":2}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"mz6WJLzKNuQVtL\",\"output_index\":0,\"sequence_number\":3}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"location\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"Tx0Nq4JI\",\"output_index\":0,\"sequence_number\":4}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"XaL6EIoZwa7FF\",\"output_index\":0,\"sequence_number\":5}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Paris\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"qBueKSuxZUe\",\"output_index\":0,\"sequence_number\":6}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\",\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"fzY51qRf1wbWidm\",\"output_index\":0,\"sequence_number\":7}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" France\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"TtYAi9o3k\",\"output_index\":0,\"sequence_number\":8}", + "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"obfuscation\":\"1hXyaNBl5dD4bJ\",\"output_index\":0,\"sequence_number\":9}", + "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"item_id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_ZUgQJ3wz7qrugXUvrpsLkOmF\",\"name\":\"get_weather\"},\"output_index\":0,\"sequence_number\":11}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0338e52f512e684a006a4b6d22bb28819facf63544413e5d52\",\"object\":\"response\",\"created_at\":1783328034,\"status\":\"completed\",\"background\":false,\"completed_at\":1783328035,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":96,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_0338e52f512e684a006a4b6d234810819f89d370ddf2dfdc97\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"location\\\":\\\"Paris, France\\\"}\",\"call_id\":\"call_ZUgQJ3wz7qrugXUvrpsLkOmF\",\"name\":\"get_weather\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":true,\"temperature\":0,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"required\",\"tool_usage\":{\"image_gen\":{\"input_tokens\":0,\"input_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"output_tokens\":0,\"output_tokens_details\":{\"image_tokens\":0,\"text_tokens\":0},\"total_tokens\":0},\"web_search\":{\"num_requests\":0}},\"tools\":[{\"type\":\"function\",\"description\":\"Get the weather for a location\",\"name\":\"get_weather\",\"parameters\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The city and country\"}},\"required\":[\"location\"],\"additionalProperties\":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"strict\":true}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":187,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":8,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":195},\"user\":null,\"metadata\":{}},\"sequence_number\":12}" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a16d61b859715aad-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 06 Jul 2026 08:53:54 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "106", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-request-id": "f2f2783a-4e97-4f00-b2eb-5fb909fe0fce" }, "status": 200, "statusText": "OK" diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.json index 879923e4a..3a9e3b97e 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.json @@ -42,9 +42,7 @@ "reasoningTokens": 0 } }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" @@ -93,11 +91,8 @@ } }, "finishReason": "stop", - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { - "headers": "", "messages": [ { "content": [ @@ -123,7 +118,6 @@ "finishReason": "stop", "isContinued": false, "response": { - "headers": "", "messages": [ { "content": [ @@ -248,9 +242,7 @@ }, "output": { "finishReason": "stop", - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "text": "One, two, three.", "warnings": [] }, @@ -380,9 +372,7 @@ "reasoningTokens": 0 } }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" @@ -466,11 +456,8 @@ } }, "finishReason": "tool-calls", - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { - "headers": "", "messages": [ { "content": [ @@ -513,7 +500,6 @@ "finishReason": "tool-calls", "isContinued": false, "response": { - "headers": "", "messages": [ { "content": [ @@ -689,9 +675,7 @@ "reasoningTokens": 0 } }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" @@ -762,11 +746,8 @@ "object": { "city": "Paris" }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -905,9 +886,7 @@ "object": { "city": "Paris" }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "warnings": [] }, "metadata": { diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.txt index 821131a25..2656453e0 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-auto-hook.span-tree.txt @@ -32,11 +32,8 @@ span_tree: │ } │ }, │ "finishReason": "stop", - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -62,7 +59,6 @@ span_tree: │ "finishReason": "stop", │ "isContinued": false, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -135,9 +131,7 @@ span_tree: │ "reasoningTokens": 0 │ } │ }, - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" @@ -185,9 +179,7 @@ span_tree: │ } │ output: { │ "finishReason": "stop", - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "text": "One, two, three.", │ "warnings": [] │ } @@ -328,11 +320,8 @@ span_tree: │ } │ }, │ "finishReason": "tool-calls", - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -375,7 +364,6 @@ span_tree: │ "finishReason": "tool-calls", │ "isContinued": false, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -544,9 +532,7 @@ span_tree: │ │ "reasoningTokens": 0 │ │ } │ │ }, - │ │ "rawResponse": { - │ │ "headers": "" - │ │ }, + │ │ "rawResponse": {}, │ │ "response": { │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" @@ -626,11 +612,8 @@ span_tree: │ "object": { │ "city": "Paris" │ }, - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -695,9 +678,7 @@ span_tree: │ "reasoningTokens": 0 │ } │ }, - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" @@ -766,9 +747,7 @@ span_tree: "object": { "city": "Paris" }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "warnings": [] } metadata: { diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.json index 879923e4a..3a9e3b97e 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.json @@ -42,9 +42,7 @@ "reasoningTokens": 0 } }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" @@ -93,11 +91,8 @@ } }, "finishReason": "stop", - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { - "headers": "", "messages": [ { "content": [ @@ -123,7 +118,6 @@ "finishReason": "stop", "isContinued": false, "response": { - "headers": "", "messages": [ { "content": [ @@ -248,9 +242,7 @@ }, "output": { "finishReason": "stop", - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "text": "One, two, three.", "warnings": [] }, @@ -380,9 +372,7 @@ "reasoningTokens": 0 } }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" @@ -466,11 +456,8 @@ } }, "finishReason": "tool-calls", - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { - "headers": "", "messages": [ { "content": [ @@ -513,7 +500,6 @@ "finishReason": "tool-calls", "isContinued": false, "response": { - "headers": "", "messages": [ { "content": [ @@ -689,9 +675,7 @@ "reasoningTokens": 0 } }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" @@ -762,11 +746,8 @@ "object": { "city": "Paris" }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "response": { - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -905,9 +886,7 @@ "object": { "city": "Paris" }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "warnings": [] }, "metadata": { diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.txt index 821131a25..2656453e0 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v3-wrapped.span-tree.txt @@ -32,11 +32,8 @@ span_tree: │ } │ }, │ "finishReason": "stop", - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -62,7 +59,6 @@ span_tree: │ "finishReason": "stop", │ "isContinued": false, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -135,9 +131,7 @@ span_tree: │ "reasoningTokens": 0 │ } │ }, - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" @@ -185,9 +179,7 @@ span_tree: │ } │ output: { │ "finishReason": "stop", - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "text": "One, two, three.", │ "warnings": [] │ } @@ -328,11 +320,8 @@ span_tree: │ } │ }, │ "finishReason": "tool-calls", - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -375,7 +364,6 @@ span_tree: │ "finishReason": "tool-calls", │ "isContinued": false, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -544,9 +532,7 @@ span_tree: │ │ "reasoningTokens": 0 │ │ } │ │ }, - │ │ "rawResponse": { - │ │ "headers": "" - │ │ }, + │ │ "rawResponse": {}, │ │ "response": { │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" @@ -626,11 +612,8 @@ span_tree: │ "object": { │ "city": "Paris" │ }, - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -695,9 +678,7 @@ span_tree: │ "reasoningTokens": 0 │ } │ }, - │ "rawResponse": { - │ "headers": "" - │ }, + │ "rawResponse": {}, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" @@ -766,9 +747,7 @@ span_tree: "object": { "city": "Paris" }, - "rawResponse": { - "headers": "" - }, + "rawResponse": {}, "warnings": [] } metadata: { diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.json index 1664279fc..8e394b55e 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.json @@ -78,8 +78,7 @@ }, "total_tokens": 20 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -140,7 +139,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -177,7 +175,6 @@ "reasoningDetails": [], "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -311,8 +308,7 @@ }, "total_tokens": 88 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -342,9 +338,6 @@ } ], "input": { - "experimental_output": { - "type": "object" - }, "maxTokens": 32, "model": { "config": { @@ -395,7 +388,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -432,7 +424,6 @@ "reasoningDetails": [], "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -730,8 +721,7 @@ }, "total_tokens": 103 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -827,7 +817,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -877,7 +866,6 @@ "reasoningDetails": [], "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1097,8 +1085,7 @@ }, "total_tokens": 64 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -1181,7 +1168,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.txt index 5ad685e6c..49cd76935 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-auto-hook.span-tree.txt @@ -43,7 +43,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -80,7 +79,6 @@ span_tree: │ "reasoningDetails": [], │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -190,8 +188,7 @@ span_tree: │ }, │ "total_tokens": 20 │ } - │ }, - │ "headers": "" + │ } │ }, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", @@ -225,9 +222,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "experimental_output": { - │ "type": "object" - │ }, │ "maxTokens": 32, │ "model": { │ "config": { @@ -278,7 +272,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -315,7 +308,6 @@ span_tree: │ "reasoningDetails": [], │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -432,8 +424,7 @@ span_tree: │ }, │ "total_tokens": 88 │ } - │ }, - │ "headers": "" + │ } │ }, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", @@ -631,7 +622,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -681,7 +671,6 @@ span_tree: │ "reasoningDetails": [], │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -894,8 +883,7 @@ span_tree: │ │ }, │ │ "total_tokens": 103 │ │ } - │ │ }, - │ │ "headers": "" + │ │ } │ │ }, │ │ "response": { │ │ "modelId": "gpt-4o-mini-2024-07-18", @@ -987,7 +975,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -1097,8 +1084,7 @@ span_tree: │ }, │ "total_tokens": 64 │ } - │ }, - │ "headers": "" + │ } │ }, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.json index 1664279fc..8e394b55e 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.json @@ -78,8 +78,7 @@ }, "total_tokens": 20 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -140,7 +139,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -177,7 +175,6 @@ "reasoningDetails": [], "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -311,8 +308,7 @@ }, "total_tokens": 88 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -342,9 +338,6 @@ } ], "input": { - "experimental_output": { - "type": "object" - }, "maxTokens": 32, "model": { "config": { @@ -395,7 +388,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -432,7 +424,6 @@ "reasoningDetails": [], "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -730,8 +721,7 @@ }, "total_tokens": 103 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -827,7 +817,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -877,7 +866,6 @@ "reasoningDetails": [], "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1097,8 +1085,7 @@ }, "total_tokens": 64 } - }, - "headers": "" + } }, "response": { "modelId": "gpt-4o-mini-2024-07-18", @@ -1181,7 +1168,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.txt index 5ad685e6c..49cd76935 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v4-wrapped.span-tree.txt @@ -43,7 +43,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -80,7 +79,6 @@ span_tree: │ "reasoningDetails": [], │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -190,8 +188,7 @@ span_tree: │ }, │ "total_tokens": 20 │ } - │ }, - │ "headers": "" + │ } │ }, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", @@ -225,9 +222,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "experimental_output": { - │ "type": "object" - │ }, │ "maxTokens": 32, │ "model": { │ "config": { @@ -278,7 +272,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -315,7 +308,6 @@ span_tree: │ "reasoningDetails": [], │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -432,8 +424,7 @@ span_tree: │ }, │ "total_tokens": 88 │ } - │ }, - │ "headers": "" + │ } │ }, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", @@ -631,7 +622,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -681,7 +671,6 @@ span_tree: │ "reasoningDetails": [], │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -894,8 +883,7 @@ span_tree: │ │ }, │ │ "total_tokens": 103 │ │ } - │ │ }, - │ │ "headers": "" + │ │ } │ │ }, │ │ "response": { │ │ "modelId": "gpt-4o-mini-2024-07-18", @@ -987,7 +975,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -1097,8 +1084,7 @@ span_tree: │ }, │ "total_tokens": 64 │ } - │ }, - │ "headers": "" + │ } │ }, │ "response": { │ "modelId": "gpt-4o-mini-2024-07-18", diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.json index 3cdf7fd03..245946982 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.json @@ -16,9 +16,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -54,7 +51,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -130,7 +126,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -172,7 +167,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -256,9 +250,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 32, "prompt": [ { @@ -310,7 +301,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -343,25 +333,6 @@ } ], "input": { - "experimental_output": { - "responseFormat": { - "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "answer": { - "type": "string" - } - }, - "required": [ - "answer" - ], - "type": "object" - }, - "type": "json" - }, - "type": "object" - }, "maxOutputTokens": 32, "model": { "config": { @@ -424,7 +395,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -466,7 +436,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -689,9 +658,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -756,7 +722,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -801,9 +766,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -898,7 +860,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -943,9 +904,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1070,7 +1028,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1115,9 +1072,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1272,7 +1226,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1390,7 +1343,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1550,7 +1502,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1628,7 +1579,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1736,7 +1686,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1874,7 +1823,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2095,9 +2043,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2138,7 +2083,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2219,7 +2163,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2261,7 +2204,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2331,9 +2273,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2374,7 +2313,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2455,7 +2393,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2497,7 +2434,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2564,9 +2500,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2607,7 +2540,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2688,7 +2620,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2730,7 +2661,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2803,9 +2733,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2858,7 +2785,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -2948,7 +2874,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2995,7 +2920,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3057,9 +2981,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3112,7 +3033,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -3202,7 +3122,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3249,7 +3168,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3308,9 +3226,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3363,7 +3278,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -3453,7 +3367,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3500,7 +3413,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3568,9 +3480,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3606,7 +3515,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3787,31 +3695,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -3958,31 +3841,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -4058,9 +3916,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 32, "prompt": [ { @@ -4112,7 +3967,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4193,7 +4047,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4366,7 +4219,81 @@ { "name": "generateText", "type": "function", - "children": [], + "children": [ + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "maxOutputTokens": 24, + "prompt": [ + { + "content": "You are a terse assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "Reply with exactly HELLO and no punctuation.", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "content": [ + { + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "text": "HELLO", + "type": "text" + } + ], + "finishReason": "stop", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "cachedInputTokens": 0, + "inputTokens": 26, + "outputTokens": 3, + "reasoningTokens": 0, + "totalTokens": 29 + }, + "warnings": [] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": "stop", + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 3, + "prompt_cached_tokens": 0, + "prompt_tokens": 26, + "reasoning_tokens": 0, + "tokens": 29 + } + } + ], "input": { "maxOutputTokens": 24, "messages": [ @@ -4416,7 +4343,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4458,7 +4384,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4514,91 +4439,6 @@ }, "model": "gpt-4o-mini-2024-07-18", "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 3, - "prompt_cached_tokens": 0, - "prompt_tokens": 26, - "reasoning_tokens": 0, - "tokens": 29 - } - }, - { - "name": "doGenerate", - "type": "llm", - "children": [], - "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, - "maxOutputTokens": 24, - "prompt": [ - { - "content": "You are a terse assistant.", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly HELLO and no punctuation.", - "type": "text" - } - ], - "role": "user" - } - ] - }, - "output": { - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "HELLO", - "type": "text" - } - ], - "finishReason": "stop", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "usage": { - "cachedInputTokens": 0, - "inputTokens": 26, - "outputTokens": 3, - "reasoningTokens": 0, - "totalTokens": 29 - }, - "warnings": [] - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "finish_reason": "stop", - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 3, - "prompt_cached_tokens": 0, - "prompt_tokens": 26, - "reasoning_tokens": 0, - "tokens": 29 } } ], @@ -4632,7 +4472,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4674,7 +4513,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4748,7 +4586,62 @@ { "name": "streamText", "type": "function", - "children": [], + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "includeRawChunks": false, + "maxOutputTokens": 24, + "prompt": [ + { + "content": "You are a terse assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "Reply with exactly STREAM HELLO and no punctuation.", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "finishReason": "stop", + "text": "STREAM HELLO", + "toolCalls": [], + "usage": { + "cachedInputTokens": 0, + "inputTokens": 27, + "outputTokens": 4, + "reasoningTokens": 0, + "totalTokens": 31 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": "stop", + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 4, + "prompt_cached_tokens": 0, + "prompt_tokens": 27, + "reasoning_tokens": 0, + "time_to_first_token": 0, + "tokens": 31 + } + } + ], "input": { "maxOutputTokens": 24, "messages": [ @@ -4792,60 +4685,6 @@ "metrics": { "time_to_first_token": 0 } - }, - { - "name": "doStream", - "type": "llm", - "children": [], - "input": { - "includeRawChunks": false, - "maxOutputTokens": 24, - "prompt": [ - { - "content": "You are a terse assistant.", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly STREAM HELLO and no punctuation.", - "type": "text" - } - ], - "role": "user" - } - ] - }, - "output": { - "finishReason": "stop", - "text": "STREAM HELLO", - "toolCalls": [], - "usage": { - "cachedInputTokens": 0, - "inputTokens": 27, - "outputTokens": 4, - "reasoningTokens": 0, - "totalTokens": 31 - } - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "finish_reason": "stop", - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 4, - "prompt_cached_tokens": 0, - "prompt_tokens": 27, - "reasoning_tokens": 0, - "time_to_first_token": 0, - "tokens": 31 - } } ], "input": { diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.txt index a328a9d42..24af76860 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-auto-hook.span-tree.txt @@ -55,7 +55,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -97,7 +96,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -156,9 +154,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -194,7 +189,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -236,25 +230,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "experimental_output": { - │ "responseFormat": { - │ "schema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "answer": { - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "answer" - │ ], - │ "type": "object" - │ }, - │ "type": "json" - │ }, - │ "type": "object" - │ }, │ "maxOutputTokens": 32, │ "model": { │ "config": { @@ -317,7 +292,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -359,7 +333,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -418,9 +391,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -472,7 +442,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -711,7 +680,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -871,7 +839,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -949,7 +916,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1057,7 +1023,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1195,7 +1160,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1402,9 +1366,6 @@ span_tree: │ } │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1469,7 +1430,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1506,9 +1466,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1603,7 +1560,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1640,9 +1596,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1767,7 +1720,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1804,9 +1756,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1961,7 +1910,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2046,7 +1994,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2088,7 +2035,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2147,9 +2093,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2190,7 +2133,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2275,7 +2217,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2317,7 +2258,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2376,9 +2316,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -2419,7 +2356,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2499,7 +2435,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2541,7 +2476,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2600,9 +2534,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2643,7 +2574,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2735,7 +2665,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2782,7 +2711,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2833,9 +2761,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2888,7 +2813,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "claude-haiku-4-5-20251001" │ }, │ "usage": { @@ -2982,7 +2906,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -3029,7 +2952,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -3080,9 +3002,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -3135,7 +3054,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "claude-haiku-4-5-20251001" │ │ }, │ │ "usage": { @@ -3224,7 +3142,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3271,7 +3188,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3322,9 +3238,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3377,7 +3290,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "claude-haiku-4-5-20251001" │ }, │ "usage": { @@ -3559,31 +3471,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -3730,31 +3617,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -3813,9 +3675,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3851,7 +3710,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3936,7 +3794,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3959,9 +3816,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -4013,7 +3867,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -4201,7 +4054,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -4243,7 +4095,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -4300,191 +4151,41 @@ span_tree: │ "model": "gpt-4o-mini-2024-07-18", │ "provider": "openai.responses" │ } - │ ├── generateText [function] - │ │ input: { - │ │ "maxOutputTokens": 24, - │ │ "messages": [ - │ │ { - │ │ "content": "Reply with exactly HELLO and no punctuation.", - │ │ "role": "user" - │ │ } - │ │ ], - │ │ "model": { - │ │ "config": { - │ │ "fileIdPrefixes": [ - │ │ "file-" - │ │ ], - │ │ "provider": "openai.responses" - │ │ }, - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "specificationVersion": "v2", - │ │ "supportedUrls": { - │ │ "application/pdf": [ - │ │ {} - │ │ ], - │ │ "image/*": [ - │ │ {} - │ │ ] - │ │ } - │ │ }, - │ │ "system": "You are a terse assistant." - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "finishReason": "stop", - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "responseId": "", - │ │ "serviceTier": "default" - │ │ } - │ │ }, - │ │ "response": { - │ │ "body": "", - │ │ "headers": "", - │ │ "messages": [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "providerOptions": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ } - │ │ ], - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "timestamp": "" - │ │ }, - │ │ "steps": [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "finishReason": "stop", - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "responseId": "", - │ │ "serviceTier": "default" - │ │ } - │ │ }, - │ │ "response": { - │ │ "body": "", - │ │ "headers": "", - │ │ "messages": [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "providerOptions": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ } - │ │ ], - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "timestamp": "" - │ │ }, - │ │ "usage": { - │ │ "cachedInputTokens": 0, - │ │ "inputTokens": 26, - │ │ "outputTokens": 3, - │ │ "reasoningTokens": 0, - │ │ "totalTokens": 29 - │ │ }, - │ │ "warnings": [] - │ │ } - │ │ ], - │ │ "text": "HELLO", - │ │ "toolCalls": [], - │ │ "toolResults": [], - │ │ "totalUsage": { - │ │ "cachedInputTokens": 0, - │ │ "inputTokens": 26, - │ │ "outputTokens": 3, - │ │ "reasoningTokens": 0, - │ │ "totalTokens": 29 - │ │ }, - │ │ "usage": { - │ │ "cachedInputTokens": 0, - │ │ "inputTokens": 26, - │ │ "outputTokens": 3, - │ │ "reasoningTokens": 0, - │ │ "totalTokens": 29 - │ │ }, - │ │ "warnings": [] - │ │ } - │ │ metadata: { - │ │ "braintrust": { - │ │ "integration_name": "ai-sdk", - │ │ "sdk_language": "typescript" - │ │ }, - │ │ "model": "gpt-4o-mini-2024-07-18", - │ │ "provider": "openai.responses" - │ │ } - │ │ metrics: { - │ │ "completion_reasoning_tokens": 0, - │ │ "completion_tokens": 3, - │ │ "prompt_cached_tokens": 0, - │ │ "prompt_tokens": 26, - │ │ "reasoning_tokens": 0, - │ │ "tokens": 29 - │ │ } - │ └── doGenerate [llm] + │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, - │ "prompt": [ + │ "messages": [ │ { - │ "content": "You are a terse assistant.", - │ "role": "system" + │ "content": "Reply with exactly HELLO and no punctuation.", + │ "role": "user" + │ } + │ ], + │ "model": { + │ "config": { + │ "fileIdPrefixes": [ + │ "file-" + │ ], + │ "provider": "openai.responses" │ }, - │ { - │ "content": [ - │ { - │ "text": "Reply with exactly HELLO and no punctuation.", - │ "type": "text" - │ } + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "specificationVersion": "v2", + │ "supportedUrls": { + │ "application/pdf": [ + │ {} │ ], - │ "role": "user" + │ "image/*": [ + │ {} + │ ] │ } - │ ] + │ }, + │ "system": "You are a terse assistant." │ } │ output: { │ "content": [ │ { │ "providerMetadata": { │ "openai": { - │ "itemId": "" + │ "itemId": "" │ } │ }, │ "text": "HELLO", @@ -4494,16 +4195,92 @@ span_tree: │ "finishReason": "stop", │ "providerMetadata": { │ "openai": { - │ "responseId": "", + │ "responseId": "", │ "serviceTier": "default" │ } │ }, │ "response": { │ "body": "", - │ "headers": "", + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, + │ "steps": [ + │ { + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "body": "", + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "usage": { + │ "cachedInputTokens": 0, + │ "inputTokens": 26, + │ "outputTokens": 3, + │ "reasoningTokens": 0, + │ "totalTokens": 29 + │ }, + │ "warnings": [] + │ } + │ ], + │ "text": "HELLO", + │ "toolCalls": [], + │ "toolResults": [], + │ "totalUsage": { + │ "cachedInputTokens": 0, + │ "inputTokens": 26, + │ "outputTokens": 3, + │ "reasoningTokens": 0, + │ "totalTokens": 29 + │ }, │ "usage": { │ "cachedInputTokens": 0, │ "inputTokens": 26, @@ -4518,18 +4295,78 @@ span_tree: │ "integration_name": "ai-sdk", │ "sdk_language": "typescript" │ }, - │ "finish_reason": "stop", │ "model": "gpt-4o-mini-2024-07-18", │ "provider": "openai.responses" │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 3, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 26, - │ "reasoning_tokens": 0, - │ "tokens": 29 - │ } + │ └── doGenerate [llm] + │ input: { + │ "maxOutputTokens": 24, + │ "prompt": [ + │ { + │ "content": "You are a terse assistant.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "Reply with exactly HELLO and no punctuation.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "body": "", + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "usage": { + │ "cachedInputTokens": 0, + │ "inputTokens": 26, + │ "outputTokens": 3, + │ "reasoningTokens": 0, + │ "totalTokens": 29 + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": "stop", + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 3, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 26, + │ "reasoning_tokens": 0, + │ "tokens": 29 + │ } └── ai-sdk-agent-stream-operation metadata: { "operation": "agent-stream", @@ -4560,97 +4397,97 @@ span_tree: metrics: { "time_to_first_token": 0 } - ├── streamText [function] - │ input: { - │ "maxOutputTokens": 24, - │ "messages": [ - │ { - │ "content": "Reply with exactly STREAM HELLO and no punctuation.", - │ "role": "user" - │ } - │ ], - │ "model": { - │ "config": { - │ "fileIdPrefixes": [ - │ "file-" - │ ], - │ "provider": "openai.responses" - │ }, - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "specificationVersion": "v2", - │ "supportedUrls": { - │ "application/pdf": [ - │ {} - │ ], - │ "image/*": [ - │ {} - │ ] - │ } - │ }, - │ "system": "You are a terse assistant." - │ } - │ output: { - │ "finishReason": "stop", - │ "text": "STREAM HELLO" - │ } - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" - │ } - │ metrics: { - │ "time_to_first_token": 0 - │ } - └── doStream [llm] + └── streamText [function] input: { - "includeRawChunks": false, "maxOutputTokens": 24, - "prompt": [ + "messages": [ { - "content": "You are a terse assistant.", - "role": "system" + "content": "Reply with exactly STREAM HELLO and no punctuation.", + "role": "user" + } + ], + "model": { + "config": { + "fileIdPrefixes": [ + "file-" + ], + "provider": "openai.responses" }, - { - "content": [ - { - "text": "Reply with exactly STREAM HELLO and no punctuation.", - "type": "text" - } + "modelId": "gpt-4o-mini-2024-07-18", + "specificationVersion": "v2", + "supportedUrls": { + "application/pdf": [ + {} ], - "role": "user" + "image/*": [ + {} + ] } - ] + }, + "system": "You are a terse assistant." } output: { "finishReason": "stop", - "text": "STREAM HELLO", - "toolCalls": [], - "usage": { - "cachedInputTokens": 0, - "inputTokens": 27, - "outputTokens": 4, - "reasoningTokens": 0, - "totalTokens": 31 - } + "text": "STREAM HELLO" } metadata: { "braintrust": { "integration_name": "ai-sdk", "sdk_language": "typescript" }, - "finish_reason": "stop", "model": "gpt-4o-mini-2024-07-18", "provider": "openai.responses" } metrics: { - "completion_reasoning_tokens": 0, - "completion_tokens": 4, - "prompt_cached_tokens": 0, - "prompt_tokens": 27, - "reasoning_tokens": 0, - "time_to_first_token": 0, - "tokens": 31 + "time_to_first_token": 0 } + └── doStream [llm] + input: { + "includeRawChunks": false, + "maxOutputTokens": 24, + "prompt": [ + { + "content": "You are a terse assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "Reply with exactly STREAM HELLO and no punctuation.", + "type": "text" + } + ], + "role": "user" + } + ] + } + output: { + "finishReason": "stop", + "text": "STREAM HELLO", + "toolCalls": [], + "usage": { + "cachedInputTokens": 0, + "inputTokens": 27, + "outputTokens": 4, + "reasoningTokens": 0, + "totalTokens": 31 + } + } + metadata: { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": "stop", + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + } + metrics: { + "completion_reasoning_tokens": 0, + "completion_tokens": 4, + "prompt_cached_tokens": 0, + "prompt_tokens": 27, + "reasoning_tokens": 0, + "time_to_first_token": 0, + "tokens": 31 + } diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.json index 87f0cbf66..79bff2e52 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.json @@ -16,9 +16,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -54,7 +51,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -130,7 +126,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -172,7 +167,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -256,9 +250,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 32, "prompt": [ { @@ -310,7 +301,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -343,25 +333,6 @@ } ], "input": { - "experimental_output": { - "responseFormat": { - "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "answer": { - "type": "string" - } - }, - "required": [ - "answer" - ], - "type": "object" - }, - "type": "json" - }, - "type": "object" - }, "maxOutputTokens": 32, "model": { "config": { @@ -424,7 +395,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -466,7 +436,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -689,9 +658,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -756,7 +722,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -801,9 +766,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -898,7 +860,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -943,9 +904,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1070,7 +1028,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1115,9 +1072,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1272,7 +1226,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1390,7 +1343,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1550,7 +1502,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1628,7 +1579,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1736,7 +1686,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1874,7 +1823,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2098,9 +2046,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2141,7 +2086,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2222,7 +2166,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2264,7 +2207,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2331,9 +2273,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2374,7 +2313,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2455,7 +2393,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2497,7 +2434,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2573,9 +2509,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2628,7 +2561,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -2718,7 +2650,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2765,7 +2696,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2824,9 +2754,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2879,7 +2806,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -2969,7 +2895,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3016,7 +2941,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3084,9 +3008,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3122,7 +3043,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3303,31 +3223,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -3474,31 +3369,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -3574,9 +3444,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 32, "prompt": [ { @@ -3628,7 +3495,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3709,7 +3575,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3884,9 +3749,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/5.0.82" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3925,7 +3787,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4006,7 +3867,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4048,7 +3908,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.txt index b727af3d2..c12f06227 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v5-wrapped.span-tree.txt @@ -55,7 +55,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -97,7 +96,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -156,9 +154,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -194,7 +189,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -236,25 +230,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "experimental_output": { - │ "responseFormat": { - │ "schema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "answer": { - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "answer" - │ ], - │ "type": "object" - │ }, - │ "type": "json" - │ }, - │ "type": "object" - │ }, │ "maxOutputTokens": 32, │ "model": { │ "config": { @@ -317,7 +292,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -359,7 +333,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -418,9 +391,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -472,7 +442,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -711,7 +680,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -871,7 +839,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -949,7 +916,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1057,7 +1023,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1195,7 +1160,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1402,9 +1366,6 @@ span_tree: │ } │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1469,7 +1430,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1506,9 +1466,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1603,7 +1560,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1640,9 +1596,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1767,7 +1720,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1804,9 +1756,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1961,7 +1910,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2051,7 +1999,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2093,7 +2040,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2152,9 +2098,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -2195,7 +2138,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2275,7 +2217,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2317,7 +2258,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2376,9 +2316,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2419,7 +2356,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2516,7 +2452,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2563,7 +2498,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2614,9 +2548,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/5.0.82" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -2669,7 +2600,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "claude-haiku-4-5-20251001" │ │ }, │ │ "usage": { @@ -2758,7 +2688,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2805,7 +2734,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2856,9 +2784,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2911,7 +2836,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "claude-haiku-4-5-20251001" │ }, │ "usage": { @@ -3093,31 +3017,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -3264,31 +3163,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -3347,9 +3221,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3385,7 +3256,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3470,7 +3340,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3493,9 +3362,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -3547,7 +3413,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3754,7 +3619,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3796,7 +3660,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3855,9 +3718,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/5.0.82" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3896,7 +3756,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.json index d54e05d09..7ea80c710 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.json @@ -16,9 +16,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -56,7 +53,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -141,6 +137,7 @@ } ], "finishReason": "stop", + "output": "PARIS", "providerMetadata": { "openai": { "responseId": "", @@ -149,7 +146,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -191,7 +187,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -319,9 +314,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 32, "prompt": [ { @@ -375,7 +367,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -425,9 +416,6 @@ } ], "input": { - "experimental_output": { - "responseFormat": {} - }, "maxOutputTokens": 32, "model": { "config": { @@ -481,6 +469,9 @@ } ], "finishReason": "stop", + "output": { + "answer": "4" + }, "providerMetadata": { "openai": { "responseId": "", @@ -489,7 +480,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -531,7 +521,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -860,9 +849,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -929,7 +915,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -991,9 +976,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1095,7 +1077,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1157,9 +1138,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1296,7 +1274,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1358,9 +1335,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1532,7 +1506,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1672,7 +1645,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1857,7 +1829,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1963,7 +1934,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2104,7 +2074,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2280,7 +2249,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2570,9 +2538,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2615,7 +2580,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2705,6 +2669,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "openai": { "responseId": "", @@ -2713,7 +2678,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2755,7 +2719,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2869,9 +2832,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2914,7 +2874,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3004,6 +2963,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "openai": { "responseId": "", @@ -3012,7 +2972,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3054,7 +3013,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3165,9 +3123,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3210,7 +3165,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3300,6 +3254,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "openai": { "responseId": "", @@ -3308,7 +3263,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3350,7 +3304,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3467,9 +3420,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3525,7 +3475,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -3612,6 +3561,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "anthropic": { "cacheCreationInputTokens": 0, @@ -3635,7 +3585,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3683,7 +3632,6 @@ "rawFinishReason": "end_turn", "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3787,9 +3735,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3845,7 +3790,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -3932,6 +3876,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "anthropic": { "cacheCreationInputTokens": 0, @@ -3955,7 +3900,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4003,7 +3947,6 @@ "rawFinishReason": "end_turn", "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4104,9 +4047,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -4162,7 +4102,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -4249,6 +4188,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "anthropic": { "cacheCreationInputTokens": 0, @@ -4272,7 +4212,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4320,7 +4259,6 @@ "rawFinishReason": "end_turn", "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4430,9 +4368,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -4470,7 +4405,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4555,6 +4489,7 @@ } ], "finishReason": "stop", + "output": "DENIED", "providerMetadata": { "openai": { "responseId": "", @@ -4668,31 +4603,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -4839,31 +4749,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -4983,9 +4868,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 32, "prompt": [ { @@ -5039,7 +4921,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -5137,7 +5018,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -5347,7 +5227,96 @@ { "name": "generateText", "type": "function", - "children": [], + "children": [ + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "maxOutputTokens": 24, + "prompt": [ + { + "content": [ + { + "text": "Reply with exactly HELLO and no punctuation.", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "content": [ + { + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "text": "HELLO", + "type": "text" + } + ], + "finishReason": { + "unified": "stop" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 16, + "total": 16 + }, + "outputTokens": { + "reasoning": 0, + "text": 3, + "total": 3 + }, + "raw": { + "input_tokens": 16, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 3, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + }, + "warnings": [] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "stop" + }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 3, + "prompt_cached_tokens": 0, + "prompt_tokens": 16, + "reasoning_tokens": 0, + "tokens": 19 + } + } + ], "input": { "maxOutputTokens": 24, "messages": [ @@ -5388,6 +5357,7 @@ } ], "finishReason": "stop", + "output": "HELLO", "providerMetadata": { "openai": { "responseId": "", @@ -5396,7 +5366,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5438,7 +5407,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5538,106 +5506,6 @@ }, "model": "gpt-4o-mini-2024-07-18", "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 3, - "prompt_cached_tokens": 0, - "prompt_tokens": 16, - "reasoning_tokens": 0, - "tokens": 19 - } - }, - { - "name": "doGenerate", - "type": "llm", - "children": [], - "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, - "maxOutputTokens": 24, - "prompt": [ - { - "content": [ - { - "text": "Reply with exactly HELLO and no punctuation.", - "type": "text" - } - ], - "role": "user" - } - ] - }, - "output": { - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "HELLO", - "type": "text" - } - ], - "finishReason": { - "unified": "stop" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "usage": { - "inputTokens": { - "cacheRead": 0, - "noCache": 16, - "total": 16 - }, - "outputTokens": { - "reasoning": 0, - "text": 3, - "total": 3 - }, - "raw": { - "input_tokens": 16, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 3, - "output_tokens_details": { - "reasoning_tokens": 0 - } - } - }, - "warnings": [] - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "finish_reason": { - "unified": "stop" - }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 3, - "prompt_cached_tokens": 0, - "prompt_tokens": 16, - "reasoning_tokens": 0, - "tokens": 19 } } ], @@ -5663,6 +5531,7 @@ } ], "finishReason": "stop", + "output": "HELLO", "providerMetadata": { "openai": { "responseId": "", @@ -5671,7 +5540,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5713,7 +5581,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5831,7 +5698,77 @@ { "name": "streamText", "type": "function", - "children": [], + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "includeRawChunks": false, + "maxOutputTokens": 24, + "prompt": [ + { + "content": [ + { + "text": "Reply with exactly STREAM HELLO and no punctuation.", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "finishReason": { + "unified": "stop" + }, + "text": "STREAM HELLO", + "toolCalls": [], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 17, + "total": 17 + }, + "outputTokens": { + "reasoning": 0, + "text": 4, + "total": 4 + }, + "raw": { + "input_tokens": 17, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 4, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "stop" + }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 4, + "prompt_cached_tokens": 0, + "prompt_tokens": 17, + "reasoning_tokens": 0, + "time_to_first_token": 0, + "tokens": 21 + } + } + ], "input": { "maxOutputTokens": 24, "messages": [ @@ -5874,1260 +5811,805 @@ "metrics": { "time_to_first_token": 0 } + } + ], + "input": { + "maxOutputTokens": 24, + "messages": [ + { + "content": "Reply with exactly STREAM HELLO and no punctuation.", + "role": "user" + } + ] + }, + "output": { + "finishReason": "stop", + "text": "STREAM HELLO" + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "time_to_first_token": 0 + } + } + ], + "metadata": { + "operation": "agent-stream", + "testRunId": "" + } + }, + { + "name": "ai-sdk-agent-tool-loop-operation", + "children": [ + { + "name": "ToolLoopAgent.generate", + "type": "function", + "children": [ { - "name": "doStream", - "type": "llm", - "children": [], - "input": { - "includeRawChunks": false, - "maxOutputTokens": 24, - "prompt": [ - { - "content": [ + "name": "generateText", + "type": "function", + "children": [ + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "maxOutputTokens": 256, + "prompt": [ { - "text": "Reply with exactly STREAM HELLO and no punctuation.", - "type": "text" - } - ], - "role": "user" - } - ] - }, - "output": { - "finishReason": { - "unified": "stop" - }, - "text": "STREAM HELLO", - "toolCalls": [], - "usage": { - "inputTokens": { - "cacheRead": 0, - "noCache": 17, - "total": 17 - }, - "outputTokens": { - "reasoning": 0, - "text": 4, - "total": 4 - }, - "raw": { - "input_tokens": 17, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 4, - "output_tokens_details": { - "reasoning_tokens": 0 - } - } - } - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "finish_reason": { - "unified": "stop" - }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 4, - "prompt_cached_tokens": 0, - "prompt_tokens": 17, - "reasoning_tokens": 0, - "time_to_first_token": 0, - "tokens": 21 - } - } - ], - "input": { - "maxOutputTokens": 24, - "messages": [ - { - "content": "Reply with exactly STREAM HELLO and no punctuation.", - "role": "user" - } - ] - }, - "output": { - "finishReason": "stop", - "text": "STREAM HELLO" - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "time_to_first_token": 0 - } - } - ], - "metadata": { - "operation": "agent-stream", - "testRunId": "" - } - }, - { - "name": "ai-sdk-agent-tool-loop-operation", - "children": [ - { - "name": "ToolLoopAgent.generate", - "type": "function", - "children": [ - { - "name": "generateText", - "type": "function", - "children": [], - "input": { - "maxOutputTokens": 256, - "messages": [ - { - "content": "I need help comparing laptop prices before checkout.", - "role": "user" - }, - { - "content": "I can compare store prices and apply a discount code.", - "role": "assistant" - }, - { - "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "role": "user" - } - ], - "model": { - "config": { - "fileIdPrefixes": [ - "file-" - ], - "provider": "openai.responses" - }, - "modelId": "gpt-4o-mini-2024-07-18", - "specificationVersion": "v3", - "supportedUrls": { - "application/pdf": [ - {} - ], - "image/*": [ - {} - ] - } - }, - "system": "You are a shopping assistant. Use the tools before answering pricing questions.", - "temperature": 0, - "tools": { - "apply_discount": { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" - }, - "total": { - "description": "The original total", - "type": "number" - } - }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - } - }, - "get_store_price": { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } - }, - "required": [ - "item", - "store" - ], - "type": "object" - } - } - } - }, - "output": { - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "role": "assistant" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "steps": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "finishReason": "tool-calls", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "usage": { - "cachedInputTokens": 0, - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 173 - }, - "inputTokens": 173, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 59 - }, - "outputTokens": 59, - "raw": { - "input_tokens": 173, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 59, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "reasoningTokens": 0, - "totalTokens": 232 - }, - "warnings": [] - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "finishReason": "tool-calls", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "usage": { - "cachedInputTokens": 0, - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 260 + "content": "You are a shopping assistant. Use the tools before answering pricing questions.", + "role": "system" }, - "inputTokens": 260, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 21 + { + "content": [ + { + "text": "I need help comparing laptop prices before checkout.", + "type": "text" + } + ], + "role": "user" }, - "outputTokens": 21, - "raw": { - "input_tokens": 260, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 21, - "output_tokens_details": { - "reasoning_tokens": 0 - } + { + "content": [ + { + "text": "I can compare store prices and apply a discount code.", + "type": "text" + } + ], + "role": "assistant" }, - "reasoningTokens": 0, - "totalTokens": 281 - }, - "warnings": [] - }, - { - "content": [ { - "providerMetadata": { - "openai": { - "itemId": "" + "content": [ + { + "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + "type": "text" } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" + ], + "role": "user" } ], - "finishReason": "stop", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } + "temperature": 0, + "toolChoice": { + "type": "auto" }, - "response": { - "body": "", - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" + "tools": [ + { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" + "store": { + "description": "The store name", + "type": "string" } + }, + "required": [ + "item", + "store" ], - "role": "assistant" + "type": "object" }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" + "name": "get_store_price", + "type": "function" + }, + { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" + "total": { + "description": "The original total", + "type": "number" } + }, + "required": [ + "discountCode", + "total" ], - "role": "tool" + "type": "object" }, - { - "content": [ - { - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "role": "assistant" - } - ], + "name": "apply_discount", + "type": "function" + } + ] + }, + "output": { + "content": [ + { + "input": "{\"item\":\"laptop\",\"store\":\"StoreA\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": "{\"item\":\"laptop\",\"store\":\"StoreB\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "finishReason": { + "unified": "tool-calls" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, "usage": { - "cachedInputTokens": 0, - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 308 + "inputTokens": { + "cacheRead": 0, + "noCache": 173, + "total": 173 }, - "inputTokens": 308, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 62 + "outputTokens": { + "reasoning": 0, + "text": 59, + "total": 59 }, - "outputTokens": 62, "raw": { - "input_tokens": 308, + "input_tokens": 173, "input_tokens_details": { "cached_tokens": 0 }, - "output_tokens": 62, + "output_tokens": 59, "output_tokens_details": { "reasoning_tokens": 0 } - }, - "reasoningTokens": 0, - "totalTokens": 370 + } }, "warnings": [] - } - ], - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "toolCalls": [], - "toolResults": [], - "totalUsage": { - "cachedInputTokens": 0, - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 741 }, - "inputTokens": 741, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 142 + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" }, - "outputTokens": 142, - "reasoningTokens": 0, - "totalTokens": 883 + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 59, + "prompt_cached_tokens": 0, + "prompt_tokens": 173, + "reasoning_tokens": 0, + "tokens": 232 + } }, - "usage": { - "cachedInputTokens": 0, - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 308 - }, - "inputTokens": 308, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 62 - }, - "outputTokens": 62, - "raw": { - "input_tokens": 308, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 62, - "output_tokens_details": { - "reasoning_tokens": 0 - } + { + "name": "get_store_price", + "type": "tool", + "children": [], + "input": { + "item": "laptop", + "store": "StoreA" }, - "reasoningTokens": 0, - "totalTokens": 370 + "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" }, - "warnings": [] - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" + { + "name": "get_store_price", + "type": "tool", + "children": [], + "input": { + "item": "laptop", + "store": "StoreB" + }, + "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses", - "tools": { - "apply_discount": { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" - }, - "total": { - "description": "The original total", - "type": "number" - } + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "maxOutputTokens": 256, + "prompt": [ + { + "content": "You are a shopping assistant. Use the tools before answering pricing questions.", + "role": "system" }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - } - }, - "get_store_price": { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } + { + "content": [ + { + "text": "I need help comparing laptop prices before checkout.", + "type": "text" + } + ], + "role": "user" }, - "required": [ - "item", - "store" - ], - "type": "object" - } - } - } - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 142, - "prompt_cached_tokens": 0, - "prompt_tokens": 741, - "reasoning_tokens": 0, - "tokens": 883 - } - }, - { - "name": "doGenerate", - "type": "llm", - "children": [], - "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, - "maxOutputTokens": 256, - "prompt": [ - { - "content": "You are a shopping assistant. Use the tools before answering pricing questions.", - "role": "system" - }, - { - "content": [ { - "text": "I need help comparing laptop prices before checkout.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ + "content": [ + { + "text": "I can compare store prices and apply a discount code.", + "type": "text" + } + ], + "role": "assistant" + }, { - "text": "I can compare store prices and apply a discount code.", - "type": "text" - } - ], - "role": "assistant" - }, - { - "content": [ + "content": [ + { + "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + "type": "text" + } + ], + "role": "user" + }, { - "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "type": "text" + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" } ], - "role": "user" - } - ], - "temperature": 0, - "toolChoice": { - "type": "auto" - }, - "tools": [ - { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } - }, - "required": [ - "item", - "store" - ], - "type": "object" - }, - "name": "get_store_price", - "type": "function" - }, - { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" + "temperature": 0, + "toolChoice": { + "type": "auto" + }, + "tools": [ + { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" }, - "total": { - "description": "The original total", - "type": "number" - } + "name": "get_store_price", + "type": "function" }, - "required": [ - "discountCode", - "total" - ], - "type": "object" + { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + }, + "name": "apply_discount", + "type": "function" + } + ] + }, + "output": { + "content": [ + { + "input": "{\"discountCode\":\"SAVE20\",\"total\":999}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "finishReason": { + "unified": "tool-calls" }, - "name": "apply_discount", - "type": "function" - } - ] - }, - "output": { - "content": [ - { - "input": "{\"item\":\"laptop\",\"store\":\"StoreA\"}", "providerMetadata": { "openai": { - "itemId": "" + "responseId": "", + "serviceTier": "default" } }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": "{\"item\":\"laptop\",\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" + "response": { + "body": "", + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 260, + "total": 260 + }, + "outputTokens": { + "reasoning": 0, + "text": 21, + "total": 21 + }, + "raw": { + "input_tokens": 260, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 21, + "output_tokens_details": { + "reasoning_tokens": 0 + } } }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "finishReason": { - "unified": "tool-calls" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "usage": { - "inputTokens": { - "cacheRead": 0, - "noCache": 173, - "total": 173 - }, - "outputTokens": { - "reasoning": 0, - "text": 59, - "total": 59 + "warnings": [] }, - "raw": { - "input_tokens": 173, - "input_tokens_details": { - "cached_tokens": 0 + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" }, - "output_tokens": 59, - "output_tokens_details": { - "reasoning_tokens": 0 - } + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 21, + "prompt_cached_tokens": 0, + "prompt_tokens": 260, + "reasoning_tokens": 0, + "tokens": 281 } }, - "warnings": [] - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "finish_reason": { - "unified": "tool-calls" - }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 59, - "prompt_cached_tokens": 0, - "prompt_tokens": 173, - "reasoning_tokens": 0, - "tokens": 232 - } - }, - { - "name": "get_store_price", - "type": "tool", - "children": [], - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - { - "name": "get_store_price", - "type": "tool", - "children": [], - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - { - "name": "doGenerate", - "type": "llm", - "children": [], - "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, - "maxOutputTokens": 256, - "prompt": [ - { - "content": "You are a shopping assistant. Use the tools before answering pricing questions.", - "role": "system" + { + "name": "apply_discount", + "type": "tool", + "children": [], + "input": { + "discountCode": "SAVE20", + "total": 999 }, - { - "content": [ + "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "maxOutputTokens": 256, + "prompt": [ { - "text": "I need help comparing laptop prices before checkout.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ + "content": "You are a shopping assistant. Use the tools before answering pricing questions.", + "role": "system" + }, { - "text": "I can compare store prices and apply a discount code.", - "type": "text" - } - ], - "role": "assistant" - }, - { - "content": [ + "content": [ + { + "text": "I need help comparing laptop prices before checkout.", + "type": "text" + } + ], + "role": "user" + }, { - "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "type": "text" + "content": [ + { + "text": "I can compare store prices and apply a discount code.", + "type": "text" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" } ], - "role": "user" - }, - { - "content": [ + "temperature": 0, + "toolChoice": { + "type": "auto" + }, + "tools": [ { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" }, - "toolName": "get_store_price", - "type": "tool-call" + "name": "get_store_price", + "type": "function" }, { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" }, - "toolName": "get_store_price", - "type": "tool-call" + "name": "apply_discount", + "type": "function" } - ], - "role": "assistant" + ] }, - { + "output": { "content": [ { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { + "providerMetadata": { "openai": { "itemId": "" } }, - "toolName": "get_store_price", - "type": "tool-result" + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" } ], - "role": "tool" + "finishReason": { + "unified": "stop" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 308, + "total": 308 + }, + "outputTokens": { + "reasoning": 0, + "text": 62, + "total": 62 + }, + "raw": { + "input_tokens": 308, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 62, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + }, + "warnings": [] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "stop" + }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 62, + "prompt_cached_tokens": 0, + "prompt_tokens": 308, + "reasoning_tokens": 0, + "tokens": 370 + } + } + ], + "input": { + "maxOutputTokens": 256, + "messages": [ + { + "content": "I need help comparing laptop prices before checkout.", + "role": "user" + }, + { + "content": "I can compare store prices and apply a discount code.", + "role": "assistant" + }, + { + "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + "role": "user" } ], - "temperature": 0, - "toolChoice": { - "type": "auto" + "model": { + "config": { + "fileIdPrefixes": [ + "file-" + ], + "provider": "openai.responses" + }, + "modelId": "gpt-4o-mini-2024-07-18", + "specificationVersion": "v3", + "supportedUrls": { + "application/pdf": [ + {} + ], + "image/*": [ + {} + ] + } }, - "tools": [ - { + "system": "You are a shopping assistant. Use the tools before answering pricing questions.", + "temperature": 0, + "tools": { + "apply_discount": { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + } + }, + "get_store_price": { "description": "Get the price of an item at a store", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -7147,159 +6629,150 @@ "store" ], "type": "object" - }, - "name": "get_store_price", - "type": "function" - }, + } + } + } + }, + "output": { + "content": [ { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "finishReason": "stop", + "output": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" }, - "total": { - "description": "The original total", - "type": "number" + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" } - }, - "required": [ - "discountCode", - "total" ], - "type": "object" - }, - "name": "apply_discount", - "type": "function" - } - ] - }, - "output": { - "content": [ - { - "input": "{\"discountCode\":\"SAVE20\",\"total\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } + "role": "tool" }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "finishReason": { - "unified": "tool-calls" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", + { + "content": [ + { + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "role": "assistant" + } + ], "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, - "usage": { - "inputTokens": { - "cacheRead": 0, - "noCache": 260, - "total": 260 - }, - "outputTokens": { - "reasoning": 0, - "text": 21, - "total": 21 - }, - "raw": { - "input_tokens": 260, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 21, - "output_tokens_details": { - "reasoning_tokens": 0 - } - } - }, - "warnings": [] - }, - "metadata": { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "finish_reason": { - "unified": "tool-calls" - }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 21, - "prompt_cached_tokens": 0, - "prompt_tokens": 260, - "reasoning_tokens": 0, - "tokens": 281 - } - }, - { - "name": "apply_discount", - "type": "tool", - "children": [], - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - { - "name": "doGenerate", - "type": "llm", - "children": [], - "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, - "maxOutputTokens": 256, - "prompt": [ - { - "content": "You are a shopping assistant. Use the tools before answering pricing questions.", - "role": "system" - }, - { - "content": [ - { - "text": "I need help comparing laptop prices before checkout.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "text": "I can compare store prices and apply a discount code.", - "type": "text" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "type": "text" - } - ], - "role": "user" - }, + "steps": [ { "content": [ { @@ -7307,7 +6780,7 @@ "item": "laptop", "store": "StoreA" }, - "providerOptions": { + "providerMetadata": { "openai": { "itemId": "" } @@ -7320,25 +6793,22 @@ "item": "laptop", "store": "StoreB" }, - "providerOptions": { + "providerMetadata": { "openai": { "itemId": "" } }, "toolName": "get_store_price", "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ + }, { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + "dynamic": false, + "input": { + "item": "laptop", + "store": "StoreA" }, - "providerOptions": { + "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + "providerMetadata": { "openai": { "itemId": "" } @@ -7347,11 +6817,13 @@ "type": "tool-result" }, { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + "dynamic": false, + "input": { + "item": "laptop", + "store": "StoreB" }, - "providerOptions": { + "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + "providerMetadata": { "openai": { "itemId": "" } @@ -7360,7 +6832,108 @@ "type": "tool-result" } ], - "role": "tool" + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 173 + }, + "inputTokens": 173, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 59 + }, + "outputTokens": 59, + "raw": { + "input_tokens": 173, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 59, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "reasoningTokens": 0, + "totalTokens": 232 + }, + "warnings": [] }, { "content": [ @@ -7369,129 +6942,365 @@ "discountCode": "SAVE20", "total": 999 }, - "providerOptions": { + "providerMetadata": { "openai": { - "itemId": "" + "itemId": "" } }, "toolName": "apply_discount", "type": "tool-call" + }, + { + "dynamic": false, + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" } ], - "role": "assistant" + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 260 + }, + "inputTokens": 260, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 21 + }, + "outputTokens": 21, + "raw": { + "input_tokens": 260, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 21, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "reasoningTokens": 0, + "totalTokens": 281 + }, + "warnings": [] }, { "content": [ { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { + "providerMetadata": { "openai": { - "itemId": "" + "itemId": "" } }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "temperature": 0, - "toolChoice": { - "type": "auto" - }, - "tools": [ - { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "finishReason": "stop", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" }, - "store": { - "description": "The store name", - "type": "string" + { + "content": [ + { + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "role": "assistant" } - }, - "required": [ - "item", - "store" ], - "type": "object" + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" }, - "name": "get_store_price", - "type": "function" - }, - { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 308 + }, + "inputTokens": 308, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 62 + }, + "outputTokens": 62, + "raw": { + "input_tokens": 308, + "input_tokens_details": { + "cached_tokens": 0 }, - "total": { - "description": "The original total", - "type": "number" + "output_tokens": 62, + "output_tokens_details": { + "reasoning_tokens": 0 } }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - }, - "name": "apply_discount", - "type": "function" - } - ] - }, - "output": { - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } + "reasoningTokens": 0, + "totalTokens": 370 }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" + "warnings": [] } ], - "finishReason": { - "unified": "stop" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "body": "", - "headers": "", - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "toolCalls": [], + "toolResults": [], + "totalUsage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 741 + }, + "inputTokens": 741, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 142 + }, + "outputTokens": 142, + "reasoningTokens": 0, + "totalTokens": 883 }, "usage": { - "inputTokens": { - "cacheRead": 0, - "noCache": 308, - "total": 308 + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 308 }, - "outputTokens": { - "reasoning": 0, - "text": 62, - "total": 62 + "inputTokens": 308, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 62 }, + "outputTokens": 62, "raw": { "input_tokens": 308, "input_tokens_details": { @@ -7501,7 +7310,9 @@ "output_tokens_details": { "reasoning_tokens": 0 } - } + }, + "reasoningTokens": 0, + "totalTokens": 370 }, "warnings": [] }, @@ -7510,19 +7321,54 @@ "integration_name": "ai-sdk", "sdk_language": "typescript" }, - "finish_reason": { - "unified": "stop" - }, "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 62, - "prompt_cached_tokens": 0, - "prompt_tokens": 308, - "reasoning_tokens": 0, - "tokens": 370 + "provider": "openai.responses", + "tools": { + "apply_discount": { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + } + }, + "get_store_price": { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" + } + } + } } } ], @@ -7556,6 +7402,7 @@ } ], "finishReason": "stop", + "output": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "providerMetadata": { "openai": { "responseId": "", @@ -7564,7 +7411,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -7751,7 +7597,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -7886,7 +7731,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -8038,7 +7882,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -8235,7 +8078,53 @@ "sdk_language": "typescript" }, "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" + "provider": "openai.responses", + "tools": { + "apply_discount": { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + } + }, + "get_store_price": { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" + } + } + } } } ], diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.txt index 0a0a16940..9a7100a1b 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-auto-hook.span-tree.txt @@ -47,6 +47,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "PARIS", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -55,7 +56,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -97,7 +97,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -200,9 +199,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -240,7 +236,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -299,9 +294,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "experimental_output": { - │ "responseFormat": {} - │ }, │ "maxOutputTokens": 32, │ "model": { │ "config": { @@ -355,6 +347,9 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": { + │ "answer": "4" + │ }, │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -363,7 +358,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -405,7 +399,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -508,9 +501,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -564,7 +554,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -879,7 +868,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1064,7 +1052,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1170,7 +1157,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1311,7 +1297,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1487,7 +1472,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1763,9 +1747,6 @@ span_tree: │ } │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1832,7 +1813,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1886,9 +1866,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1990,7 +1967,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2044,9 +2020,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -2183,7 +2156,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2237,9 +2209,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -2411,7 +2380,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2505,6 +2473,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "CACHE_OK", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -2513,7 +2482,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2555,7 +2523,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2658,9 +2625,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2703,7 +2667,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2797,6 +2760,7 @@ span_tree: │ │ } │ │ ], │ │ "finishReason": "stop", + │ │ "output": "CACHE_OK", │ │ "providerMetadata": { │ │ "openai": { │ │ "responseId": "", @@ -2805,7 +2769,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2847,7 +2810,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2950,9 +2912,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -2995,7 +2954,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -3084,6 +3042,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "CACHE_OK", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -3092,7 +3051,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3134,7 +3092,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3237,9 +3194,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3282,7 +3236,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3368,6 +3321,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "CACHE_OK", │ "providerMetadata": { │ "anthropic": { │ "cacheCreationInputTokens": 0, @@ -3391,7 +3345,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3439,7 +3392,6 @@ span_tree: │ "rawFinishReason": "end_turn", │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3532,9 +3484,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3590,7 +3539,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "claude-haiku-4-5-20251001" │ }, │ "usage": { @@ -3681,6 +3629,7 @@ span_tree: │ │ } │ │ ], │ │ "finishReason": "stop", + │ │ "output": "CACHE_OK", │ │ "providerMetadata": { │ │ "anthropic": { │ │ "cacheCreationInputTokens": 0, @@ -3704,7 +3653,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -3752,7 +3700,6 @@ span_tree: │ │ "rawFinishReason": "end_turn", │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -3845,9 +3792,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -3903,7 +3847,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "claude-haiku-4-5-20251001" │ │ }, │ │ "usage": { @@ -3989,6 +3932,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "CACHE_OK", │ "providerMetadata": { │ "anthropic": { │ "cacheCreationInputTokens": 0, @@ -4012,7 +3956,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -4060,7 +4003,6 @@ span_tree: │ "rawFinishReason": "end_turn", │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -4153,9 +4095,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -4211,7 +4150,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "claude-haiku-4-5-20251001" │ }, │ "usage": { @@ -4300,6 +4238,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "DENIED", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -4413,31 +4352,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -4584,31 +4498,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -4711,9 +4600,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -4751,7 +4637,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -4853,7 +4738,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -4894,9 +4778,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -4950,7 +4831,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -5166,6 +5046,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "HELLO", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -5174,7 +5055,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -5216,7 +5096,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -5317,262 +5196,174 @@ span_tree: │ "model": "gpt-4o-mini-2024-07-18", │ "provider": "openai.responses" │ } - │ ├── generateText [function] - │ │ input: { - │ │ "maxOutputTokens": 24, - │ │ "messages": [ - │ │ { - │ │ "content": "Reply with exactly HELLO and no punctuation.", - │ │ "role": "user" - │ │ } - │ │ ], - │ │ "model": { - │ │ "config": { - │ │ "fileIdPrefixes": [ - │ │ "file-" - │ │ ], - │ │ "provider": "openai.responses" - │ │ }, - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "specificationVersion": "v3", - │ │ "supportedUrls": { - │ │ "application/pdf": [ - │ │ {} - │ │ ], - │ │ "image/*": [ - │ │ {} - │ │ ] - │ │ } - │ │ } - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "finishReason": "stop", - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "responseId": "", - │ │ "serviceTier": "default" - │ │ } - │ │ }, - │ │ "response": { - │ │ "body": "", - │ │ "headers": "", - │ │ "messages": [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "providerOptions": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ } - │ │ ], - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "timestamp": "" - │ │ }, - │ │ "steps": [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "finishReason": "stop", - │ │ "providerMetadata": { - │ │ "openai": { - │ │ "responseId": "", - │ │ "serviceTier": "default" - │ │ } - │ │ }, - │ │ "response": { - │ │ "body": "", - │ │ "headers": "", - │ │ "messages": [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "providerOptions": { - │ │ "openai": { - │ │ "itemId": "" - │ │ } - │ │ }, - │ │ "text": "HELLO", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ } - │ │ ], - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "timestamp": "" - │ │ }, - │ │ "usage": { - │ │ "cachedInputTokens": 0, - │ │ "inputTokenDetails": { - │ │ "cacheReadTokens": 0, - │ │ "noCacheTokens": 16 - │ │ }, - │ │ "inputTokens": 16, - │ │ "outputTokenDetails": { - │ │ "reasoningTokens": 0, - │ │ "textTokens": 3 - │ │ }, - │ │ "outputTokens": 3, - │ │ "raw": { - │ │ "input_tokens": 16, - │ │ "input_tokens_details": { - │ │ "cached_tokens": 0 - │ │ }, - │ │ "output_tokens": 3, - │ │ "output_tokens_details": { - │ │ "reasoning_tokens": 0 - │ │ } - │ │ }, - │ │ "reasoningTokens": 0, - │ │ "totalTokens": 19 - │ │ }, - │ │ "warnings": [] - │ │ } - │ │ ], - │ │ "text": "HELLO", - │ │ "toolCalls": [], - │ │ "toolResults": [], - │ │ "totalUsage": { - │ │ "cachedInputTokens": 0, - │ │ "inputTokenDetails": { - │ │ "cacheReadTokens": 0, - │ │ "noCacheTokens": 16 - │ │ }, - │ │ "inputTokens": 16, - │ │ "outputTokenDetails": { - │ │ "reasoningTokens": 0, - │ │ "textTokens": 3 - │ │ }, - │ │ "outputTokens": 3, - │ │ "reasoningTokens": 0, - │ │ "totalTokens": 19 - │ │ }, - │ │ "usage": { - │ │ "cachedInputTokens": 0, - │ │ "inputTokenDetails": { - │ │ "cacheReadTokens": 0, - │ │ "noCacheTokens": 16 - │ │ }, - │ │ "inputTokens": 16, - │ │ "outputTokenDetails": { - │ │ "reasoningTokens": 0, - │ │ "textTokens": 3 - │ │ }, - │ │ "outputTokens": 3, - │ │ "raw": { - │ │ "input_tokens": 16, - │ │ "input_tokens_details": { - │ │ "cached_tokens": 0 - │ │ }, - │ │ "output_tokens": 3, - │ │ "output_tokens_details": { - │ │ "reasoning_tokens": 0 - │ │ } - │ │ }, - │ │ "reasoningTokens": 0, - │ │ "totalTokens": 19 - │ │ }, - │ │ "warnings": [] - │ │ } - │ │ metadata: { - │ │ "braintrust": { - │ │ "integration_name": "ai-sdk", - │ │ "sdk_language": "typescript" - │ │ }, - │ │ "model": "gpt-4o-mini-2024-07-18", - │ │ "provider": "openai.responses" - │ │ } - │ │ metrics: { - │ │ "completion_reasoning_tokens": 0, - │ │ "completion_tokens": 3, - │ │ "prompt_cached_tokens": 0, - │ │ "prompt_tokens": 16, - │ │ "reasoning_tokens": 0, - │ │ "tokens": 19 - │ │ } - │ └── doGenerate [llm] + │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, - │ "prompt": [ + │ "messages": [ │ { - │ "content": [ - │ { - │ "text": "Reply with exactly HELLO and no punctuation.", - │ "type": "text" - │ } - │ ], + │ "content": "Reply with exactly HELLO and no punctuation.", │ "role": "user" │ } - │ ] + │ ], + │ "model": { + │ "config": { + │ "fileIdPrefixes": [ + │ "file-" + │ ], + │ "provider": "openai.responses" + │ }, + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "specificationVersion": "v3", + │ "supportedUrls": { + │ "application/pdf": [ + │ {} + │ ], + │ "image/*": [ + │ {} + │ ] + │ } + │ } │ } │ output: { │ "content": [ │ { │ "providerMetadata": { │ "openai": { - │ "itemId": "" + │ "itemId": "" │ } │ }, │ "text": "HELLO", │ "type": "text" │ } │ ], - │ "finishReason": { - │ "unified": "stop" - │ }, + │ "finishReason": "stop", + │ "output": "HELLO", │ "providerMetadata": { │ "openai": { - │ "responseId": "", + │ "responseId": "", │ "serviceTier": "default" │ } │ }, │ "response": { │ "body": "", - │ "headers": "", + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, + │ "steps": [ + │ { + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "body": "", + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "usage": { + │ "cachedInputTokens": 0, + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 16 + │ }, + │ "inputTokens": 16, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 3 + │ }, + │ "outputTokens": 3, + │ "raw": { + │ "input_tokens": 16, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 3, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "reasoningTokens": 0, + │ "totalTokens": 19 + │ }, + │ "warnings": [] + │ } + │ ], + │ "text": "HELLO", + │ "toolCalls": [], + │ "toolResults": [], + │ "totalUsage": { + │ "cachedInputTokens": 0, + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 16 + │ }, + │ "inputTokens": 16, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 3 + │ }, + │ "outputTokens": 3, + │ "reasoningTokens": 0, + │ "totalTokens": 19 + │ }, │ "usage": { - │ "inputTokens": { - │ "cacheRead": 0, - │ "noCache": 16, - │ "total": 16 + │ "cachedInputTokens": 0, + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 16 │ }, - │ "outputTokens": { - │ "reasoning": 0, - │ "text": 3, - │ "total": 3 + │ "inputTokens": 16, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 3 │ }, + │ "outputTokens": 3, │ "raw": { │ "input_tokens": 16, │ "input_tokens_details": { @@ -5582,7 +5373,9 @@ span_tree: │ "output_tokens_details": { │ "reasoning_tokens": 0 │ } - │ } + │ }, + │ "reasoningTokens": 0, + │ "totalTokens": 19 │ }, │ "warnings": [] │ } @@ -5591,20 +5384,93 @@ span_tree: │ "integration_name": "ai-sdk", │ "sdk_language": "typescript" │ }, - │ "finish_reason": { - │ "unified": "stop" - │ }, │ "model": "gpt-4o-mini-2024-07-18", │ "provider": "openai.responses" │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 3, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 16, - │ "reasoning_tokens": 0, - │ "tokens": 19 - │ } + │ └── doGenerate [llm] + │ input: { + │ "maxOutputTokens": 24, + │ "prompt": [ + │ { + │ "content": [ + │ { + │ "text": "Reply with exactly HELLO and no punctuation.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "HELLO", + │ "type": "text" + │ } + │ ], + │ "finishReason": { + │ "unified": "stop" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "body": "", + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "usage": { + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 16, + │ "total": 16 + │ }, + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 3, + │ "total": 3 + │ }, + │ "raw": { + │ "input_tokens": 16, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 3, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ } + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": { + │ "unified": "stop" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 3, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 16, + │ "reasoning_tokens": 0, + │ "tokens": 19 + │ } ├── ai-sdk-agent-stream-operation │ metadata: { │ "operation": "agent-stream", @@ -5635,114 +5501,114 @@ span_tree: │ metrics: { │ "time_to_first_token": 0 │ } - │ ├── streamText [function] - │ │ input: { - │ │ "maxOutputTokens": 24, - │ │ "messages": [ - │ │ { - │ │ "content": "Reply with exactly STREAM HELLO and no punctuation.", - │ │ "role": "user" - │ │ } - │ │ ], - │ │ "model": { - │ │ "config": { - │ │ "fileIdPrefixes": [ - │ │ "file-" - │ │ ], - │ │ "provider": "openai.responses" - │ │ }, - │ │ "modelId": "gpt-4o-mini-2024-07-18", - │ │ "specificationVersion": "v3", - │ │ "supportedUrls": { - │ │ "application/pdf": [ - │ │ {} - │ │ ], - │ │ "image/*": [ - │ │ {} - │ │ ] - │ │ } - │ │ } - │ │ } - │ │ output: { - │ │ "finishReason": "stop", - │ │ "text": "STREAM HELLO" - │ │ } - │ │ metadata: { - │ │ "braintrust": { - │ │ "integration_name": "ai-sdk", - │ │ "sdk_language": "typescript" - │ │ }, - │ │ "model": "gpt-4o-mini-2024-07-18", - │ │ "provider": "openai.responses" - │ │ } - │ │ metrics: { - │ │ "time_to_first_token": 0 - │ │ } - │ └── doStream [llm] + │ └── streamText [function] │ input: { - │ "includeRawChunks": false, │ "maxOutputTokens": 24, - │ "prompt": [ + │ "messages": [ │ { - │ "content": [ - │ { - │ "text": "Reply with exactly STREAM HELLO and no punctuation.", - │ "type": "text" - │ } - │ ], + │ "content": "Reply with exactly STREAM HELLO and no punctuation.", │ "role": "user" │ } - │ ] - │ } - │ output: { - │ "finishReason": { - │ "unified": "stop" - │ }, - │ "text": "STREAM HELLO", - │ "toolCalls": [], - │ "usage": { - │ "inputTokens": { - │ "cacheRead": 0, - │ "noCache": 17, - │ "total": 17 - │ }, - │ "outputTokens": { - │ "reasoning": 0, - │ "text": 4, - │ "total": 4 + │ ], + │ "model": { + │ "config": { + │ "fileIdPrefixes": [ + │ "file-" + │ ], + │ "provider": "openai.responses" │ }, - │ "raw": { - │ "input_tokens": 17, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 4, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "specificationVersion": "v3", + │ "supportedUrls": { + │ "application/pdf": [ + │ {} + │ ], + │ "image/*": [ + │ {} + │ ] │ } │ } │ } + │ output: { + │ "finishReason": "stop", + │ "text": "STREAM HELLO" + │ } │ metadata: { │ "braintrust": { │ "integration_name": "ai-sdk", │ "sdk_language": "typescript" │ }, - │ "finish_reason": { - │ "unified": "stop" - │ }, │ "model": "gpt-4o-mini-2024-07-18", │ "provider": "openai.responses" │ } │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 4, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 17, - │ "reasoning_tokens": 0, - │ "time_to_first_token": 0, - │ "tokens": 21 + │ "time_to_first_token": 0 │ } + │ └── doStream [llm] + │ input: { + │ "includeRawChunks": false, + │ "maxOutputTokens": 24, + │ "prompt": [ + │ { + │ "content": [ + │ { + │ "text": "Reply with exactly STREAM HELLO and no punctuation.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "finishReason": { + │ "unified": "stop" + │ }, + │ "text": "STREAM HELLO", + │ "toolCalls": [], + │ "usage": { + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 17, + │ "total": 17 + │ }, + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 4, + │ "total": 4 + │ }, + │ "raw": { + │ "input_tokens": 17, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 4, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ } + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": { + │ "unified": "stop" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 4, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 17, + │ "reasoning_tokens": 0, + │ "time_to_first_token": 0, + │ "tokens": 21 + │ } └── ai-sdk-agent-tool-loop-operation metadata: { "operation": "agent-tool-loop", @@ -5779,6 +5645,7 @@ span_tree: } ], "finishReason": "stop", + "output": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "providerMetadata": { "openai": { "responseId": "", @@ -5787,7 +5654,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5974,7 +5840,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -6109,7 +5974,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -6261,7 +6125,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -6458,1491 +6321,807 @@ span_tree: "sdk_language": "typescript" }, "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" + "provider": "openai.responses", + "tools": { + "apply_discount": { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + } + }, + "get_store_price": { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" + } + } + } } - ├── generateText [function] - │ input: { - │ "maxOutputTokens": 256, - │ "messages": [ - │ { - │ "content": "I need help comparing laptop prices before checkout.", - │ "role": "user" - │ }, - │ { - │ "content": "I can compare store prices and apply a discount code.", - │ "role": "assistant" - │ }, - │ { - │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - │ "role": "user" - │ } - │ ], - │ "model": { - │ "config": { - │ "fileIdPrefixes": [ - │ "file-" - │ ], - │ "provider": "openai.responses" - │ }, - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "specificationVersion": "v3", - │ "supportedUrls": { - │ "application/pdf": [ - │ {} - │ ], - │ "image/*": [ - │ {} - │ ] - │ } - │ }, - │ "system": "You are a shopping assistant. Use the tools before answering pricing questions.", - │ "temperature": 0, - │ "tools": { - │ "apply_discount": { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" - │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ } - │ }, - │ "get_store_price": { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" - │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ } - │ } - │ } - │ } - │ output: { - │ "content": [ - │ { - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - │ "type": "text" - │ } - │ ], - │ "finishReason": "stop", - │ "providerMetadata": { - │ "openai": { - │ "responseId": "", - │ "serviceTier": "default" - │ } - │ }, - │ "response": { - │ "body": "", - │ "headers": "", - │ "messages": [ - │ { - │ "content": [ - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ }, - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ }, - │ { - │ "content": [ - │ { - │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ }, - │ { - │ "content": [ - │ { - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - │ "type": "text" - │ } - │ ], - │ "role": "assistant" - │ } - │ ], - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "timestamp": "" - │ }, - │ "steps": [ - │ { - │ "content": [ - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "dynamic": false, - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ }, - │ { - │ "dynamic": false, - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ } - │ ], - │ "finishReason": "tool-calls", - │ "providerMetadata": { - │ "openai": { - │ "responseId": "", - │ "serviceTier": "default" - │ } - │ }, - │ "response": { - │ "body": "", - │ "headers": "", - │ "messages": [ - │ { - │ "content": [ - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ }, - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ } - │ ], - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "timestamp": "" - │ }, - │ "usage": { - │ "cachedInputTokens": 0, - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 173 - │ }, - │ "inputTokens": 173, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 59 - │ }, - │ "outputTokens": 59, - │ "raw": { - │ "input_tokens": 173, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 59, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } - │ }, - │ "reasoningTokens": 0, - │ "totalTokens": 232 - │ }, - │ "warnings": [] - │ }, - │ { - │ "content": [ - │ { - │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-call" - │ }, - │ { - │ "dynamic": false, - │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, - │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-result" - │ } - │ ], - │ "finishReason": "tool-calls", - │ "providerMetadata": { - │ "openai": { - │ "responseId": "", - │ "serviceTier": "default" - │ } - │ }, - │ "response": { - │ "body": "", - │ "headers": "", - │ "messages": [ - │ { - │ "content": [ - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ }, - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ }, - │ { - │ "content": [ - │ { - │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ } - │ ], - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "timestamp": "" - │ }, - │ "usage": { - │ "cachedInputTokens": 0, - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 260 - │ }, - │ "inputTokens": 260, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 21 - │ }, - │ "outputTokens": 21, - │ "raw": { - │ "input_tokens": 260, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 21, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } - │ }, - │ "reasoningTokens": 0, - │ "totalTokens": 281 - │ }, - │ "warnings": [] - │ }, - │ { - │ "content": [ - │ { - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - │ "type": "text" - │ } - │ ], - │ "finishReason": "stop", - │ "providerMetadata": { - │ "openai": { - │ "responseId": "", - │ "serviceTier": "default" - │ } - │ }, - │ "response": { - │ "body": "", - │ "headers": "", - │ "messages": [ - │ { - │ "content": [ - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ }, - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ }, - │ { - │ "content": [ - │ { - │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ }, - │ { - │ "content": [ - │ { - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - │ "type": "text" - │ } - │ ], - │ "role": "assistant" - │ } - │ ], - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "timestamp": "" - │ }, - │ "usage": { - │ "cachedInputTokens": 0, - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 308 - │ }, - │ "inputTokens": 308, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 62 - │ }, - │ "outputTokens": 62, - │ "raw": { - │ "input_tokens": 308, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 62, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } - │ }, - │ "reasoningTokens": 0, - │ "totalTokens": 370 - │ }, - │ "warnings": [] - │ } - │ ], - │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - │ "toolCalls": [], - │ "toolResults": [], - │ "totalUsage": { - │ "cachedInputTokens": 0, - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 741 - │ }, - │ "inputTokens": 741, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 142 - │ }, - │ "outputTokens": 142, - │ "reasoningTokens": 0, - │ "totalTokens": 883 - │ }, - │ "usage": { - │ "cachedInputTokens": 0, - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 308 - │ }, - │ "inputTokens": 308, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 62 - │ }, - │ "outputTokens": 62, - │ "raw": { - │ "input_tokens": 308, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 62, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } - │ }, - │ "reasoningTokens": 0, - │ "totalTokens": 370 - │ }, - │ "warnings": [] - │ } - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses", - │ "tools": { - │ "apply_discount": { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" - │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ } - │ }, - │ "get_store_price": { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" - │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ } - │ } - │ } - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 142, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 741, - │ "reasoning_tokens": 0, - │ "tokens": 883 - │ } - ├── doGenerate [llm] - │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, - │ "maxOutputTokens": 256, - │ "prompt": [ - │ { - │ "content": "You are a shopping assistant. Use the tools before answering pricing questions.", - │ "role": "system" - │ }, - │ { - │ "content": [ - │ { - │ "text": "I need help comparing laptop prices before checkout.", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "text": "I can compare store prices and apply a discount code.", - │ "type": "text" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ } - │ ], - │ "temperature": 0, - │ "toolChoice": { - │ "type": "auto" - │ }, - │ "tools": [ - │ { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" - │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ }, - │ "name": "get_store_price", - │ "type": "function" - │ }, - │ { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" - │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ }, - │ "name": "apply_discount", - │ "type": "function" - │ } - │ ] - │ } - │ output: { - │ "content": [ - │ { - │ "input": "{\"item\":\"laptop\",\"store\":\"StoreA\"}", - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": "{\"item\":\"laptop\",\"store\":\"StoreB\"}", - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ } - │ ], - │ "finishReason": { - │ "unified": "tool-calls" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "responseId": "", - │ "serviceTier": "default" - │ } - │ }, - │ "response": { - │ "body": "", - │ "headers": "", - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "timestamp": "" - │ }, - │ "usage": { - │ "inputTokens": { - │ "cacheRead": 0, - │ "noCache": 173, - │ "total": 173 - │ }, - │ "outputTokens": { - │ "reasoning": 0, - │ "text": 59, - │ "total": 59 - │ }, - │ "raw": { - │ "input_tokens": 173, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 59, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } - │ } - │ }, - │ "warnings": [] - │ } - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "finish_reason": { - │ "unified": "tool-calls" - │ }, - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 59, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 173, - │ "reasoning_tokens": 0, - │ "tokens": 232 - │ } - ├── get_store_price [tool] - │ input: { - │ "item": "laptop", - │ "store": "StoreA" - │ } - │ output: "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - ├── get_store_price [tool] - │ input: { - │ "item": "laptop", - │ "store": "StoreB" - │ } - │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - ├── doGenerate [llm] - │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, - │ "maxOutputTokens": 256, - │ "prompt": [ - │ { - │ "content": "You are a shopping assistant. Use the tools before answering pricing questions.", - │ "role": "system" - │ }, - │ { - │ "content": [ - │ { - │ "text": "I need help comparing laptop prices before checkout.", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "text": "I can compare store prices and apply a discount code.", - │ "type": "text" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ }, - │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-result" - │ } - │ ], - │ "role": "tool" - │ } - │ ], - │ "temperature": 0, - │ "toolChoice": { - │ "type": "auto" - │ }, - │ "tools": [ - │ { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" - │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ }, - │ "name": "get_store_price", - │ "type": "function" - │ }, - │ { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" - │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ }, - │ "name": "apply_discount", - │ "type": "function" - │ } - │ ] - │ } - │ output: { - │ "content": [ - │ { - │ "input": "{\"discountCode\":\"SAVE20\",\"total\":999}", - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "apply_discount", - │ "type": "tool-call" - │ } - │ ], - │ "finishReason": { - │ "unified": "tool-calls" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "responseId": "", - │ "serviceTier": "default" - │ } - │ }, - │ "response": { - │ "body": "", - │ "headers": "", - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "timestamp": "" - │ }, - │ "usage": { - │ "inputTokens": { - │ "cacheRead": 0, - │ "noCache": 260, - │ "total": 260 - │ }, - │ "outputTokens": { - │ "reasoning": 0, - │ "text": 21, - │ "total": 21 - │ }, - │ "raw": { - │ "input_tokens": 260, - │ "input_tokens_details": { - │ "cached_tokens": 0 - │ }, - │ "output_tokens": 21, - │ "output_tokens_details": { - │ "reasoning_tokens": 0 - │ } - │ } - │ }, - │ "warnings": [] - │ } - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "finish_reason": { - │ "unified": "tool-calls" - │ }, - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 21, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 260, - │ "reasoning_tokens": 0, - │ "tokens": 281 - │ } - ├── apply_discount [tool] - │ input: { - │ "discountCode": "SAVE20", - │ "total": 999 - │ } - │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - └── doGenerate [llm] + └── generateText [function] input: { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 256, - "prompt": [ - { - "content": "You are a shopping assistant. Use the tools before answering pricing questions.", - "role": "system" - }, + "messages": [ { - "content": [ - { - "text": "I need help comparing laptop prices before checkout.", - "type": "text" - } - ], + "content": "I need help comparing laptop prices before checkout.", "role": "user" }, { - "content": [ - { - "text": "I can compare store prices and apply a discount code.", - "type": "text" - } - ], + "content": "I can compare store prices and apply a discount code.", "role": "assistant" }, { - "content": [ - { - "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "type": "text" - } - ], + "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", "role": "user" - }, - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } + } + ], + "model": { + "config": { + "fileIdPrefixes": [ + "file-" ], - "role": "assistant" + "provider": "openai.responses" }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } + "modelId": "gpt-4o-mini-2024-07-18", + "specificationVersion": "v3", + "supportedUrls": { + "application/pdf": [ + {} ], - "role": "tool" + "image/*": [ + {} + ] } - ], - "temperature": 0, - "toolChoice": { - "type": "auto" }, - "tools": [ - { - "description": "Get the price of an item at a store", + "system": "You are a shopping assistant. Use the tools before answering pricing questions.", + "temperature": 0, + "tools": { + "apply_discount": { + "description": "Apply a discount code to a total", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { - "item": { - "description": "The item to price", + "discountCode": { + "description": "The discount code to apply", "type": "string" }, - "store": { - "description": "The store name", - "type": "string" + "total": { + "description": "The original total", + "type": "number" } }, "required": [ - "item", - "store" + "discountCode", + "total" ], "type": "object" - }, - "name": "get_store_price", - "type": "function" + } }, - { - "description": "Apply a discount code to a total", + "get_store_price": { + "description": "Get the price of an item at a store", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { - "discountCode": { - "description": "The discount code to apply", + "item": { + "description": "The item to price", "type": "string" }, - "total": { - "description": "The original total", - "type": "number" + "store": { + "description": "The store name", + "type": "string" } }, "required": [ - "discountCode", - "total" + "item", + "store" ], "type": "object" - }, - "name": "apply_discount", - "type": "function" + } } - ] + } } output: { "content": [ { "providerMetadata": { "openai": { - "itemId": "" + "itemId": "" } }, "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "type": "text" } ], - "finishReason": { - "unified": "stop" - }, + "finishReason": "stop", + "output": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "providerMetadata": { "openai": { - "responseId": "", + "responseId": "", "serviceTier": "default" } }, "response": { "body": "", - "headers": "", - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "usage": { - "inputTokens": { - "cacheRead": 0, - "noCache": 308, - "total": 308 - }, - "outputTokens": { - "reasoning": 0, - "text": 62, - "total": 62 - }, - "raw": { + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "role": "assistant" + } + ], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "steps": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "dynamic": false, + "input": { + "item": "laptop", + "store": "StoreA" + }, + "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "dynamic": false, + "input": { + "item": "laptop", + "store": "StoreB" + }, + "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 173 + }, + "inputTokens": 173, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 59 + }, + "outputTokens": 59, + "raw": { + "input_tokens": 173, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 59, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "reasoningTokens": 0, + "totalTokens": 232 + }, + "warnings": [] + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + }, + { + "dynamic": false, + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 260 + }, + "inputTokens": 260, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 21 + }, + "outputTokens": 21, + "raw": { + "input_tokens": 260, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 21, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "reasoningTokens": 0, + "totalTokens": 281 + }, + "warnings": [] + }, + { + "content": [ + { + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "finishReason": "stop", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "messages": [ + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "role": "assistant" + } + ], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 308 + }, + "inputTokens": 308, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 62 + }, + "outputTokens": 62, + "raw": { + "input_tokens": 308, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 62, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "reasoningTokens": 0, + "totalTokens": 370 + }, + "warnings": [] + } + ], + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "toolCalls": [], + "toolResults": [], + "totalUsage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 741 + }, + "inputTokens": 741, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 142 + }, + "outputTokens": 142, + "reasoningTokens": 0, + "totalTokens": 883 + }, + "usage": { + "cachedInputTokens": 0, + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 308 + }, + "inputTokens": 308, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 62 + }, + "outputTokens": 62, + "raw": { "input_tokens": 308, "input_tokens_details": { "cached_tokens": 0 @@ -7951,7 +7130,9 @@ span_tree: "output_tokens_details": { "reasoning_tokens": 0 } - } + }, + "reasoningTokens": 0, + "totalTokens": 370 }, "warnings": [] } @@ -7960,17 +7141,722 @@ span_tree: "integration_name": "ai-sdk", "sdk_language": "typescript" }, - "finish_reason": { - "unified": "stop" - }, "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - } - metrics: { - "completion_reasoning_tokens": 0, - "completion_tokens": 62, - "prompt_cached_tokens": 0, - "prompt_tokens": 308, - "reasoning_tokens": 0, - "tokens": 370 + "provider": "openai.responses", + "tools": { + "apply_discount": { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + } + }, + "get_store_price": { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" + } + } + } } + ├── doGenerate [llm] + │ input: { + │ "maxOutputTokens": 256, + │ "prompt": [ + │ { + │ "content": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "I need help comparing laptop prices before checkout.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "text": "I can compare store prices and apply a discount code.", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ], + │ "temperature": 0, + │ "toolChoice": { + │ "type": "auto" + │ }, + │ "tools": [ + │ { + │ "description": "Get the price of an item at a store", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "item": { + │ "description": "The item to price", + │ "type": "string" + │ }, + │ "store": { + │ "description": "The store name", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "item", + │ "store" + │ ], + │ "type": "object" + │ }, + │ "name": "get_store_price", + │ "type": "function" + │ }, + │ { + │ "description": "Apply a discount code to a total", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "discountCode": { + │ "description": "The discount code to apply", + │ "type": "string" + │ }, + │ "total": { + │ "description": "The original total", + │ "type": "number" + │ } + │ }, + │ "required": [ + │ "discountCode", + │ "total" + │ ], + │ "type": "object" + │ }, + │ "name": "apply_discount", + │ "type": "function" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "input": "{\"item\":\"laptop\",\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": "{\"item\":\"laptop\",\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": { + │ "unified": "tool-calls" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "body": "", + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "usage": { + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 173, + │ "total": 173 + │ }, + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 59, + │ "total": 59 + │ }, + │ "raw": { + │ "input_tokens": 173, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 59, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ } + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": { + │ "unified": "tool-calls" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 59, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 173, + │ "reasoning_tokens": 0, + │ "tokens": 232 + │ } + ├── get_store_price [tool] + │ input: { + │ "item": "laptop", + │ "store": "StoreA" + │ } + │ output: "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + ├── get_store_price [tool] + │ input: { + │ "item": "laptop", + │ "store": "StoreB" + │ } + │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + ├── doGenerate [llm] + │ input: { + │ "maxOutputTokens": 256, + │ "prompt": [ + │ { + │ "content": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "I need help comparing laptop prices before checkout.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "text": "I can compare store prices and apply a discount code.", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "temperature": 0, + │ "toolChoice": { + │ "type": "auto" + │ }, + │ "tools": [ + │ { + │ "description": "Get the price of an item at a store", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "item": { + │ "description": "The item to price", + │ "type": "string" + │ }, + │ "store": { + │ "description": "The store name", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "item", + │ "store" + │ ], + │ "type": "object" + │ }, + │ "name": "get_store_price", + │ "type": "function" + │ }, + │ { + │ "description": "Apply a discount code to a total", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "discountCode": { + │ "description": "The discount code to apply", + │ "type": "string" + │ }, + │ "total": { + │ "description": "The original total", + │ "type": "number" + │ } + │ }, + │ "required": [ + │ "discountCode", + │ "total" + │ ], + │ "type": "object" + │ }, + │ "name": "apply_discount", + │ "type": "function" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "input": "{\"discountCode\":\"SAVE20\",\"total\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": { + │ "unified": "tool-calls" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "body": "", + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "usage": { + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 260, + │ "total": 260 + │ }, + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 21, + │ "total": 21 + │ }, + │ "raw": { + │ "input_tokens": 260, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 21, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ } + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": { + │ "unified": "tool-calls" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 21, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 260, + │ "reasoning_tokens": 0, + │ "tokens": 281 + │ } + ├── apply_discount [tool] + │ input: { + │ "discountCode": "SAVE20", + │ "total": 999 + │ } + │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + └── doGenerate [llm] + input: { + "maxOutputTokens": 256, + "prompt": [ + { + "content": "You are a shopping assistant. Use the tools before answering pricing questions.", + "role": "system" + }, + { + "content": [ + { + "text": "I need help comparing laptop prices before checkout.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I can compare store prices and apply a discount code.", + "type": "text" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "item": "laptop", + "store": "StoreA" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + }, + { + "input": { + "item": "laptop", + "store": "StoreB" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + }, + { + "output": { + "type": "text", + "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_store_price", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "discountCode": "SAVE20", + "total": 999 + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "text", + "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + }, + "providerOptions": { + "openai": { + "itemId": "" + } + }, + "toolName": "apply_discount", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "temperature": 0, + "toolChoice": { + "type": "auto" + }, + "tools": [ + { + "description": "Get the price of an item at a store", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "item": { + "description": "The item to price", + "type": "string" + }, + "store": { + "description": "The store name", + "type": "string" + } + }, + "required": [ + "item", + "store" + ], + "type": "object" + }, + "name": "get_store_price", + "type": "function" + }, + { + "description": "Apply a discount code to a total", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "discountCode": { + "description": "The discount code to apply", + "type": "string" + }, + "total": { + "description": "The original total", + "type": "number" + } + }, + "required": [ + "discountCode", + "total" + ], + "type": "object" + }, + "name": "apply_discount", + "type": "function" + } + ] + } + output: { + "content": [ + { + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "type": "text" + } + ], + "finishReason": { + "unified": "stop" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "response": { + "body": "", + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 308, + "total": 308 + }, + "outputTokens": { + "reasoning": 0, + "text": 62, + "total": 62 + }, + "raw": { + "input_tokens": 308, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 62, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + }, + "warnings": [] + } + metadata: { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "stop" + }, + "model": "gpt-4o-mini-2024-07-18", + "provider": "openai.responses" + } + metrics: { + "completion_reasoning_tokens": 0, + "completion_tokens": 62, + "prompt_cached_tokens": 0, + "prompt_tokens": 308, + "reasoning_tokens": 0, + "tokens": 370 + } diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.json index 3da00e3e5..fb047d529 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.json @@ -16,9 +16,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -56,7 +53,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -141,6 +137,7 @@ } ], "finishReason": "stop", + "output": "PARIS", "providerMetadata": { "openai": { "responseId": "", @@ -149,7 +146,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -191,7 +187,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -319,9 +314,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 32, "prompt": [ { @@ -375,7 +367,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -425,9 +416,6 @@ } ], "input": { - "experimental_output": { - "responseFormat": {} - }, "maxOutputTokens": 32, "model": { "config": { @@ -481,6 +469,9 @@ } ], "finishReason": "stop", + "output": { + "answer": "4" + }, "providerMetadata": { "openai": { "responseId": "", @@ -489,7 +480,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -531,7 +521,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -860,9 +849,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -929,7 +915,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -991,9 +976,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1095,7 +1077,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1157,9 +1138,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1296,7 +1274,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1358,9 +1335,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 128, "prompt": [ { @@ -1532,7 +1506,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -1672,7 +1645,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1857,7 +1829,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -1963,7 +1934,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2104,7 +2074,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2280,7 +2249,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2573,9 +2541,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2618,7 +2583,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2708,6 +2672,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "openai": { "responseId": "", @@ -2716,7 +2681,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2758,7 +2722,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -2869,9 +2832,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -2914,7 +2874,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3004,6 +2963,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "openai": { "responseId": "", @@ -3012,7 +2972,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3054,7 +3013,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3174,9 +3132,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3232,7 +3187,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -3319,6 +3273,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "anthropic": { "cacheCreationInputTokens": 0, @@ -3342,7 +3297,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3390,7 +3344,6 @@ "rawFinishReason": "end_turn", "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3491,9 +3444,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3549,7 +3499,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "claude-haiku-4-5-20251001" }, "usage": { @@ -3636,6 +3585,7 @@ } ], "finishReason": "stop", + "output": "CACHE_OK", "providerMetadata": { "anthropic": { "cacheCreationInputTokens": 0, @@ -3659,7 +3609,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3707,7 +3656,6 @@ "rawFinishReason": "end_turn", "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -3817,9 +3765,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -3857,7 +3802,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -3942,6 +3886,7 @@ } ], "finishReason": "stop", + "output": "DENIED", "providerMetadata": { "openai": { "responseId": "", @@ -4055,31 +4000,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -4226,31 +4146,6 @@ }, "user": null }, - "headers": { - "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "", - "connection": "keep-alive", - "content-type": "application/json", - "date": "", - "openai-organization": "braintrust-data", - "openai-processing-ms": "", - "openai-project": "", - "openai-version": "", - "server": "cloudflare", - "set-cookie": "", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-ratelimit-limit-requests": "30000", - "x-ratelimit-limit-tokens": "150000000", - "x-ratelimit-remaining-requests": "", - "x-ratelimit-remaining-tokens": "", - "x-ratelimit-reset-requests": "", - "x-ratelimit-reset-tokens": "", - "x-request-id": "" - }, "messages": [ { "content": [ @@ -4370,9 +4265,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 32, "prompt": [ { @@ -4426,7 +4318,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4524,7 +4415,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4736,9 +4626,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 24, "prompt": [ { @@ -4775,7 +4662,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -4865,6 +4751,7 @@ } ], "finishReason": "stop", + "output": "HELLO", "providerMetadata": { "openai": { "responseId": "", @@ -4873,7 +4760,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -4915,7 +4801,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5162,9 +5047,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 256, "prompt": [ { @@ -5288,7 +5170,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -5361,9 +5242,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 256, "prompt": [ { @@ -5539,7 +5417,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -5602,9 +5479,6 @@ "type": "llm", "children": [], "input": { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 256, "prompt": [ { @@ -5815,7 +5689,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -5960,6 +5833,7 @@ } ], "finishReason": "stop", + "output": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "providerMetadata": { "openai": { "responseId": "", @@ -5968,7 +5842,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -6155,7 +6028,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -6290,7 +6162,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -6442,7 +6313,6 @@ }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.txt index 0603c87c9..525bedcbf 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v6-wrapped.span-tree.txt @@ -47,6 +47,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "PARIS", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -55,7 +56,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -97,7 +97,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -200,9 +199,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -240,7 +236,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -299,9 +294,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "experimental_output": { - │ "responseFormat": {} - │ }, │ "maxOutputTokens": 32, │ "model": { │ "config": { @@ -355,6 +347,9 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": { + │ "answer": "4" + │ }, │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -363,7 +358,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -405,7 +399,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -508,9 +501,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -564,7 +554,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -879,7 +868,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1064,7 +1052,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1170,7 +1157,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1311,7 +1297,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1487,7 +1472,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1763,9 +1747,6 @@ span_tree: │ } │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1832,7 +1813,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -1886,9 +1866,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -1990,7 +1967,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2044,9 +2020,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -2183,7 +2156,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2237,9 +2209,6 @@ span_tree: │ │ output: "{\"condition\":\"sunny\",\"location\":\"Paris, France\",\"temperatureC\":22}" │ ├── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 128, │ │ "prompt": [ │ │ { @@ -2411,7 +2380,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2510,6 +2478,7 @@ span_tree: │ │ } │ │ ], │ │ "finishReason": "stop", + │ │ "output": "CACHE_OK", │ │ "providerMetadata": { │ │ "openai": { │ │ "responseId": "", @@ -2518,7 +2487,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2560,7 +2528,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -2663,9 +2630,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -2708,7 +2672,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "gpt-4o-mini-2024-07-18", │ │ "timestamp": "" │ │ }, @@ -2797,6 +2760,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "CACHE_OK", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -2805,7 +2769,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2847,7 +2810,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2950,9 +2912,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -2995,7 +2954,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -3086,6 +3044,7 @@ span_tree: │ │ } │ │ ], │ │ "finishReason": "stop", + │ │ "output": "CACHE_OK", │ │ "providerMetadata": { │ │ "anthropic": { │ │ "cacheCreationInputTokens": 0, @@ -3109,7 +3068,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -3157,7 +3115,6 @@ span_tree: │ │ "rawFinishReason": "end_turn", │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "messages": [ │ │ { │ │ "content": [ @@ -3250,9 +3207,6 @@ span_tree: │ │ } │ │ └── doGenerate [llm] │ │ input: { - │ │ "headers": { - │ │ "user-agent": "ai/6.0.1" - │ │ }, │ │ "maxOutputTokens": 24, │ │ "prompt": [ │ │ { @@ -3308,7 +3262,6 @@ span_tree: │ │ }, │ │ "response": { │ │ "body": "", - │ │ "headers": "", │ │ "modelId": "claude-haiku-4-5-20251001" │ │ }, │ │ "usage": { @@ -3394,6 +3347,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "CACHE_OK", │ "providerMetadata": { │ "anthropic": { │ "cacheCreationInputTokens": 0, @@ -3417,7 +3371,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3465,7 +3418,6 @@ span_tree: │ "rawFinishReason": "end_turn", │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3558,9 +3510,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -3616,7 +3565,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "claude-haiku-4-5-20251001" │ }, │ "usage": { @@ -3705,6 +3653,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "DENIED", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -3818,31 +3767,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -3989,31 +3913,6 @@ span_tree: │ }, │ "user": null │ }, - │ "headers": { - │ "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", - │ "alt-svc": "h3=\":443\"; ma=86400", - │ "cf-cache-status": "DYNAMIC", - │ "cf-ray": "", - │ "connection": "keep-alive", - │ "content-type": "application/json", - │ "date": "", - │ "openai-organization": "braintrust-data", - │ "openai-processing-ms": "", - │ "openai-project": "", - │ "openai-version": "", - │ "server": "cloudflare", - │ "set-cookie": "", - │ "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - │ "transfer-encoding": "chunked", - │ "x-content-type-options": "nosniff", - │ "x-ratelimit-limit-requests": "30000", - │ "x-ratelimit-limit-tokens": "150000000", - │ "x-ratelimit-remaining-requests": "", - │ "x-ratelimit-remaining-tokens": "", - │ "x-ratelimit-reset-requests": "", - │ "x-ratelimit-reset-tokens": "", - │ "x-request-id": "" - │ }, │ "messages": [ │ { │ "content": [ @@ -4116,9 +4015,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -4156,7 +4052,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -4258,7 +4153,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -4299,9 +4193,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 32, │ "prompt": [ │ { @@ -4355,7 +4246,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -4590,6 +4480,7 @@ span_tree: │ } │ ], │ "finishReason": "stop", + │ "output": "HELLO", │ "providerMetadata": { │ "openai": { │ "responseId": "", @@ -4598,7 +4489,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -4640,7 +4530,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -4743,9 +4632,6 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 24, │ "prompt": [ │ { @@ -4782,7 +4668,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -5045,6 +4930,7 @@ span_tree: } ], "finishReason": "stop", + "output": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "providerMetadata": { "openai": { "responseId": "", @@ -5053,7 +4939,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5240,7 +5125,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5375,7 +5259,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5527,7 +5410,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "messages": [ { "content": [ @@ -5774,9 +5656,6 @@ span_tree: } ├── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 256, │ "prompt": [ │ { @@ -5900,7 +5779,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -5961,9 +5839,6 @@ span_tree: │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" ├── doGenerate [llm] │ input: { - │ "headers": { - │ "user-agent": "ai/6.0.1" - │ }, │ "maxOutputTokens": 256, │ "prompt": [ │ { @@ -6139,7 +6014,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -6194,9 +6068,6 @@ span_tree: │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" └── doGenerate [llm] input: { - "headers": { - "user-agent": "ai/6.0.1" - }, "maxOutputTokens": 256, "prompt": [ { @@ -6407,7 +6278,6 @@ span_tree: }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.json index d154db703..779d8f39d 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.json @@ -84,9 +84,6 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, "maxOutputTokens": 24, "maxRetries": 2, "messages": [ @@ -121,7 +118,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -168,7 +164,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -351,9 +346,6 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, "maxOutputTokens": 32, "maxRetries": 2, "messages": [ @@ -406,7 +398,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -453,7 +444,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -662,7 +652,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -709,7 +698,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -956,6 +944,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1067,6 +1056,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1213,6 +1203,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1394,6 +1385,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1607,9 +1599,7 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "maxRetries": 2, "messages": [ @@ -1759,7 +1749,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -1844,7 +1833,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -1955,7 +1943,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2066,7 +2053,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2177,7 +2163,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2433,7 +2418,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2480,9 +2464,6 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, "maxOutputTokens": 32, "maxRetries": 2, "model": { @@ -2519,7 +2500,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2596,7 +2576,6 @@ } }, "response": { - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2678,7 +2657,6 @@ } }, "response": { - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2734,6 +2712,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "messages": [ { @@ -2801,9 +2780,7 @@ } ], "input": { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - }, + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "maxRetries": 2, "messages": [ @@ -2837,7 +2814,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2884,7 +2860,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2991,6 +2966,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "messages": [ { @@ -3058,9 +3034,7 @@ } ], "input": { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop" - }, + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "maxRetries": 2, "messages": [ @@ -3094,7 +3068,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -3141,7 +3114,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -3251,6 +3223,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "messages": [ { @@ -3431,6 +3404,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "messages": [ { @@ -3643,6 +3617,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "messages": [ { @@ -3867,9 +3842,7 @@ } ], "input": { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - }, + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "maxRetries": 2, "messages": [ @@ -4042,7 +4015,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4136,7 +4108,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4276,7 +4247,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4371,7 +4341,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4551,12 +4520,1981 @@ "operation": "agent-tool-loop", "testRunId": "" } + }, + { + "name": "ai-sdk-workflow-agent-stream-operation", + "children": [ + { + "name": "WorkflowAgent.stream", + "type": "function", + "children": [ + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 84 + }, + "inputTokens": 84, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 84, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 92 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 84, + "tokens": 92 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 123 + }, + "inputTokens": 123, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 123, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 131 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 123, + "tokens": 131 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 162 + }, + "inputTokens": 162, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 162, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 170 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 162, + "tokens": 170 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 201 + }, + "inputTokens": 201, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 201, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 209 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 201, + "tokens": 209 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": { + "messages": [ + { + "content": "Use get_weather for Paris, France, then reply with one short sentence.", + "role": "user" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "steps": [ + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 0, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 84 + }, + "inputTokens": 84, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 84, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 92 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 1, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 123 + }, + "inputTokens": 123, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 123, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 131 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 2, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 162 + }, + "inputTokens": 162, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 162, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 170 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 3, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 201 + }, + "inputTokens": 201, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 201, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 209 + }, + "warnings": [] + } + ], + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "totalUsage": { + "inputTokens": 570, + "outputTokens": 32, + "totalTokens": 602 + }, + "usage": { + "inputTokens": 570, + "outputTokens": 32, + "totalTokens": 602 + }, + "warnings": [] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "maxRetries": 2, + "temperature": 0, + "toolChoice": "required" + }, + "provider": "openai.responses", + "tools": { + "get_weather": { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + } + } + } + ], + "metadata": { + "operation": "workflow-agent-stream", + "testRunId": "" + } + }, + { + "name": "ai-sdk-workflow-agent-stream-prompt-operation", + "children": [ + { + "name": "WorkflowAgent.stream", + "type": "function", + "children": [ + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 70 + }, + "inputTokens": 70, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 70, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 78 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 70, + "tokens": 78 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 109 + }, + "inputTokens": 109, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 109, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 117 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 109, + "tokens": 117 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 148 + }, + "inputTokens": 148, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 148, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 156 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 148, + "tokens": 156 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "doGenerate", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "response": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 187 + }, + "inputTokens": 187, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 187, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 195 + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "temperature": 0 + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + ] + }, + "metrics": { + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 187, + "tokens": 195 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "toolName": "get_weather" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": { + "messages": [ + { + "content": "What's the weather in Paris?", + "role": "user" + } + ] + }, + "output": { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "steps": [ + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 0, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 70 + }, + "inputTokens": 70, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 70, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 78 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 1, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 109 + }, + "inputTokens": 109, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 109, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 117 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 2, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 148 + }, + "inputTokens": 148, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 148, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 156 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 3, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 187 + }, + "inputTokens": 187, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 187, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 195 + }, + "warnings": [] + } + ], + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "totalUsage": { + "inputTokens": 514, + "outputTokens": 32, + "totalTokens": 546 + }, + "usage": { + "inputTokens": 514, + "outputTokens": 32, + "totalTokens": 546 + }, + "warnings": [] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "maxRetries": 2, + "temperature": 0, + "toolChoice": "required" + }, + "provider": "openai.responses", + "tools": { + "get_weather": { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + } + } + } + ], + "metadata": { + "operation": "workflow-agent-stream-prompt", + "testRunId": "" + } } ], "metadata": { "aiSdkVersion": "7.0.0", "scenario": "ai-sdk-instrumentation", - "testRunId": "" + "testRunId": "", + "workflowVersion": "1.0.8" } } ] diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.txt index 7e3892a80..738f555b6 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-auto-hook.span-tree.txt @@ -3,7 +3,8 @@ span_tree: metadata: { "aiSdkVersion": "7.0.0", "scenario": "ai-sdk-instrumentation", - "testRunId": "" + "testRunId": "", + "workflowVersion": "1.0.8" } ├── ai-sdk-generate-operation │ metadata: { @@ -12,9 +13,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, │ "maxOutputTokens": 24, │ "maxRetries": 2, │ "messages": [ @@ -49,7 +47,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -96,7 +93,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -263,9 +259,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, │ "maxOutputTokens": 32, │ "maxRetries": 2, │ "messages": [ @@ -318,7 +311,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -365,7 +357,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -561,7 +552,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -608,7 +598,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -884,9 +873,7 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, + │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ "maxOutputTokens": 128, │ "maxRetries": 2, │ "messages": [ @@ -1036,7 +1023,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1121,7 +1107,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1232,7 +1217,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1343,7 +1327,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1454,7 +1437,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1671,6 +1653,7 @@ span_tree: │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -1774,6 +1757,7 @@ span_tree: │ │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -1912,6 +1896,7 @@ span_tree: │ │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -2085,6 +2070,7 @@ span_tree: │ │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -2298,9 +2284,6 @@ span_tree: │ } │ └── generateObject [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, │ "maxOutputTokens": 32, │ "maxRetries": 2, │ "model": { @@ -2337,7 +2320,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2398,7 +2380,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2484,7 +2465,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2544,7 +2524,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2595,9 +2574,7 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - │ }, + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "maxRetries": 2, │ "messages": [ @@ -2631,7 +2608,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2678,7 +2654,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2768,6 +2743,7 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "messages": [ │ { @@ -2839,9 +2815,7 @@ span_tree: │ } │ └── streamText [function] │ input: { - │ "headers": { - │ "user-agent": "ai-sdk-agent/tool-loop" - │ }, + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "maxRetries": 2, │ "messages": [ @@ -2875,7 +2849,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2922,7 +2895,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3015,6 +2987,7 @@ span_tree: │ } │ └── doStream [llm] │ input: { + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "messages": [ │ { @@ -3079,680 +3052,2519 @@ span_tree: │ "prompt_tokens": 27, │ "tokens": 31 │ } - └── ai-sdk-agent-tool-loop-operation - metadata: { - "operation": "agent-tool-loop", - "testRunId": "" - } - └── generateText [function] - input: { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - }, - "maxOutputTokens": 256, - "maxRetries": 2, - "messages": [ - { - "content": "I need help comparing laptop prices before checkout.", - "role": "user" - }, - { - "content": "I can compare store prices and apply a discount code.", - "role": "assistant" - }, - { - "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "role": "user" - } - ], - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "temperature": 0, - "tools": { - "apply_discount": { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" - }, - "total": { - "description": "The original total", - "type": "number" - } - }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - } - }, - "get_store_price": { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } - }, - "required": [ - "item", - "store" - ], - "type": "object" - } - } - } - } - output: { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - }, - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "role": "assistant" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "responseMessages": "", - "steps": [ - { - "callId": "", - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "finishReason": "tool-calls", - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "runtimeContext": {}, - "stepNumber": 0, - "toolsContext": {}, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 173 - }, - "inputTokens": 173, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 59 - }, - "outputTokens": 59, - "raw": { - "input_tokens": 173, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 59, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "totalTokens": 232 - }, - "warnings": [] - }, - { - "callId": "", - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "finishReason": "tool-calls", - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "runtimeContext": {}, - "stepNumber": 1, - "toolsContext": {}, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 260 - }, - "inputTokens": 260, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 21 - }, - "outputTokens": 21, - "raw": { - "input_tokens": 260, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 21, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "totalTokens": 281 - }, - "warnings": [] - }, - { - "callId": "", - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } + ├── ai-sdk-agent-tool-loop-operation + │ metadata: { + │ "operation": "agent-tool-loop", + │ "testRunId": "" + │ } + │ └── generateText [function] + │ input: { + │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ "maxOutputTokens": 256, + │ "maxRetries": 2, + │ "messages": [ + │ { + │ "content": "I need help comparing laptop prices before checkout.", + │ "role": "user" + │ }, + │ { + │ "content": "I can compare store prices and apply a discount code.", + │ "role": "assistant" + │ }, + │ { + │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "role": "user" + │ } + │ ], + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "temperature": 0, + │ "tools": { + │ "apply_discount": { + │ "description": "Apply a discount code to a total", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "discountCode": { + │ "description": "The discount code to apply", + │ "type": "string" + │ }, + │ "total": { + │ "description": "The original total", + │ "type": "number" + │ } + │ }, + │ "required": [ + │ "discountCode", + │ "total" + │ ], + │ "type": "object" + │ } + │ }, + │ "get_store_price": { + │ "description": "Get the price of an item at a store", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "item": { + │ "description": "The item to price", + │ "type": "string" + │ }, + │ "store": { + │ "description": "The store name", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "item", + │ "store" + │ ], + │ "type": "object" + │ } + │ } + │ } + │ } + │ output: { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ }, + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "responseMessages": "", + │ "steps": [ + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 0, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 173 + │ }, + │ "inputTokens": 173, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 59 + │ }, + │ "outputTokens": 59, + │ "raw": { + │ "input_tokens": 173, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 59, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 232 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 1, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 260 + │ }, + │ "inputTokens": 260, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 21 + │ }, + │ "outputTokens": 21, + │ "raw": { + │ "input_tokens": 260, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 21, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 281 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 2, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 308 + │ }, + │ "inputTokens": 308, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 62 + │ }, + │ "outputTokens": 62, + │ "raw": { + │ "input_tokens": 308, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 62, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 370 + │ }, + │ "warnings": [] + │ } + │ ], + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "toolCalls": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [ + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "totalUsage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 741 + │ }, + │ "inputTokens": 741, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 142 + │ }, + │ "outputTokens": 142, + │ "totalTokens": 883 + │ }, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 741 + │ }, + │ "inputTokens": 741, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 142 + │ }, + │ "outputTokens": 142, + │ "totalTokens": 883 + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ │ "maxOutputTokens": 256, + │ │ "messages": [ + │ │ { + │ │ "content": "I need help comparing laptop prices before checkout.", + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": "I can compare store prices and apply a discount code.", + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ │ "role": "user" + │ │ } + │ │ ], + │ │ "model": { + │ │ "modelId": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ }, + │ │ "temperature": 0, + │ │ "tools": [ + │ │ { + │ │ "description": "Get the price of an item at a store", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "item": { + │ │ "description": "The item to price", + │ │ "type": "string" + │ │ }, + │ │ "store": { + │ │ "description": "The store name", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "item", + │ │ "store" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_store_price", + │ │ "type": "function" + │ │ }, + │ │ { + │ │ "description": "Apply a discount code to a total", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "discountCode": { + │ │ "description": "The discount code to apply", + │ │ "type": "string" + │ │ }, + │ │ "total": { + │ │ "description": "The original total", + │ │ "type": "number" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "discountCode", + │ │ "total" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "apply_discount", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreA" + │ │ }, + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ }, + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreB" + │ │ }, + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 173 + │ │ }, + │ │ "inputTokens": 173, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 59 + │ │ }, + │ │ "outputTokens": 59, + │ │ "raw": { + │ │ "input_tokens": 173, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 59, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 232 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 59, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 173, + │ │ "tokens": 232 + │ │ } + │ ├── get_store_price [tool] + │ │ input: { + │ │ "item": "laptop", + │ │ "store": "StoreA" + │ │ } + │ │ output: "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_store_price" + │ │ } + │ ├── get_store_price [tool] + │ │ input: { + │ │ "item": "laptop", + │ │ "store": "StoreB" + │ │ } + │ │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_store_price" + │ │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ │ "maxOutputTokens": 256, + │ │ "messages": [ + │ │ { + │ │ "content": "I need help comparing laptop prices before checkout.", + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": "I can compare store prices and apply a discount code.", + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreA" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ }, + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreB" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "text", + │ │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-result" + │ │ }, + │ │ { + │ │ "output": { + │ │ "type": "text", + │ │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ], + │ │ "model": { + │ │ "modelId": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ }, + │ │ "temperature": 0, + │ │ "tools": [ + │ │ { + │ │ "description": "Get the price of an item at a store", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "item": { + │ │ "description": "The item to price", + │ │ "type": "string" + │ │ }, + │ │ "store": { + │ │ "description": "The store name", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "item", + │ │ "store" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_store_price", + │ │ "type": "function" + │ │ }, + │ │ { + │ │ "description": "Apply a discount code to a total", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "discountCode": { + │ │ "description": "The discount code to apply", + │ │ "type": "string" + │ │ }, + │ │ "total": { + │ │ "description": "The original total", + │ │ "type": "number" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "discountCode", + │ │ "total" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "apply_discount", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "discountCode": "SAVE20", + │ │ "total": 999 + │ │ }, + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "apply_discount", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 260 + │ │ }, + │ │ "inputTokens": 260, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 21 + │ │ }, + │ │ "outputTokens": 21, + │ │ "raw": { + │ │ "input_tokens": 260, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 21, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 281 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 21, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 260, + │ │ "tokens": 281 + │ │ } + │ ├── apply_discount [tool] + │ │ input: { + │ │ "discountCode": "SAVE20", + │ │ "total": 999 + │ │ } + │ │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "apply_discount" + │ │ } + │ └── doGenerate [llm] + │ input: { + │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ "maxOutputTokens": 256, + │ "messages": [ + │ { + │ "content": "I need help comparing laptop prices before checkout.", + │ "role": "user" + │ }, + │ { + │ "content": "I can compare store prices and apply a discount code.", + │ "role": "assistant" + │ }, + │ { + │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "temperature": 0, + │ "tools": [ + │ { + │ "description": "Get the price of an item at a store", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "item": { + │ "description": "The item to price", + │ "type": "string" + │ }, + │ "store": { + │ "description": "The store name", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "item", + │ "store" + │ ], + │ "type": "object" + │ }, + │ "name": "get_store_price", + │ "type": "function" + │ }, + │ { + │ "description": "Apply a discount code to a total", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "discountCode": { + │ "description": "The discount code to apply", + │ "type": "string" + │ }, + │ "total": { + │ "description": "The original total", + │ "type": "number" + │ } + │ }, + │ "required": [ + │ "discountCode", + │ "total" + │ ], + │ "type": "object" + │ }, + │ "name": "apply_discount", + │ "type": "function" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "response": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 308 + │ }, + │ "inputTokens": 308, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 62 + │ }, + │ "outputTokens": 62, + │ "raw": { + │ "input_tokens": 308, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 62, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 370 + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_tokens": 62, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 308, + │ "tokens": 370 + │ } + ├── ai-sdk-workflow-agent-stream-operation + │ metadata: { + │ "operation": "workflow-agent-stream", + │ "testRunId": "" + │ } + │ └── WorkflowAgent.stream [function] + │ input: { + │ "messages": [ + │ { + │ "content": "Use get_weather for Paris, France, then reply with one short sentence.", + │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "steps": [ + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 0, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 84 + │ }, + │ "inputTokens": 84, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 84, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 92 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 1, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 123 + │ }, + │ "inputTokens": 123, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 123, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 131 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 2, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 162 + │ }, + │ "inputTokens": 162, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 162, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 170 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 3, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 201 + │ }, + │ "inputTokens": 201, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 201, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 209 + │ }, + │ "warnings": [] + │ } + │ ], + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [], + │ "totalUsage": { + │ "inputTokens": 570, + │ "outputTokens": 32, + │ "totalTokens": 602 + │ }, + │ "usage": { + │ "inputTokens": 570, + │ "outputTokens": 32, + │ "totalTokens": 602 + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "options": { + │ "maxOutputTokens": 96, + │ "maxRetries": 2, + │ "temperature": 0, + │ "toolChoice": "required" + │ }, + │ "provider": "openai.responses", + │ "tools": { + │ "get_weather": { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ } + │ } + │ } + │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 84 + │ │ }, + │ │ "inputTokens": 84, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 8 + │ │ }, + │ │ "outputTokens": 8, + │ │ "raw": { + │ │ "input_tokens": 84, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 92 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0 + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ } + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 84, + │ │ "tokens": 92 + │ │ } + │ ├── get_weather [tool] + │ │ input: { + │ │ "location": "Paris, France" + │ │ } + │ │ output: { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_weather" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 123 + │ │ }, + │ │ "inputTokens": 123, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 8 + │ │ }, + │ │ "outputTokens": 8, + │ │ "raw": { + │ │ "input_tokens": 123, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 131 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0 + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ } + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 123, + │ │ "tokens": 131 + │ │ } + │ ├── get_weather [tool] + │ │ input: { + │ │ "location": "Paris, France" + │ │ } + │ │ output: { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_weather" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 162 + │ │ }, + │ │ "inputTokens": 162, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 8 + │ │ }, + │ │ "outputTokens": 8, + │ │ "raw": { + │ │ "input_tokens": 162, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 170 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0 + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ } + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 162, + │ │ "tokens": 170 + │ │ } + │ ├── get_weather [tool] + │ │ input: { + │ │ "location": "Paris, France" + │ │ } + │ │ output: { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_weather" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 201 + │ │ }, + │ │ "inputTokens": 201, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 8 + │ │ }, + │ │ "outputTokens": 8, + │ │ "raw": { + │ │ "input_tokens": 201, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 209 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0 + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ } + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 201, + │ │ "tokens": 209 + │ │ } + │ └── get_weather [tool] + │ input: { + │ "location": "Paris, France" + │ } + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "toolName": "get_weather" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + └── ai-sdk-workflow-agent-stream-prompt-operation + metadata: { + "operation": "workflow-agent-stream-prompt", + "testRunId": "" + } + └── WorkflowAgent.stream [function] + input: { + "messages": [ + { + "content": "What's the weather in Paris?", + "role": "user" + } + ] + } + output: { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "steps": [ + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 0, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 70 + }, + "inputTokens": 70, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 70, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 78 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 1, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 109 + }, + "inputTokens": 109, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 109, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 117 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "stepNumber": 2, + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 148 + }, + "inputTokens": 148, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 148, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 156 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "request": { + "messages": [] }, "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "role": "assistant" - } - ], + "messages": [], "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, "runtimeContext": {}, - "stepNumber": 2, + "stepNumber": 3, "toolsContext": {}, "usage": { "inputTokenDetails": { "cacheReadTokens": 0, - "noCacheTokens": 308 + "noCacheTokens": 187 }, - "inputTokens": 308, + "inputTokens": 187, "outputTokenDetails": { "reasoningTokens": 0, - "textTokens": 62 + "textTokens": 8 }, - "outputTokens": 62, + "outputTokens": 8, "raw": { - "input_tokens": 308, + "input_tokens": 187, "input_tokens_details": { "cached_tokens": 0 }, - "output_tokens": 62, + "output_tokens": 8, "output_tokens_details": { "reasoning_tokens": 0 } }, - "totalTokens": 370 + "totalTokens": 195 }, "warnings": [] } ], - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + "text": "", "toolCalls": [ { "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } + "location": "Paris, France" }, - "toolName": "apply_discount", + "toolName": "get_weather", "type": "tool-call" } ], - "toolResults": [ - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], + "toolResults": [], "totalUsage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 741 - }, - "inputTokens": 741, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 142 - }, - "outputTokens": 142, - "totalTokens": 883 + "inputTokens": 514, + "outputTokens": 32, + "totalTokens": 546 }, "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 741 - }, - "inputTokens": 741, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 142 - }, - "outputTokens": 142, - "totalTokens": 883 + "inputTokens": 514, + "outputTokens": 32, + "totalTokens": 546 }, "warnings": [] } @@ -3762,78 +5574,355 @@ span_tree: "sdk_language": "typescript" }, "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" + "options": { + "maxOutputTokens": 96, + "maxRetries": 2, + "temperature": 0, + "toolChoice": "required" + }, + "provider": "openai.responses", + "tools": { + "get_weather": { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + } } ├── doGenerate [llm] │ input: { - │ "maxOutputTokens": 256, │ "messages": [ │ { - │ "content": "I need help comparing laptop prices before checkout.", + │ "content": "You are a helpful weather assistant.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "response": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 70 + │ }, + │ "inputTokens": 70, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 70, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 78 + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "options": { + │ "maxOutputTokens": 96, + │ "temperature": 0 + │ }, + │ "provider": "openai.responses", + │ "tools": [ + │ { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ } + │ } + │ ] + │ } + │ metrics: { + │ "completion_tokens": 8, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 70, + │ "tokens": 78 + │ } + ├── get_weather [tool] + │ input: { + │ "location": "Paris, France" + │ } + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "toolName": "get_weather" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + ├── doGenerate [llm] + │ input: { + │ "messages": [ + │ { + │ "content": "You are a helpful weather assistant.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "response": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 109 + │ }, + │ "inputTokens": 109, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 109, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 117 + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "options": { + │ "maxOutputTokens": 96, + │ "temperature": 0 + │ }, + │ "provider": "openai.responses", + │ "tools": [ + │ { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ } + │ } + │ ] + │ } + │ metrics: { + │ "completion_tokens": 8, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 109, + │ "tokens": 117 + │ } + ├── get_weather [tool] + │ input: { + │ "location": "Paris, France" + │ } + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "toolName": "get_weather" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + ├── doGenerate [llm] + │ input: { + │ "messages": [ + │ { + │ "content": "You are a helpful weather assistant.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], │ "role": "user" │ }, │ { - │ "content": "I can compare store prices and apply a discount code.", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], │ "role": "assistant" │ }, │ { - │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - │ "role": "user" - │ } - │ ], - │ "model": { - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" - │ }, - │ "temperature": 0, - │ "tools": [ + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, │ { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ }, - │ "name": "get_store_price", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" │ }, │ { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ }, - │ "name": "apply_discount", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" │ } │ ] │ } @@ -3841,28 +5930,9 @@ span_tree: │ "content": [ │ { │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } + │ "location": "Paris, France" │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-call" │ } │ ], @@ -3871,25 +5941,25 @@ span_tree: │ "usage": { │ "inputTokenDetails": { │ "cacheReadTokens": 0, - │ "noCacheTokens": 173 + │ "noCacheTokens": 148 │ }, - │ "inputTokens": 173, + │ "inputTokens": 148, │ "outputTokenDetails": { │ "reasoningTokens": 0, - │ "textTokens": 59 + │ "textTokens": 8 │ }, - │ "outputTokens": 59, + │ "outputTokens": 8, │ "raw": { - │ "input_tokens": 173, + │ "input_tokens": 148, │ "input_tokens_details": { │ "cached_tokens": 0 │ }, - │ "output_tokens": 59, + │ "output_tokens": 8, │ "output_tokens_details": { │ "reasoning_tokens": 0 │ } │ }, - │ "totalTokens": 232 + │ "totalTokens": 156 │ } │ } │ metadata: { @@ -3898,82 +5968,79 @@ span_tree: │ "sdk_language": "typescript" │ }, │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" + │ "options": { + │ "maxOutputTokens": 96, + │ "temperature": 0 + │ }, + │ "provider": "openai.responses", + │ "tools": [ + │ { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ } + │ } + │ ] │ } │ metrics: { - │ "completion_tokens": 59, + │ "completion_tokens": 8, │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 173, - │ "tokens": 232 + │ "prompt_tokens": 148, + │ "tokens": 156 │ } - ├── get_store_price [tool] + ├── get_weather [tool] │ input: { - │ "item": "laptop", - │ "store": "StoreA" + │ "location": "Paris, France" │ } - │ output: "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "toolName": "get_store_price" - │ } - ├── get_store_price [tool] - │ input: { - │ "item": "laptop", - │ "store": "StoreB" + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 │ } - │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" │ metadata: { │ "braintrust": { │ "integration_name": "ai-sdk", │ "sdk_language": "typescript" │ }, - │ "toolName": "get_store_price" + │ "toolName": "get_weather" + │ } + │ metrics: { + │ "duration_ms": 0 │ } ├── doGenerate [llm] │ input: { - │ "maxOutputTokens": 256, │ "messages": [ │ { - │ "content": "I need help comparing laptop prices before checkout.", - │ "role": "user" - │ }, - │ { - │ "content": "I can compare store prices and apply a discount code.", - │ "role": "assistant" + │ "content": "You are a helpful weather assistant.", + │ "role": "system" │ }, │ { - │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], │ "role": "user" │ }, │ { │ "content": [ │ { │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } + │ "location": "Paris, France" │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-call" │ } │ ], @@ -3983,87 +6050,76 @@ span_tree: │ "content": [ │ { │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 │ } │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-result" - │ }, + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ "input": { + │ "location": "Paris, France" │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 │ } │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-result" │ } │ ], │ "role": "tool" - │ } - │ ], - │ "model": { - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" - │ }, - │ "temperature": 0, - │ "tools": [ + │ }, │ { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ }, - │ "name": "get_store_price", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" │ }, │ { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ }, - │ "name": "apply_discount", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" │ } │ ] │ } @@ -4071,15 +6127,9 @@ span_tree: │ "content": [ │ { │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } + │ "location": "Paris, France" │ }, - │ "toolName": "apply_discount", + │ "toolName": "get_weather", │ "type": "tool-call" │ } │ ], @@ -4088,25 +6138,25 @@ span_tree: │ "usage": { │ "inputTokenDetails": { │ "cacheReadTokens": 0, - │ "noCacheTokens": 260 + │ "noCacheTokens": 187 │ }, - │ "inputTokens": 260, + │ "inputTokens": 187, │ "outputTokenDetails": { │ "reasoningTokens": 0, - │ "textTokens": 21 + │ "textTokens": 8 │ }, - │ "outputTokens": 21, + │ "outputTokens": 8, │ "raw": { - │ "input_tokens": 260, + │ "input_tokens": 187, │ "input_tokens_details": { │ "cached_tokens": 0 │ }, - │ "output_tokens": 21, + │ "output_tokens": 8, │ "output_tokens_details": { │ "reasoning_tokens": 0 │ } │ }, - │ "totalTokens": 281 + │ "totalTokens": 195 │ } │ } │ metadata: { @@ -4115,247 +6165,53 @@ span_tree: │ "sdk_language": "typescript" │ }, │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" + │ "options": { + │ "maxOutputTokens": 96, + │ "temperature": 0 + │ }, + │ "provider": "openai.responses", + │ "tools": [ + │ { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ } + │ } + │ ] │ } │ metrics: { - │ "completion_tokens": 21, + │ "completion_tokens": 8, │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 260, - │ "tokens": 281 - │ } - ├── apply_discount [tool] - │ input: { - │ "discountCode": "SAVE20", - │ "total": 999 - │ } - │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "toolName": "apply_discount" + │ "prompt_tokens": 187, + │ "tokens": 195 │ } - └── doGenerate [llm] + └── get_weather [tool] input: { - "maxOutputTokens": 256, - "messages": [ - { - "content": "I need help comparing laptop prices before checkout.", - "role": "user" - }, - { - "content": "I can compare store prices and apply a discount code.", - "role": "assistant" - }, - { - "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "role": "user" - }, - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "temperature": 0, - "tools": [ - { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } - }, - "required": [ - "item", - "store" - ], - "type": "object" - }, - "name": "get_store_price", - "type": "function" - }, - { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" - }, - "total": { - "description": "The original total", - "type": "number" - } - }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - }, - "name": "apply_discount", - "type": "function" - } - ] + "location": "Paris, France" } output: { - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", - "response": {}, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 308 - }, - "inputTokens": 308, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 62 - }, - "outputTokens": 62, - "raw": { - "input_tokens": 308, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 62, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "totalTokens": 370 - } + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 } metadata: { "braintrust": { "integration_name": "ai-sdk", "sdk_language": "typescript" }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" + "toolName": "get_weather" } metrics: { - "completion_tokens": 62, - "prompt_cached_tokens": 0, - "prompt_tokens": 308, - "tokens": 370 + "duration_ms": 0 } diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.json b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.json index d154db703..e126e3ed5 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.json +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.json @@ -84,9 +84,6 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, "maxOutputTokens": 24, "maxRetries": 2, "messages": [ @@ -121,7 +118,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -168,7 +164,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -351,9 +346,6 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, "maxOutputTokens": 32, "maxRetries": 2, "messages": [ @@ -406,7 +398,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -453,7 +444,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -662,7 +652,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -709,7 +698,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -956,6 +944,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1067,6 +1056,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1213,6 +1203,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1394,6 +1385,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "messages": [ { @@ -1607,9 +1599,7 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, + "instructions": "You must inspect live weather via the provided get_weather tool before responding.", "maxOutputTokens": 128, "maxRetries": 2, "messages": [ @@ -1759,7 +1749,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -1844,7 +1833,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -1955,7 +1943,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2066,7 +2053,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2177,7 +2163,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2433,7 +2418,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2480,9 +2464,6 @@ } ], "input": { - "headers": { - "user-agent": "ai/7.0.0" - }, "maxOutputTokens": 32, "maxRetries": 2, "model": { @@ -2519,7 +2500,6 @@ }, "response": { "body": "", - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2596,7 +2576,6 @@ } }, "response": { - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2678,7 +2657,6 @@ } }, "response": { - "headers": "", "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, @@ -2734,6 +2712,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "messages": [ { @@ -2801,9 +2780,7 @@ } ], "input": { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - }, + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "maxRetries": 2, "messages": [ @@ -2837,7 +2814,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2884,7 +2860,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -2991,6 +2966,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "messages": [ { @@ -3058,9 +3034,7 @@ } ], "input": { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop" - }, + "instructions": "You are a terse assistant.", "maxOutputTokens": 24, "maxRetries": 2, "messages": [ @@ -3094,7 +3068,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -3141,7 +3114,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -3251,6 +3223,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "messages": [ { @@ -3431,6 +3404,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "messages": [ { @@ -3643,6 +3617,7 @@ "type": "llm", "children": [], "input": { + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "messages": [ { @@ -3867,9 +3842,7 @@ } ], "input": { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - }, + "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", "maxOutputTokens": 256, "maxRetries": 2, "messages": [ @@ -4042,7 +4015,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4136,7 +4108,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4276,7 +4247,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4371,7 +4341,6 @@ } }, "response": { - "headers": "", "messages": [ { "content": [ @@ -4551,12 +4520,2377 @@ "operation": "agent-tool-loop", "testRunId": "" } + }, + { + "name": "ai-sdk-workflow-agent-stream-operation", + "children": [ + { + "name": "WorkflowAgent.stream", + "type": "function", + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 84, + "total": 84 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 84, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 84, + "reasoning_tokens": 0, + "tokens": 92 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 123, + "total": 123 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 123, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 123, + "reasoning_tokens": 0, + "tokens": 131 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 162, + "total": 162 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 162, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 162, + "reasoning_tokens": 0, + "tokens": 170 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 201, + "total": 201 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 201, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 201, + "reasoning_tokens": 0, + "tokens": 209 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + } + ], + "input": { + "messages": [ + { + "content": "Use get_weather for Paris, France, then reply with one short sentence.", + "role": "user" + } + ] + }, + "output": { + "messages": [ + { + "content": "You are a terse weather assistant. Use tools before answering.", + "role": "system" + }, + { + "content": [ + { + "text": "Use get_weather for Paris, France, then reply with one short sentence.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "steps": [ + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 0, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 84 + }, + "inputTokens": 84, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 84, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 92 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 1, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 123 + }, + "inputTokens": 123, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 123, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 131 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 2, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 162 + }, + "inputTokens": 162, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 162, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 170 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 3, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 201 + }, + "inputTokens": 201, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 201, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 209 + }, + "warnings": [] + } + ], + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [ + { + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "toolName": "get_weather", + "type": "tool-result" + } + ] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "stopWhen": "[Function]", + "temperature": 0, + "toolChoice": "required" + }, + "provider": "openai.responses", + "tools": { + "get_weather": { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + } + } + } + ], + "metadata": { + "operation": "workflow-agent-stream", + "testRunId": "" + } + }, + { + "name": "ai-sdk-workflow-agent-stream-prompt-operation", + "children": [ + { + "name": "WorkflowAgent.stream", + "type": "function", + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 70, + "total": 70 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 70, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 70, + "reasoning_tokens": 0, + "tokens": 78 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 109, + "total": 109 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 109, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 109, + "reasoning_tokens": 0, + "tokens": 117 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 148, + "total": 148 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 148, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 148, + "reasoning_tokens": 0, + "tokens": 156 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "input": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ] + }, + "output": { + "finishReason": { + "unified": "tool-calls" + }, + "text": "", + "toolCalls": [ + { + "input": "{\"location\":\"Paris, France\"}", + "providerMetadata": { + "openai": { + "itemId": "" + } + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "usage": { + "inputTokens": { + "cacheRead": 0, + "noCache": 187, + "total": 187 + }, + "outputTokens": { + "reasoning": 0, + "text": 8, + "total": 8 + }, + "raw": { + "input_tokens": 187, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + } + } + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "finish_reason": { + "unified": "tool-calls" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "includeRawChunks": false, + "maxOutputTokens": 96, + "temperature": 0, + "toolChoice": { + "type": "required" + } + }, + "provider": "openai.responses", + "tools": [ + { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + }, + "name": "get_weather", + "type": "function" + } + ] + }, + "metrics": { + "completion_reasoning_tokens": 0, + "completion_tokens": 8, + "prompt_cached_tokens": 0, + "prompt_tokens": 187, + "reasoning_tokens": 0, + "tokens": 195 + } + }, + { + "name": "get_weather", + "type": "tool", + "children": [], + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + } + ], + "input": { + "prompt": "What's the weather in Paris?", + "system": "You are a helpful weather assistant." + }, + "output": { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "steps": [ + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 0, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 70 + }, + "inputTokens": 70, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 70, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 78 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 1, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 109 + }, + "inputTokens": 109, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 109, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 117 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 2, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 148 + }, + "inputTokens": 148, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 148, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 156 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 3, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 187 + }, + "inputTokens": 187, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 187, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 195 + }, + "warnings": [] + } + ], + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [ + { + "input": { + "location": "Paris, France" + }, + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + }, + "toolName": "get_weather", + "type": "tool-result" + } + ] + }, + "metadata": { + "braintrust": { + "integration_name": "ai-sdk", + "sdk_language": "typescript" + }, + "model": "gpt-4o-mini-2024-07-18", + "options": { + "maxOutputTokens": 96, + "stopWhen": "[Function]", + "temperature": 0, + "toolChoice": "required" + }, + "provider": "openai.responses", + "tools": { + "get_weather": { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + } + } + } + ], + "metadata": { + "operation": "workflow-agent-stream-prompt", + "testRunId": "" + } } ], "metadata": { "aiSdkVersion": "7.0.0", "scenario": "ai-sdk-instrumentation", - "testRunId": "" + "testRunId": "", + "workflowVersion": "1.0.8" } } ] diff --git a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.txt b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.txt index 7e3892a80..656496e68 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.txt +++ b/e2e/scenarios/ai-sdk-instrumentation/__snapshots__/ai-sdk-v7-explicit.span-tree.txt @@ -3,7 +3,8 @@ span_tree: metadata: { "aiSdkVersion": "7.0.0", "scenario": "ai-sdk-instrumentation", - "testRunId": "" + "testRunId": "", + "workflowVersion": "1.0.8" } ├── ai-sdk-generate-operation │ metadata: { @@ -12,9 +13,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, │ "maxOutputTokens": 24, │ "maxRetries": 2, │ "messages": [ @@ -49,7 +47,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -96,7 +93,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -263,9 +259,6 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, │ "maxOutputTokens": 32, │ "maxRetries": 2, │ "messages": [ @@ -318,7 +311,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -365,7 +357,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -561,7 +552,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -608,7 +598,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -884,9 +873,7 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, + │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ "maxOutputTokens": 128, │ "maxRetries": 2, │ "messages": [ @@ -1036,7 +1023,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1121,7 +1107,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1232,7 +1217,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1343,7 +1327,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1454,7 +1437,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -1671,6 +1653,7 @@ span_tree: │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -1774,6 +1757,7 @@ span_tree: │ │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -1912,6 +1896,7 @@ span_tree: │ │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -2085,6 +2070,7 @@ span_tree: │ │ } │ ├── doGenerate [llm] │ │ input: { + │ │ "instructions": "You must inspect live weather via the provided get_weather tool before responding.", │ │ "maxOutputTokens": 128, │ │ "messages": [ │ │ { @@ -2298,9 +2284,6 @@ span_tree: │ } │ └── generateObject [function] │ input: { - │ "headers": { - │ "user-agent": "ai/7.0.0" - │ }, │ "maxOutputTokens": 32, │ "maxRetries": 2, │ "model": { @@ -2337,7 +2320,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2398,7 +2380,6 @@ span_tree: │ }, │ "response": { │ "body": "", - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2484,7 +2465,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2544,7 +2524,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "modelId": "gpt-4o-mini-2024-07-18", │ "timestamp": "" │ }, @@ -2595,9 +2574,7 @@ span_tree: │ } │ └── generateText [function] │ input: { - │ "headers": { - │ "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - │ }, + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "maxRetries": 2, │ "messages": [ @@ -2631,7 +2608,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2678,7 +2654,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2768,6 +2743,7 @@ span_tree: │ } │ └── doGenerate [llm] │ input: { + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "messages": [ │ { @@ -2839,9 +2815,7 @@ span_tree: │ } │ └── streamText [function] │ input: { - │ "headers": { - │ "user-agent": "ai-sdk-agent/tool-loop" - │ }, + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "maxRetries": 2, │ "messages": [ @@ -2875,7 +2849,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -2922,7 +2895,6 @@ span_tree: │ } │ }, │ "response": { - │ "headers": "", │ "messages": [ │ { │ "content": [ @@ -3015,6 +2987,7 @@ span_tree: │ } │ └── doStream [llm] │ input: { + │ "instructions": "You are a terse assistant.", │ "maxOutputTokens": 24, │ "messages": [ │ { @@ -3079,682 +3052,2897 @@ span_tree: │ "prompt_tokens": 27, │ "tokens": 31 │ } - └── ai-sdk-agent-tool-loop-operation - metadata: { - "operation": "agent-tool-loop", - "testRunId": "" - } - └── generateText [function] - input: { - "headers": { - "user-agent": "ai-sdk-agent/tool-loop ai/7.0.0" - }, - "maxOutputTokens": 256, - "maxRetries": 2, - "messages": [ - { - "content": "I need help comparing laptop prices before checkout.", - "role": "user" - }, - { - "content": "I can compare store prices and apply a discount code.", - "role": "assistant" - }, - { - "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "role": "user" - } - ], - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "temperature": 0, - "tools": { - "apply_discount": { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" - }, - "total": { - "description": "The original total", - "type": "number" - } - }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - } - }, - "get_store_price": { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } - }, - "required": [ - "item", - "store" - ], - "type": "object" - } - } - } - } - output: { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - }, - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "role": "assistant" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "responseMessages": "", - "steps": [ - { - "callId": "", - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "finishReason": "tool-calls", - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "runtimeContext": {}, - "stepNumber": 0, - "toolsContext": {}, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 173 - }, - "inputTokens": 173, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 59 - }, - "outputTokens": 59, - "raw": { - "input_tokens": 173, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 59, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "totalTokens": 232 - }, - "warnings": [] - }, - { - "callId": "", - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - }, - { - "dynamic": false, - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "finishReason": "tool-calls", - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "providerMetadata": { - "openai": { - "responseId": "", - "serviceTier": "default" - } - }, - "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "modelId": "gpt-4o-mini-2024-07-18", - "timestamp": "" - }, - "runtimeContext": {}, - "stepNumber": 1, - "toolsContext": {}, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 260 - }, - "inputTokens": 260, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 21 - }, - "outputTokens": 21, - "raw": { - "input_tokens": 260, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 21, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "totalTokens": 281 - }, - "warnings": [] - }, - { - "callId": "", - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", + ├── ai-sdk-agent-tool-loop-operation + │ metadata: { + │ "operation": "agent-tool-loop", + │ "testRunId": "" + │ } + │ └── generateText [function] + │ input: { + │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ "maxOutputTokens": 256, + │ "maxRetries": 2, + │ "messages": [ + │ { + │ "content": "I need help comparing laptop prices before checkout.", + │ "role": "user" + │ }, + │ { + │ "content": "I can compare store prices and apply a discount code.", + │ "role": "assistant" + │ }, + │ { + │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "role": "user" + │ } + │ ], + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "temperature": 0, + │ "tools": { + │ "apply_discount": { + │ "description": "Apply a discount code to a total", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "discountCode": { + │ "description": "The discount code to apply", + │ "type": "string" + │ }, + │ "total": { + │ "description": "The original total", + │ "type": "number" + │ } + │ }, + │ "required": [ + │ "discountCode", + │ "total" + │ ], + │ "type": "object" + │ } + │ }, + │ "get_store_price": { + │ "description": "Get the price of an item at a store", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "item": { + │ "description": "The item to price", + │ "type": "string" + │ }, + │ "store": { + │ "description": "The store name", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "item", + │ "store" + │ ], + │ "type": "object" + │ } + │ } + │ } + │ } + │ output: { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ }, + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "responseMessages": "", + │ "steps": [ + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 0, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 173 + │ }, + │ "inputTokens": 173, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 59 + │ }, + │ "outputTokens": 59, + │ "raw": { + │ "input_tokens": 173, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 59, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 232 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 1, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 260 + │ }, + │ "inputTokens": 260, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 21 + │ }, + │ "outputTokens": 21, + │ "raw": { + │ "input_tokens": 260, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 21, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 281 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "response": { + │ "messages": [ + │ { + │ "content": [ + │ { + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ ], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "stepNumber": 2, + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 308 + │ }, + │ "inputTokens": 308, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 62 + │ }, + │ "outputTokens": 62, + │ "raw": { + │ "input_tokens": 308, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 62, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 370 + │ }, + │ "warnings": [] + │ } + │ ], + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "toolCalls": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [ + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "dynamic": false, + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "totalUsage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 741 + │ }, + │ "inputTokens": 741, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 142 + │ }, + │ "outputTokens": 142, + │ "totalTokens": 883 + │ }, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 741 + │ }, + │ "inputTokens": 741, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 142 + │ }, + │ "outputTokens": 142, + │ "totalTokens": 883 + │ }, + │ "warnings": [] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ │ "maxOutputTokens": 256, + │ │ "messages": [ + │ │ { + │ │ "content": "I need help comparing laptop prices before checkout.", + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": "I can compare store prices and apply a discount code.", + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ │ "role": "user" + │ │ } + │ │ ], + │ │ "model": { + │ │ "modelId": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ }, + │ │ "temperature": 0, + │ │ "tools": [ + │ │ { + │ │ "description": "Get the price of an item at a store", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "item": { + │ │ "description": "The item to price", + │ │ "type": "string" + │ │ }, + │ │ "store": { + │ │ "description": "The store name", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "item", + │ │ "store" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_store_price", + │ │ "type": "function" + │ │ }, + │ │ { + │ │ "description": "Apply a discount code to a total", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "discountCode": { + │ │ "description": "The discount code to apply", + │ │ "type": "string" + │ │ }, + │ │ "total": { + │ │ "description": "The original total", + │ │ "type": "number" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "discountCode", + │ │ "total" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "apply_discount", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreA" + │ │ }, + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ }, + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreB" + │ │ }, + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 173 + │ │ }, + │ │ "inputTokens": 173, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 59 + │ │ }, + │ │ "outputTokens": 59, + │ │ "raw": { + │ │ "input_tokens": 173, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 59, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 232 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 59, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 173, + │ │ "tokens": 232 + │ │ } + │ ├── get_store_price [tool] + │ │ input: { + │ │ "item": "laptop", + │ │ "store": "StoreA" + │ │ } + │ │ output: "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_store_price" + │ │ } + │ ├── get_store_price [tool] + │ │ input: { + │ │ "item": "laptop", + │ │ "store": "StoreB" + │ │ } + │ │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "get_store_price" + │ │ } + │ ├── doGenerate [llm] + │ │ input: { + │ │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ │ "maxOutputTokens": 256, + │ │ "messages": [ + │ │ { + │ │ "content": "I need help comparing laptop prices before checkout.", + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": "I can compare store prices and apply a discount code.", + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreA" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ }, + │ │ { + │ │ "input": { + │ │ "item": "laptop", + │ │ "store": "StoreB" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "text", + │ │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-result" + │ │ }, + │ │ { + │ │ "output": { + │ │ "type": "text", + │ │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ │ }, + │ │ "providerOptions": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_store_price", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ], + │ │ "model": { + │ │ "modelId": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ }, + │ │ "temperature": 0, + │ │ "tools": [ + │ │ { + │ │ "description": "Get the price of an item at a store", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "item": { + │ │ "description": "The item to price", + │ │ "type": "string" + │ │ }, + │ │ "store": { + │ │ "description": "The store name", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "item", + │ │ "store" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_store_price", + │ │ "type": "function" + │ │ }, + │ │ { + │ │ "description": "Apply a discount code to a total", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "discountCode": { + │ │ "description": "The discount code to apply", + │ │ "type": "string" + │ │ }, + │ │ "total": { + │ │ "description": "The original total", + │ │ "type": "number" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "discountCode", + │ │ "total" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "apply_discount", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "discountCode": "SAVE20", + │ │ "total": 999 + │ │ }, + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "apply_discount", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "finishReason": "tool-calls", + │ │ "response": {}, + │ │ "usage": { + │ │ "inputTokenDetails": { + │ │ "cacheReadTokens": 0, + │ │ "noCacheTokens": 260 + │ │ }, + │ │ "inputTokens": 260, + │ │ "outputTokenDetails": { + │ │ "reasoningTokens": 0, + │ │ "textTokens": 21 + │ │ }, + │ │ "outputTokens": 21, + │ │ "raw": { + │ │ "input_tokens": 260, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 21, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ }, + │ │ "totalTokens": 281 + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "provider": "openai.responses" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 21, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 260, + │ │ "tokens": 281 + │ │ } + │ ├── apply_discount [tool] + │ │ input: { + │ │ "discountCode": "SAVE20", + │ │ "total": 999 + │ │ } + │ │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "toolName": "apply_discount" + │ │ } + │ └── doGenerate [llm] + │ input: { + │ "instructions": "You are a shopping assistant. Use the tools before answering pricing questions.", + │ "maxOutputTokens": 256, + │ "messages": [ + │ { + │ "content": "I need help comparing laptop prices before checkout.", + │ "role": "user" + │ }, + │ { + │ "content": "I can compare store prices and apply a discount code.", + │ "role": "assistant" + │ }, + │ { + │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreA" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ }, + │ { + │ "input": { + │ "item": "laptop", + │ "store": "StoreB" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ }, + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_store_price", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "discountCode": "SAVE20", + │ "total": 999 + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "text", + │ "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" + │ }, + │ "providerOptions": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "apply_discount", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ }, + │ "temperature": 0, + │ "tools": [ + │ { + │ "description": "Get the price of an item at a store", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "item": { + │ "description": "The item to price", + │ "type": "string" + │ }, + │ "store": { + │ "description": "The store name", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "item", + │ "store" + │ ], + │ "type": "object" + │ }, + │ "name": "get_store_price", + │ "type": "function" + │ }, + │ { + │ "description": "Apply a discount code to a total", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "discountCode": { + │ "description": "The discount code to apply", + │ "type": "string" + │ }, + │ "total": { + │ "description": "The original total", + │ "type": "number" + │ } + │ }, + │ "required": [ + │ "discountCode", + │ "total" + │ ], + │ "type": "object" + │ }, + │ "name": "apply_discount", + │ "type": "function" + │ } + │ ] + │ } + │ output: { + │ "content": [ + │ { + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", + │ "type": "text" + │ } + │ ], + │ "finishReason": "stop", + │ "response": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 308 + │ }, + │ "inputTokens": 308, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 62 + │ }, + │ "outputTokens": 62, + │ "raw": { + │ "input_tokens": 308, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 62, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 370 + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "provider": "openai.responses" + │ } + │ metrics: { + │ "completion_tokens": 62, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 308, + │ "tokens": 370 + │ } + ├── ai-sdk-workflow-agent-stream-operation + │ metadata: { + │ "operation": "workflow-agent-stream", + │ "testRunId": "" + │ } + │ └── WorkflowAgent.stream [function] + │ input: { + │ "messages": [ + │ { + │ "content": "Use get_weather for Paris, France, then reply with one short sentence.", + │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "messages": [ + │ { + │ "content": "You are a terse weather assistant. Use tools before answering.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ], + │ "steps": [ + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "dynamicToolCalls": [], + │ "dynamicToolResults": [], + │ "files": [], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "reasoning": [], + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "sources": [], + │ "staticToolCalls": [], + │ "staticToolResults": [], + │ "stepNumber": 0, + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [], + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 84 + │ }, + │ "inputTokens": 84, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 84, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 92 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "dynamicToolCalls": [], + │ "dynamicToolResults": [], + │ "files": [], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "reasoning": [], + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "sources": [], + │ "staticToolCalls": [], + │ "staticToolResults": [], + │ "stepNumber": 1, + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [], + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 123 + │ }, + │ "inputTokens": 123, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 123, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 131 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "dynamicToolCalls": [], + │ "dynamicToolResults": [], + │ "files": [], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "reasoning": [], + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "sources": [], + │ "staticToolCalls": [], + │ "staticToolResults": [], + │ "stepNumber": 2, + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [], + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 162 + │ }, + │ "inputTokens": 162, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 162, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 170 + │ }, + │ "warnings": [] + │ }, + │ { + │ "callId": "", + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "dynamicToolCalls": [], + │ "dynamicToolResults": [], + │ "files": [], + │ "finishReason": "tool-calls", + │ "model": { + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "provider": "gpt-4o-mini-2024-07-18" + │ }, + │ "providerMetadata": { + │ "openai": { + │ "responseId": "", + │ "serviceTier": "default" + │ } + │ }, + │ "reasoning": [], + │ "request": { + │ "messages": [] + │ }, + │ "response": { + │ "messages": [], + │ "modelId": "gpt-4o-mini-2024-07-18", + │ "timestamp": "" + │ }, + │ "runtimeContext": {}, + │ "sources": [], + │ "staticToolCalls": [], + │ "staticToolResults": [], + │ "stepNumber": 3, + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [], + │ "toolsContext": {}, + │ "usage": { + │ "inputTokenDetails": { + │ "cacheReadTokens": 0, + │ "noCacheTokens": 201 + │ }, + │ "inputTokens": 201, + │ "outputTokenDetails": { + │ "reasoningTokens": 0, + │ "textTokens": 8 + │ }, + │ "outputTokens": 8, + │ "raw": { + │ "input_tokens": 201, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ }, + │ "totalTokens": 209 + │ }, + │ "warnings": [] + │ } + │ ], + │ "toolCalls": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "toolResults": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "output": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ] + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "options": { + │ "maxOutputTokens": 96, + │ "stopWhen": "[Function]", + │ "temperature": 0, + │ "toolChoice": "required" + │ }, + │ "provider": "openai.responses", + │ "tools": { + │ "get_weather": { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ } + │ } + │ } + │ } + │ ├── doStream [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "finishReason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "text": "", + │ │ "toolCalls": [ + │ │ { + │ │ "input": "{\"location\":\"Paris, France\"}", + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "usage": { + │ │ "inputTokens": { + │ │ "cacheRead": 0, + │ │ "noCache": 84, + │ │ "total": 84 + │ │ }, + │ │ "outputTokens": { + │ │ "reasoning": 0, + │ │ "text": 8, + │ │ "total": 8 + │ │ }, + │ │ "raw": { + │ │ "input_tokens": 84, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ } + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "finish_reason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "includeRawChunks": false, + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0, + │ │ "toolChoice": { + │ │ "type": "required" + │ │ } + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_weather", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_reasoning_tokens": 0, + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 84, + │ │ "reasoning_tokens": 0, + │ │ "tokens": 92 + │ │ } + │ ├── get_weather [tool] + │ │ input: { + │ │ "location": "Paris, France" + │ │ } + │ │ output: { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ ├── doStream [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "finishReason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "text": "", + │ │ "toolCalls": [ + │ │ { + │ │ "input": "{\"location\":\"Paris, France\"}", + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "usage": { + │ │ "inputTokens": { + │ │ "cacheRead": 0, + │ │ "noCache": 123, + │ │ "total": 123 + │ │ }, + │ │ "outputTokens": { + │ │ "reasoning": 0, + │ │ "text": 8, + │ │ "total": 8 + │ │ }, + │ │ "raw": { + │ │ "input_tokens": 123, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ } + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "finish_reason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "includeRawChunks": false, + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0, + │ │ "toolChoice": { + │ │ "type": "required" + │ │ } + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_weather", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_reasoning_tokens": 0, + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 123, + │ │ "reasoning_tokens": 0, + │ │ "tokens": 131 + │ │ } + │ ├── get_weather [tool] + │ │ input: { + │ │ "location": "Paris, France" + │ │ } + │ │ output: { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ ├── doStream [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "finishReason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "text": "", + │ │ "toolCalls": [ + │ │ { + │ │ "input": "{\"location\":\"Paris, France\"}", + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "usage": { + │ │ "inputTokens": { + │ │ "cacheRead": 0, + │ │ "noCache": 162, + │ │ "total": 162 + │ │ }, + │ │ "outputTokens": { + │ │ "reasoning": 0, + │ │ "text": 8, + │ │ "total": 8 + │ │ }, + │ │ "raw": { + │ │ "input_tokens": 162, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ } + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "finish_reason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "includeRawChunks": false, + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0, + │ │ "toolChoice": { + │ │ "type": "required" + │ │ } + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_weather", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_reasoning_tokens": 0, + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 162, + │ │ "reasoning_tokens": 0, + │ │ "tokens": 170 + │ │ } + │ ├── get_weather [tool] + │ │ input: { + │ │ "location": "Paris, France" + │ │ } + │ │ output: { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ ├── doStream [llm] + │ │ input: { + │ │ "messages": [ + │ │ { + │ │ "content": "You are a terse weather assistant. Use tools before answering.", + │ │ "role": "system" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Use get_weather for Paris, France, then reply with one short sentence.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "input": { + │ │ "location": "Paris, France" + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "output": { + │ │ "type": "json", + │ │ "value": { + │ │ "condition": "sunny", + │ │ "location": "Paris, France", + │ │ "temperatureC": 22 + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-result" + │ │ } + │ │ ], + │ │ "role": "tool" + │ │ } + │ │ ] + │ │ } + │ │ output: { + │ │ "finishReason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "text": "", + │ │ "toolCalls": [ + │ │ { + │ │ "input": "{\"location\":\"Paris, France\"}", + │ │ "providerMetadata": { + │ │ "openai": { + │ │ "itemId": "" + │ │ } + │ │ }, + │ │ "toolName": "get_weather", + │ │ "type": "tool-call" + │ │ } + │ │ ], + │ │ "usage": { + │ │ "inputTokens": { + │ │ "cacheRead": 0, + │ │ "noCache": 201, + │ │ "total": 201 + │ │ }, + │ │ "outputTokens": { + │ │ "reasoning": 0, + │ │ "text": 8, + │ │ "total": 8 + │ │ }, + │ │ "raw": { + │ │ "input_tokens": 201, + │ │ "input_tokens_details": { + │ │ "cached_tokens": 0 + │ │ }, + │ │ "output_tokens": 8, + │ │ "output_tokens_details": { + │ │ "reasoning_tokens": 0 + │ │ } + │ │ } + │ │ } + │ │ } + │ │ metadata: { + │ │ "braintrust": { + │ │ "integration_name": "ai-sdk", + │ │ "sdk_language": "typescript" + │ │ }, + │ │ "finish_reason": { + │ │ "unified": "tool-calls" + │ │ }, + │ │ "model": "gpt-4o-mini-2024-07-18", + │ │ "options": { + │ │ "includeRawChunks": false, + │ │ "maxOutputTokens": 96, + │ │ "temperature": 0, + │ │ "toolChoice": { + │ │ "type": "required" + │ │ } + │ │ }, + │ │ "provider": "openai.responses", + │ │ "tools": [ + │ │ { + │ │ "description": "Get the weather for a location", + │ │ "inputSchema": { + │ │ "$schema": "http://json-schema.org/draft-07/schema#", + │ │ "additionalProperties": false, + │ │ "properties": { + │ │ "location": { + │ │ "description": "The city and country", + │ │ "type": "string" + │ │ } + │ │ }, + │ │ "required": [ + │ │ "location" + │ │ ], + │ │ "type": "object" + │ │ }, + │ │ "name": "get_weather", + │ │ "type": "function" + │ │ } + │ │ ] + │ │ } + │ │ metrics: { + │ │ "completion_reasoning_tokens": 0, + │ │ "completion_tokens": 8, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 201, + │ │ "reasoning_tokens": 0, + │ │ "tokens": 209 + │ │ } + │ └── get_weather [tool] + │ input: { + │ "location": "Paris, France" + │ } + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + └── ai-sdk-workflow-agent-stream-prompt-operation + metadata: { + "operation": "workflow-agent-stream-prompt", + "testRunId": "" + } + └── WorkflowAgent.stream [function] + input: { + "prompt": "What's the weather in Paris?", + "system": "You are a helpful weather assistant." + } + output: { + "messages": [ + { + "content": "You are a helpful weather assistant.", + "role": "system" + }, + { + "content": [ + { + "text": "What's the weather in Paris?", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + }, + { + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "output": { + "type": "json", + "value": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 + } + }, + "toolName": "get_weather", + "type": "tool-result" + } + ], + "role": "tool" + } + ], + "steps": [ + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 0, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 70 + }, + "inputTokens": 70, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 70, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 78 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 1, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 109 + }, + "inputTokens": 109, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 109, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 117 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", + "model": { + "modelId": "gpt-4o-mini-2024-07-18", + "provider": "gpt-4o-mini-2024-07-18" + }, + "providerMetadata": { + "openai": { + "responseId": "", + "serviceTier": "default" + } + }, + "reasoning": [], + "request": { + "messages": [] + }, + "response": { + "messages": [], + "modelId": "gpt-4o-mini-2024-07-18", + "timestamp": "" + }, + "runtimeContext": {}, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 2, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], + "toolsContext": {}, + "usage": { + "inputTokenDetails": { + "cacheReadTokens": 0, + "noCacheTokens": 148 + }, + "inputTokens": 148, + "outputTokenDetails": { + "reasoningTokens": 0, + "textTokens": 8 + }, + "outputTokens": 8, + "raw": { + "input_tokens": 148, + "input_tokens_details": { + "cached_tokens": 0 + }, + "output_tokens": 8, + "output_tokens_details": { + "reasoning_tokens": 0 + } + }, + "totalTokens": 156 + }, + "warnings": [] + }, + { + "callId": "", + "content": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "dynamicToolCalls": [], + "dynamicToolResults": [], + "files": [], + "finishReason": "tool-calls", "model": { "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" + "provider": "gpt-4o-mini-2024-07-18" }, "providerMetadata": { "openai": { - "responseId": "", + "responseId": "", "serviceTier": "default" } }, + "reasoning": [], + "request": { + "messages": [] + }, "response": { - "headers": "", - "messages": [ - { - "content": [ - { - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "role": "assistant" - } - ], + "messages": [], "modelId": "gpt-4o-mini-2024-07-18", "timestamp": "" }, "runtimeContext": {}, - "stepNumber": 2, + "sources": [], + "staticToolCalls": [], + "staticToolResults": [], + "stepNumber": 3, + "text": "", + "toolCalls": [ + { + "input": { + "location": "Paris, France" + }, + "toolName": "get_weather", + "type": "tool-call" + } + ], + "toolResults": [], "toolsContext": {}, "usage": { "inputTokenDetails": { "cacheReadTokens": 0, - "noCacheTokens": 308 + "noCacheTokens": 187 }, - "inputTokens": 308, + "inputTokens": 187, "outputTokenDetails": { "reasoningTokens": 0, - "textTokens": 62 + "textTokens": 8 }, - "outputTokens": 62, + "outputTokens": 8, "raw": { - "input_tokens": 308, + "input_tokens": 187, "input_tokens_details": { "cached_tokens": 0 }, - "output_tokens": 62, + "output_tokens": 8, "output_tokens_details": { "reasoning_tokens": 0 } }, - "totalTokens": 370 + "totalTokens": 195 }, "warnings": [] } ], - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", "toolCalls": [ { "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerMetadata": { - "openai": { - "itemId": "" - } + "location": "Paris, France" }, - "toolName": "apply_discount", + "toolName": "get_weather", "type": "tool-call" } ], "toolResults": [ { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreA" - }, - "output": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, - "input": { - "item": "laptop", - "store": "StoreB" - }, - "output": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}", - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "dynamic": false, "input": { - "discountCode": "SAVE20", - "total": 999 + "location": "Paris, France" }, - "output": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}", - "providerMetadata": { - "openai": { - "itemId": "" - } + "output": { + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 }, - "toolName": "apply_discount", + "toolName": "get_weather", "type": "tool-result" } - ], - "totalUsage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 741 - }, - "inputTokens": 741, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 142 - }, - "outputTokens": 142, - "totalTokens": 883 - }, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 741 - }, - "inputTokens": 741, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 142 - }, - "outputTokens": 142, - "totalTokens": 883 - }, - "warnings": [] + ] } metadata: { "braintrust": { @@ -3762,134 +5950,406 @@ span_tree: "sdk_language": "typescript" }, "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" + "options": { + "maxOutputTokens": 96, + "stopWhen": "[Function]", + "temperature": 0, + "toolChoice": "required" + }, + "provider": "openai.responses", + "tools": { + "get_weather": { + "description": "Get the weather for a location", + "inputSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "location": { + "description": "The city and country", + "type": "string" + } + }, + "required": [ + "location" + ], + "type": "object" + } + } + } } - ├── doGenerate [llm] + ├── doStream [llm] │ input: { - │ "maxOutputTokens": 256, │ "messages": [ │ { - │ "content": "I need help comparing laptop prices before checkout.", + │ "content": "You are a helpful weather assistant.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], │ "role": "user" + │ } + │ ] + │ } + │ output: { + │ "finishReason": { + │ "unified": "tool-calls" + │ }, + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": "{\"location\":\"Paris, France\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "usage": { + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 70, + │ "total": 70 + │ }, + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 8, + │ "total": 8 │ }, + │ "raw": { + │ "input_tokens": 70, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ } + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": { + │ "unified": "tool-calls" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "options": { + │ "includeRawChunks": false, + │ "maxOutputTokens": 96, + │ "temperature": 0, + │ "toolChoice": { + │ "type": "required" + │ } + │ }, + │ "provider": "openai.responses", + │ "tools": [ │ { - │ "content": "I can compare store prices and apply a discount code.", - │ "role": "assistant" + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ }, + │ "name": "get_weather", + │ "type": "function" + │ } + │ ] + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 8, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 70, + │ "reasoning_tokens": 0, + │ "tokens": 78 + │ } + ├── get_weather [tool] + │ input: { + │ "location": "Paris, France" + │ } + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + ├── doStream [llm] + │ input: { + │ "messages": [ + │ { + │ "content": "You are a helpful weather assistant.", + │ "role": "system" │ }, │ { - │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ } + │ ] + │ } + │ output: { + │ "finishReason": { + │ "unified": "tool-calls" + │ }, + │ "text": "", + │ "toolCalls": [ + │ { + │ "input": "{\"location\":\"Paris, France\"}", + │ "providerMetadata": { + │ "openai": { + │ "itemId": "" + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" │ } │ ], - │ "model": { - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" + │ "usage": { + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 109, + │ "total": 109 + │ }, + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 8, + │ "total": 8 + │ }, + │ "raw": { + │ "input_tokens": 109, + │ "input_tokens_details": { + │ "cached_tokens": 0 + │ }, + │ "output_tokens": 8, + │ "output_tokens_details": { + │ "reasoning_tokens": 0 + │ } + │ } + │ } + │ } + │ metadata: { + │ "braintrust": { + │ "integration_name": "ai-sdk", + │ "sdk_language": "typescript" + │ }, + │ "finish_reason": { + │ "unified": "tool-calls" + │ }, + │ "model": "gpt-4o-mini-2024-07-18", + │ "options": { + │ "includeRawChunks": false, + │ "maxOutputTokens": 96, + │ "temperature": 0, + │ "toolChoice": { + │ "type": "required" + │ } │ }, - │ "temperature": 0, + │ "provider": "openai.responses", │ "tools": [ │ { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ }, + │ "name": "get_weather", + │ "type": "function" + │ } + │ ] + │ } + │ metrics: { + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 8, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 109, + │ "reasoning_tokens": 0, + │ "tokens": 117 + │ } + ├── get_weather [tool] + │ input: { + │ "location": "Paris, France" + │ } + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + ├── doStream [llm] + │ input: { + │ "messages": [ + │ { + │ "content": "You are a helpful weather assistant.", + │ "role": "system" + │ }, + │ { + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" + │ }, + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } + │ }, + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ }, - │ "name": "get_store_price", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" │ }, │ { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ }, - │ "name": "apply_discount", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" │ } │ ] │ } │ output: { - │ "content": [ + │ "finishReason": { + │ "unified": "tool-calls" + │ }, + │ "text": "", + │ "toolCalls": [ │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, + │ "input": "{\"location\":\"Paris, France\"}", │ "providerMetadata": { │ "openai": { │ "itemId": "" │ } │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerMetadata": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-call" │ } │ ], - │ "finishReason": "tool-calls", - │ "response": {}, │ "usage": { - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 173 + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 148, + │ "total": 148 │ }, - │ "inputTokens": 173, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 59 + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 8, + │ "total": 8 │ }, - │ "outputTokens": 59, │ "raw": { - │ "input_tokens": 173, + │ "input_tokens": 148, │ "input_tokens_details": { │ "cached_tokens": 0 │ }, - │ "output_tokens": 59, + │ "output_tokens": 8, │ "output_tokens_details": { │ "reasoning_tokens": 0 │ } - │ }, - │ "totalTokens": 232 + │ } │ } │ } │ metadata: { @@ -3897,83 +6357,81 @@ span_tree: │ "integration_name": "ai-sdk", │ "sdk_language": "typescript" │ }, + │ "finish_reason": { + │ "unified": "tool-calls" + │ }, │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" + │ "options": { + │ "includeRawChunks": false, + │ "maxOutputTokens": 96, + │ "temperature": 0, + │ "toolChoice": { + │ "type": "required" + │ } + │ }, + │ "provider": "openai.responses", + │ "tools": [ + │ { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ }, + │ "name": "get_weather", + │ "type": "function" + │ } + │ ] │ } │ metrics: { - │ "completion_tokens": 59, + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 8, │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 173, - │ "tokens": 232 - │ } - ├── get_store_price [tool] - │ input: { - │ "item": "laptop", - │ "store": "StoreA" - │ } - │ output: "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "toolName": "get_store_price" + │ "prompt_tokens": 148, + │ "reasoning_tokens": 0, + │ "tokens": 156 │ } - ├── get_store_price [tool] + ├── get_weather [tool] │ input: { - │ "item": "laptop", - │ "store": "StoreB" + │ "location": "Paris, France" │ } - │ output: "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "toolName": "get_store_price" + │ output: { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 │ } - ├── doGenerate [llm] + ├── doStream [llm] │ input: { - │ "maxOutputTokens": 256, │ "messages": [ │ { - │ "content": "I need help comparing laptop prices before checkout.", - │ "role": "user" - │ }, - │ { - │ "content": "I can compare store prices and apply a discount code.", - │ "role": "assistant" + │ "content": "You are a helpful weather assistant.", + │ "role": "system" │ }, │ { - │ "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", + │ "content": [ + │ { + │ "text": "What's the weather in Paris?", + │ "type": "text" + │ } + │ ], │ "role": "user" │ }, │ { │ "content": [ │ { │ "input": { - │ "item": "laptop", - │ "store": "StoreA" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } - │ }, - │ "toolName": "get_store_price", - │ "type": "tool-call" - │ }, - │ { - │ "input": { - │ "item": "laptop", - │ "store": "StoreB" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" - │ } + │ "location": "Paris, France" │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-call" │ } │ ], @@ -3983,130 +6441,117 @@ span_tree: │ "content": [ │ { │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 │ } │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-result" - │ }, + │ } + │ ], + │ "role": "tool" + │ }, + │ { + │ "content": [ │ { - │ "output": { - │ "type": "text", - │ "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" + │ "input": { + │ "location": "Paris, France" │ }, - │ "providerOptions": { - │ "openai": { - │ "itemId": "" + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 │ } │ }, - │ "toolName": "get_store_price", + │ "toolName": "get_weather", │ "type": "tool-result" │ } │ ], │ "role": "tool" - │ } - │ ], - │ "model": { - │ "modelId": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" - │ }, - │ "temperature": 0, - │ "tools": [ + │ }, │ { - │ "description": "Get the price of an item at a store", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "item": { - │ "description": "The item to price", - │ "type": "string" + │ "content": [ + │ { + │ "input": { + │ "location": "Paris, France" │ }, - │ "store": { - │ "description": "The store name", - │ "type": "string" - │ } - │ }, - │ "required": [ - │ "item", - │ "store" - │ ], - │ "type": "object" - │ }, - │ "name": "get_store_price", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-call" + │ } + │ ], + │ "role": "assistant" │ }, │ { - │ "description": "Apply a discount code to a total", - │ "inputSchema": { - │ "$schema": "http://json-schema.org/draft-07/schema#", - │ "additionalProperties": false, - │ "properties": { - │ "discountCode": { - │ "description": "The discount code to apply", - │ "type": "string" + │ "content": [ + │ { + │ "output": { + │ "type": "json", + │ "value": { + │ "condition": "sunny", + │ "location": "Paris, France", + │ "temperatureC": 22 + │ } │ }, - │ "total": { - │ "description": "The original total", - │ "type": "number" - │ } - │ }, - │ "required": [ - │ "discountCode", - │ "total" - │ ], - │ "type": "object" - │ }, - │ "name": "apply_discount", - │ "type": "function" + │ "toolName": "get_weather", + │ "type": "tool-result" + │ } + │ ], + │ "role": "tool" │ } │ ] │ } │ output: { - │ "content": [ + │ "finishReason": { + │ "unified": "tool-calls" + │ }, + │ "text": "", + │ "toolCalls": [ │ { - │ "input": { - │ "discountCode": "SAVE20", - │ "total": 999 - │ }, + │ "input": "{\"location\":\"Paris, France\"}", │ "providerMetadata": { │ "openai": { │ "itemId": "" │ } │ }, - │ "toolName": "apply_discount", + │ "toolName": "get_weather", │ "type": "tool-call" │ } │ ], - │ "finishReason": "tool-calls", - │ "response": {}, │ "usage": { - │ "inputTokenDetails": { - │ "cacheReadTokens": 0, - │ "noCacheTokens": 260 + │ "inputTokens": { + │ "cacheRead": 0, + │ "noCache": 187, + │ "total": 187 │ }, - │ "inputTokens": 260, - │ "outputTokenDetails": { - │ "reasoningTokens": 0, - │ "textTokens": 21 + │ "outputTokens": { + │ "reasoning": 0, + │ "text": 8, + │ "total": 8 │ }, - │ "outputTokens": 21, │ "raw": { - │ "input_tokens": 260, + │ "input_tokens": 187, │ "input_tokens_details": { │ "cached_tokens": 0 │ }, - │ "output_tokens": 21, + │ "output_tokens": 8, │ "output_tokens_details": { │ "reasoning_tokens": 0 │ } - │ }, - │ "totalTokens": 281 + │ } │ } │ } │ metadata: { @@ -4114,248 +6559,55 @@ span_tree: │ "integration_name": "ai-sdk", │ "sdk_language": "typescript" │ }, + │ "finish_reason": { + │ "unified": "tool-calls" + │ }, │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai.responses" + │ "options": { + │ "includeRawChunks": false, + │ "maxOutputTokens": 96, + │ "temperature": 0, + │ "toolChoice": { + │ "type": "required" + │ } + │ }, + │ "provider": "openai.responses", + │ "tools": [ + │ { + │ "description": "Get the weather for a location", + │ "inputSchema": { + │ "$schema": "http://json-schema.org/draft-07/schema#", + │ "additionalProperties": false, + │ "properties": { + │ "location": { + │ "description": "The city and country", + │ "type": "string" + │ } + │ }, + │ "required": [ + │ "location" + │ ], + │ "type": "object" + │ }, + │ "name": "get_weather", + │ "type": "function" + │ } + │ ] │ } │ metrics: { - │ "completion_tokens": 21, + │ "completion_reasoning_tokens": 0, + │ "completion_tokens": 8, │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 260, - │ "tokens": 281 - │ } - ├── apply_discount [tool] - │ input: { - │ "discountCode": "SAVE20", - │ "total": 999 - │ } - │ output: "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - │ metadata: { - │ "braintrust": { - │ "integration_name": "ai-sdk", - │ "sdk_language": "typescript" - │ }, - │ "toolName": "apply_discount" + │ "prompt_tokens": 187, + │ "reasoning_tokens": 0, + │ "tokens": 195 │ } - └── doGenerate [llm] + └── get_weather [tool] input: { - "maxOutputTokens": 256, - "messages": [ - { - "content": "I need help comparing laptop prices before checkout.", - "role": "user" - }, - { - "content": "I can compare store prices and apply a discount code.", - "role": "assistant" - }, - { - "content": "Call get_store_price for a laptop at StoreA and StoreB, then call apply_discount with code SAVE20 for the cheaper price. Finish with the discounted total.", - "role": "user" - }, - { - "content": [ - { - "input": { - "item": "laptop", - "store": "StoreA" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - }, - { - "input": { - "item": "laptop", - "store": "StoreB" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":999,\"store\":\"StoreA\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - }, - { - "output": { - "type": "text", - "value": "{\"item\":\"laptop\",\"price\":1099,\"store\":\"StoreB\"}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "get_store_price", - "type": "tool-result" - } - ], - "role": "tool" - }, - { - "content": [ - { - "input": { - "discountCode": "SAVE20", - "total": 999 - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-call" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "output": { - "type": "text", - "value": "{\"discountCode\":\"SAVE20\",\"finalTotal\":799.2,\"originalTotal\":999}" - }, - "providerOptions": { - "openai": { - "itemId": "" - } - }, - "toolName": "apply_discount", - "type": "tool-result" - } - ], - "role": "tool" - } - ], - "model": { - "modelId": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - }, - "temperature": 0, - "tools": [ - { - "description": "Get the price of an item at a store", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "item": { - "description": "The item to price", - "type": "string" - }, - "store": { - "description": "The store name", - "type": "string" - } - }, - "required": [ - "item", - "store" - ], - "type": "object" - }, - "name": "get_store_price", - "type": "function" - }, - { - "description": "Apply a discount code to a total", - "inputSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "discountCode": { - "description": "The discount code to apply", - "type": "string" - }, - "total": { - "description": "The original total", - "type": "number" - } - }, - "required": [ - "discountCode", - "total" - ], - "type": "object" - }, - "name": "apply_discount", - "type": "function" - } - ] + "location": "Paris, France" } output: { - "content": [ - { - "providerMetadata": { - "openai": { - "itemId": "" - } - }, - "text": "Here are the prices for the laptop:\n\n- **Store A**: $999\n- **Store B**: $1099\n\nThe cheaper price is from **Store A** at $999. After applying the discount code **SAVE20**, the final total is **$799.20**.", - "type": "text" - } - ], - "finishReason": "stop", - "response": {}, - "usage": { - "inputTokenDetails": { - "cacheReadTokens": 0, - "noCacheTokens": 308 - }, - "inputTokens": 308, - "outputTokenDetails": { - "reasoningTokens": 0, - "textTokens": 62 - }, - "outputTokens": 62, - "raw": { - "input_tokens": 308, - "input_tokens_details": { - "cached_tokens": 0 - }, - "output_tokens": 62, - "output_tokens_details": { - "reasoning_tokens": 0 - } - }, - "totalTokens": 370 - } - } - metadata: { - "braintrust": { - "integration_name": "ai-sdk", - "sdk_language": "typescript" - }, - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai.responses" - } - metrics: { - "completion_tokens": 62, - "prompt_cached_tokens": 0, - "prompt_tokens": 308, - "tokens": 370 + "condition": "sunny", + "location": "Paris, France", + "temperatureC": 22 } diff --git a/e2e/scenarios/ai-sdk-instrumentation/assertions.ts b/e2e/scenarios/ai-sdk-instrumentation/assertions.ts index 2d71755d2..30c85555b 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/assertions.ts +++ b/e2e/scenarios/ai-sdk-instrumentation/assertions.ts @@ -215,6 +215,30 @@ function findModelChildren( }); } +function findModelDescendants( + capturedEvents: CapturedLogEvent[], + parentId: string | undefined, +) { + if (!parentId) { + return []; + } + + const descendantIds = new Set([parentId]); + for (const event of capturedEvents) { + if (event.span.parentIds.some((id) => descendantIds.has(id))) { + descendantIds.add(event.span.id); + } + } + + return capturedEvents.filter((event) => { + const name = event.span.name ?? ""; + return ( + event.span.parentIds.some((id) => descendantIds.has(id)) && + (name === "doGenerate" || name === "doStream") + ); + }); +} + function findParentSpan( events: CapturedLogEvent[], name: string, @@ -373,7 +397,7 @@ function findAgentGenerateTrace( `${agentSpanName}.generate`, operation?.span.id, ); - const modelChildren = findModelChildren(events, parent?.span.id); + const modelChildren = findModelDescendants(events, parent?.span.id); return { latestChild: latestEvent(modelChildren), @@ -393,7 +417,7 @@ function findAgentStreamTrace( `${agentSpanName}.stream`, operation?.span.id, ); - const modelChildren = findModelChildren(events, parent?.span.id); + const modelChildren = findModelDescendants(events, parent?.span.id); return { latestChild: latestEvent(modelChildren), @@ -849,6 +873,7 @@ export function defineAISDKInstrumentationAssertions(options: { supportsRerank: boolean; supportsStreamObject: boolean; supportsToolExecution: boolean; + supportsWorkflowAgent?: boolean; testFileUrl: string; timeoutMs: number; }): void { @@ -1288,6 +1313,93 @@ export function defineAISDKInstrumentationAssertions(options: { } } + if (options.supportsWorkflowAgent) { + test( + "captures trace for WorkflowAgent.stream() with messages", + testConfig, + () => { + const root = findLatestSpan(events, ROOT_NAME); + const trace = findWorkflowAgentTrace( + events, + "ai-sdk-workflow-agent-stream-operation", + ); + + expectOperationParentedByRoot(trace.operation, root); + expect(operationName(trace.operation)).toBe("workflow-agent-stream"); + expect(findAllSpans(events, "WorkflowAgent.stream")).toHaveLength(2); + expect(trace.workflowSpans).toHaveLength(1); + expectAISDKParentSpan(trace.parent); + expect(hasPromptLikeInput(trace.parent?.input)).toBe(true); + expect( + hasSemanticOutput(trace.parent?.output, [ + "messages", + "steps", + "text", + "toolCalls", + "toolResults", + ]), + ).toBe(true); + expect(trace.modelChildren.length).toBeGreaterThanOrEqual(1); + trace.modelChildren.forEach(expectAISDKModelChildSpan); + expect(trace.toolSpans.length).toBeGreaterThanOrEqual(1); + expect(trace.toolSpans[0]?.input).toMatchObject({ + location: expect.any(String), + }); + expect(trace.toolSpans[0]?.output).toBeDefined(); + expect(collectToolCallNames(trace.parent?.output)).toContain( + "get_weather", + ); + expect(collectToolResultNames(trace.parent?.output)).toContain( + "get_weather", + ); + expect(trace.parent?.span.ended).toBe(true); + expect(trace.modelChildren.every((child) => child.span.ended)).toBe( + true, + ); + }, + ); + + test( + "captures trace for WorkflowAgent.stream() with system and prompt", + testConfig, + () => { + const root = findLatestSpan(events, ROOT_NAME); + const trace = findWorkflowAgentTrace( + events, + "ai-sdk-workflow-agent-stream-prompt-operation", + ); + + expectOperationParentedByRoot(trace.operation, root); + expect(operationName(trace.operation)).toBe( + "workflow-agent-stream-prompt", + ); + expect(trace.workflowSpans).toHaveLength(1); + expectAISDKParentSpan(trace.parent); + const input = isRecord(trace.parent?.input) + ? trace.parent.input + : null; + expect(hasPromptLikeInput(input)).toBe(true); + expect(JSON.stringify(input)).toContain("weather in Paris"); + expect( + hasSemanticOutput(trace.parent?.output, [ + "messages", + "steps", + "text", + "toolCalls", + "toolResults", + ]), + ).toBe(true); + expect(trace.modelChildren.length).toBeGreaterThanOrEqual(1); + trace.modelChildren.forEach(expectAISDKModelChildSpan); + expect(trace.toolSpans.length).toBeGreaterThanOrEqual(1); + expect(trace.toolSpans[0]?.input).toMatchObject({ + location: expect.any(String), + }); + expect(trace.parent?.span.ended).toBe(true); + }, + ); + } + if (options.supportsAgentToolLoop) { test("captures trace for ToolLoopAgent tool loop", testConfig, () => { const root = findLatestSpan(events, ROOT_NAME); @@ -1384,3 +1496,29 @@ export function defineAISDKInstrumentationAssertions(options: { }); }); } + +function findWorkflowAgentTrace( + events: CapturedLogEvent[], + operationSpanName: string, +) { + const operation = findLatestSpan(events, operationSpanName); + const workflowSpans = findChildSpans( + events, + "WorkflowAgent.stream", + operation?.span.id, + ); + const parent = latestEvent(workflowSpans); + const modelChildren = [ + ...findChildSpans(events, "doGenerate", parent?.span.id), + ...findChildSpans(events, "doStream", parent?.span.id), + ]; + const toolSpans = findChildSpans(events, "get_weather", parent?.span.id); + + return { + modelChildren, + operation, + parent, + toolSpans, + workflowSpans, + }; +} diff --git a/e2e/scenarios/ai-sdk-instrumentation/package.json b/e2e/scenarios/ai-sdk-instrumentation/package.json index b5da44c4c..7a35bfbe0 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/package.json +++ b/e2e/scenarios/ai-sdk-instrumentation/package.json @@ -13,6 +13,8 @@ "ai-sdk-openai-v7": "@ai-sdk/openai@4.0.0-beta.44", "ai-sdk-cohere-v5": "@ai-sdk/cohere@2", "ai-sdk-cohere-v6": "@ai-sdk/cohere@3", + "ai-sdk-workflow-v1": "@ai-sdk/workflow@1", + "ai": "7.0.8", "ai-sdk-v3": "ai@3", "ai-sdk-v4": "ai@4", "ai-sdk-v5": "ai@5", @@ -31,6 +33,8 @@ "ai-sdk-openai-v7": "npm:@ai-sdk/openai@4.0.0-beta.44", "ai-sdk-cohere-v5": "npm:@ai-sdk/cohere@2.0.7", "ai-sdk-cohere-v6": "npm:@ai-sdk/cohere@3.0.7", + "ai-sdk-workflow-v1": "npm:@ai-sdk/workflow@1.0.8", + "ai": "7.0.8", "ai-sdk-v3": "npm:ai@3.4.33", "ai-sdk-v4": "npm:ai@4.3.19", "ai-sdk-v5": "npm:ai@5.0.82", diff --git a/e2e/scenarios/ai-sdk-instrumentation/pnpm-lock.yaml b/e2e/scenarios/ai-sdk-instrumentation/pnpm-lock.yaml index 4d7e89b67..437fdb392 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/pnpm-lock.yaml +++ b/e2e/scenarios/ai-sdk-instrumentation/pnpm-lock.yaml @@ -13,6 +13,9 @@ importers: .: dependencies: + ai: + specifier: 7.0.8 + version: 7.0.8(zod@3.25.76) ai-sdk-anthropic-v5: specifier: npm:@ai-sdk/anthropic@2.0.74 version: '@ai-sdk/anthropic@2.0.74(zod@3.25.76)' @@ -55,6 +58,9 @@ importers: ai-sdk-v7: specifier: npm:ai@7.0.0 version: ai@7.0.0(zod@3.25.76) + ai-sdk-workflow-v1: + specifier: npm:@ai-sdk/workflow@1.0.8 + version: '@ai-sdk/workflow@1.0.8(zod@3.25.76)' zod: specifier: 3.25.76 version: 3.25.76 @@ -103,6 +109,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/gateway@4.0.6': + resolution: {integrity: sha512-8GjssUxXeTd8tst2fYXNOFbtNNZFv3sG7aq7wKnQYrU2eB3JFR7np6o4F3Snp/fy/rJZSeH28LvjSWq5wkdL8Q==} + engines: {node: '>=22'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/openai@0.0.62': resolution: {integrity: sha512-qNQmTgZXGS3xyd6XsDGEMLWV3Ag3uAVPJxHVkZLDZ7Dubmgs3Mp8iupkwZ7JhD7TIBx8yifyyBuE1dnE70v8Ig==} engines: {node: '>=18'} @@ -211,6 +223,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@5.0.2': + resolution: {integrity: sha512-EcmdjJb7yggsZPCbS3MFBpvAUnKaPW+QvanU5GzF00XCq0bqqAmvJ3MN19ejlmOETbW8sJNiq6qam48wTcbUNw==} + engines: {node: '>=22'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider@0.0.23': resolution: {integrity: sha512-oAc49O5+xypVrKM7EUU5P/Y4DUL4JZUWVxhejoAVOTOl3WZUEWsMbP3QZR+TrimQIsS0WR/n9UuF6U0jPdp0tQ==} engines: {node: '>=18'} @@ -255,6 +273,10 @@ packages: resolution: {integrity: sha512-SMijtjVHs38n0dMkTcNuGrnStiF76OhAqS0R+ZX4iXUnuPPyTxQoVcF8Xuf2AoBB5rqndTId5FVT05bgqD5KsA==} engines: {node: '>=18'} + '@ai-sdk/provider@4.0.1': + resolution: {integrity: sha512-6p3C/vGqVIjcptBu1DnVd/BZJ2wWmV9TUv9192vT6ZvT9KNED8EwRTqyqFpoQZKgSbMDSvBSq3dqR524Nt/Crw==} + engines: {node: '>=22'} + '@ai-sdk/react@0.0.70': resolution: {integrity: sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ==} engines: {node: '>=18'} @@ -319,6 +341,12 @@ packages: vue: optional: true + '@ai-sdk/workflow@1.0.8': + resolution: {integrity: sha512-cCRvGNq3PORnsnE6DsWg8EltWCyC/Wu3QHOGRpN1pgtNrkeX+WbRZ6IX4JC6b7ibFC4hJUNzEunM+1yPkJ16kQ==} + engines: {node: '>=22'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@babel/helper-string-parser@7.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} @@ -471,6 +499,15 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + ai@7.0.8: + resolution: {integrity: sha512-vTEKl6fDBZ2IxBXTRaZOajf9W2Ev57Ju8iKtUvqlmDk8Z9BrEP4c22SWJsg1RcWHSFmJMSBa/s5dlUBHUq3YwA==} + engines: {node: '>=22'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + aria-query@5.3.1: resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} engines: {node: '>= 0.4'} @@ -526,9 +563,18 @@ packages: resolution: {integrity: sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==} engines: {node: '>=18.0.0'} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.3: + resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} + is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -564,6 +610,10 @@ packages: resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} @@ -668,6 +718,13 @@ snapshots: '@vercel/oidc': 3.2.0 zod: 3.25.76 + '@ai-sdk/gateway@4.0.6(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 4.0.1 + '@ai-sdk/provider-utils': 5.0.2(zod@3.25.76) + '@vercel/oidc': 3.2.0 + zod: 3.25.76 + '@ai-sdk/openai@0.0.62(zod@3.25.76)': dependencies: '@ai-sdk/provider': 0.0.23 @@ -788,6 +845,14 @@ snapshots: eventsource-parser: 3.0.8 zod: 3.25.76 + '@ai-sdk/provider-utils@5.0.2(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 4.0.1 + '@standard-schema/spec': 1.1.0 + '@workflow/serde': 4.1.0 + eventsource-parser: 3.0.8 + zod: 3.25.76 + '@ai-sdk/provider@0.0.23': dependencies: json-schema: 0.4.0 @@ -832,6 +897,10 @@ snapshots: dependencies: json-schema: 0.4.0 + '@ai-sdk/provider@4.0.1': + dependencies: + json-schema: 0.4.0 + '@ai-sdk/react@0.0.70(react@19.2.6)(zod@3.25.76)': dependencies: '@ai-sdk/provider-utils': 1.0.22(zod@3.25.76) @@ -896,6 +965,14 @@ snapshots: transitivePeerDependencies: - zod + '@ai-sdk/workflow@1.0.8(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 4.0.1 + '@ai-sdk/provider-utils': 5.0.2(zod@3.25.76) + ai: 7.0.8(zod@3.25.76) + ajv: 8.20.0 + zod: 3.25.76 + '@babel/helper-string-parser@7.29.7': {} '@babel/helper-validator-identifier@7.29.7': {} @@ -1065,6 +1142,20 @@ snapshots: '@ai-sdk/provider-utils': 5.0.0(zod@3.25.76) zod: 3.25.76 + ai@7.0.8(zod@3.25.76): + dependencies: + '@ai-sdk/gateway': 4.0.6(zod@3.25.76) + '@ai-sdk/provider': 4.0.1 + '@ai-sdk/provider-utils': 5.0.2(zod@3.25.76) + zod: 3.25.76 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + aria-query@5.3.1: {} axobject-query@4.1.0: {} @@ -1095,10 +1186,16 @@ snapshots: eventsource-parser@3.0.8: {} + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.3: {} + is-reference@3.0.3: dependencies: '@types/estree': 1.0.9 + json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} jsondiffpatch@0.6.0: @@ -1127,6 +1224,8 @@ snapshots: react@19.2.6: {} + require-from-string@2.0.2: {} + secure-json-parse@2.7.0: {} source-map-js@1.2.1: {} diff --git a/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7-explicit.mjs b/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7-explicit.mjs new file mode 100644 index 000000000..12300df76 --- /dev/null +++ b/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7-explicit.mjs @@ -0,0 +1,40 @@ +import { createOpenAI, openai } from "ai-sdk-openai-v7"; +import * as workflowAI from "ai"; +import * as ai from "ai-sdk-v7"; +import * as workflow from "ai-sdk-workflow-v1"; +import { braintrustAISDKTelemetry, wrapAISDK } from "braintrust"; +import { + getInstalledPackageVersion, + runMain, +} from "../../helpers/provider-runtime.mjs"; +import { runAutoAISDKInstrumentation } from "./scenario.impl.mjs"; + +ai.registerTelemetry(braintrustAISDKTelemetry()); + +runMain(async () => + runAutoAISDKInstrumentation({ + agentClassExport: "ToolLoopAgent", + ai, + createOpenAI, + maxTokensKey: "maxOutputTokens", + openai, + sdkVersion: await getInstalledPackageVersion(import.meta.url, "ai-sdk-v7"), + supportsDenyOutputOverrideScenario: false, + supportsAgentToolLoop: true, + supportsEmbedMany: true, + supportsGenerateObject: true, + supportsOpenAICacheScenario: false, + supportsOutputObjectScenario: true, + supportsProviderCacheAssertions: false, + supportsRerank: false, + supportsStreamObject: true, + supportsToolExecution: true, + workflow: wrapAISDK(workflow), + workflowAI, + workflowVersion: await getInstalledPackageVersion( + import.meta.url, + "ai-sdk-workflow-v1", + ), + toolSchemaKey: "inputSchema", + }), +); diff --git a/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7.mjs b/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7.mjs index 31dcfb02b..7df879d7a 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7.mjs +++ b/e2e/scenarios/ai-sdk-instrumentation/scenario.ai-sdk-v7.mjs @@ -1,5 +1,7 @@ import { createOpenAI, openai } from "ai-sdk-openai-v7"; +import * as workflowAI from "ai"; import * as ai from "ai-sdk-v7"; +import * as workflow from "ai-sdk-workflow-v1"; import { getInstalledPackageVersion } from "../../helpers/provider-runtime.mjs"; import { runAutoAISDKInstrumentationOrExit } from "./scenario.impl.mjs"; @@ -20,5 +22,11 @@ runAutoAISDKInstrumentationOrExit({ supportsRerank: false, supportsStreamObject: true, supportsToolExecution: true, + workflow, + workflowAI, + workflowVersion: await getInstalledPackageVersion( + import.meta.url, + "ai-sdk-workflow-v1", + ), toolSchemaKey: "inputSchema", }); diff --git a/e2e/scenarios/ai-sdk-instrumentation/scenario.impl.mjs b/e2e/scenarios/ai-sdk-instrumentation/scenario.impl.mjs index 36fe43dbe..ca22d4567 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/scenario.impl.mjs +++ b/e2e/scenarios/ai-sdk-instrumentation/scenario.impl.mjs @@ -101,8 +101,9 @@ export const AI_SDK_SCENARIO_SPECS = [ supportsRerank: false, supportsStreamObject: true, supportsToolExecution: true, + supportsWorkflowAgent: true, toolSchemaKey: "inputSchema", - wrapperEntry: "scenario.ai-sdk-v7.ts", + wrapperEntry: "scenario.ai-sdk-v7-explicit.mjs", wrapperSnapshotSuffix: "explicit", wrapperTestName: "explicit telemetry", }, @@ -201,6 +202,66 @@ function createWeatherTool(ai, schemaKey) { }); } +async function runWorkflowAgentStreamOperation({ + ai, + instrumentedWorkflow, + openaiModel, +}) { + const agent = new instrumentedWorkflow.WorkflowAgent({ + instructions: + "You are a terse weather assistant. Use tools before answering.", + model: openaiModel, + tools: { + get_weather: ai.tool({ + description: "Get the weather for a location", + inputSchema: z.object({ + location: z.string().describe("The city and country"), + }), + execute: async ({ location }) => ({ + condition: "sunny", + location, + temperatureC: 22, + }), + }), + }, + }); + + await runOperation( + "ai-sdk-workflow-agent-stream-operation", + "workflow-agent-stream", + async () => { + await agent.stream({ + messages: [ + { + role: "user", + content: + "Use get_weather for Paris, France, then reply with one short sentence.", + }, + ], + stopWhen: ai.stepCountIs(4), + temperature: 0, + toolChoice: "required", + maxOutputTokens: 96, + }); + }, + ); + + await runOperation( + "ai-sdk-workflow-agent-stream-prompt-operation", + "workflow-agent-stream-prompt", + async () => { + await agent.stream({ + system: "You are a helpful weather assistant.", + prompt: "What's the weather in Paris?", + stopWhen: ai.stepCountIs(4), + temperature: 0, + toolChoice: "required", + maxOutputTokens: 96, + }); + }, + ); +} + async function runAISDKInstrumentationScenario( options, { decorateAI, flushCount, flushDelayMs } = {}, @@ -611,12 +672,23 @@ async function runAISDKInstrumentationScenario( ); } } + + if (options.workflow) { + await runWorkflowAgentStreamOperation({ + ai: options.workflowAI ?? options.ai, + instrumentedWorkflow: options.workflow, + openaiModel, + }); + } }, flushCount, flushDelayMs, metadata: { aiSdkVersion: options.sdkVersion, scenario: SCENARIO_NAME, + ...(options.workflowVersion + ? { workflowVersion: options.workflowVersion } + : {}), }, projectNameBase: "e2e-ai-sdk-instrumentation", rootName: ROOT_NAME, diff --git a/e2e/scenarios/ai-sdk-instrumentation/scenario.test.ts b/e2e/scenarios/ai-sdk-instrumentation/scenario.test.ts index 1fe05a74a..1c6f2c396 100644 --- a/e2e/scenarios/ai-sdk-instrumentation/scenario.test.ts +++ b/e2e/scenarios/ai-sdk-instrumentation/scenario.test.ts @@ -68,6 +68,7 @@ describe.concurrent("variants", () => { supportsRerank: scenario.supportsRerank !== false, supportsStreamObject: scenario.supportsStreamObject, supportsToolExecution: scenario.supportsToolExecution, + supportsWorkflowAgent: scenario.supportsWorkflowAgent, sdkMajorVersion, testFileUrl: import.meta.url, timeoutMs: AI_SDK_SCENARIO_TIMEOUT_MS, @@ -100,6 +101,7 @@ describe.concurrent("variants", () => { supportsRerank: scenario.supportsRerank !== false, supportsStreamObject: scenario.supportsStreamObject, supportsToolExecution: scenario.supportsToolExecution, + supportsWorkflowAgent: scenario.supportsWorkflowAgent, sdkMajorVersion, testFileUrl: import.meta.url, timeoutMs: AI_SDK_SCENARIO_TIMEOUT_MS, diff --git a/js/src/auto-instrumentations/configs/ai-sdk.ts b/js/src/auto-instrumentations/configs/ai-sdk.ts index 09a43bb4d..b7e3bfa7e 100644 --- a/js/src/auto-instrumentations/configs/ai-sdk.ts +++ b/js/src/auto-instrumentations/configs/ai-sdk.ts @@ -210,6 +210,18 @@ export const aiSDKConfigs: InstrumentationConfig[] = [ kind: "Sync", }, }, + { + channelName: aiSDKChannels.v7CreateTelemetryDispatcher.channelName, + module: { + name: "ai", + versionRange: ">=7.0.0-0 <8.0.0", + filePath: "dist/internal/index.js", + }, + functionQuery: { + functionName: "createTelemetryDispatcher", + kind: "Sync", + }, + }, // streamObject - async function (v3 only, before the sync refactor in v4) { diff --git a/js/src/instrumentation/core/channel-tracing.ts b/js/src/instrumentation/core/channel-tracing.ts index 2f2d49e62..a45002bab 100644 --- a/js/src/instrumentation/core/channel-tracing.ts +++ b/js/src/instrumentation/core/channel-tracing.ts @@ -113,6 +113,13 @@ export type StreamingChannelSpanConfig = span: Span; startTime: number; }) => void; + onError?: (args: { + channelName: string; + error: Error; + event: AsyncEndOf | ErrorOf; + span: Span; + startTime: number; + }) => void; }; export type SyncStreamChannelSpanConfig = @@ -374,6 +381,31 @@ function runStreamingCompletionHook(args: { } } +function runStreamingErrorHook(args: { + channelName: string; + config: StreamingChannelSpanConfig; + error: Error; + event: AsyncEndOf | ErrorOf; + span: Span; + startTime: number; +}): void { + if (!args.config.onError) { + return; + } + + try { + args.config.onError({ + channelName: args.channelName, + error: args.error, + event: args.event, + span: args.span, + startTime: args.startTime, + }); + } catch (error) { + debugLogger.error(`Error in onError hook for ${args.channelName}:`, error); + } +} + export function traceAsyncChannel( channel: TChannel, config: AsyncChannelSpanConfig, @@ -571,6 +603,14 @@ export function traceStreamingChannel( } }, onError: (error: Error) => { + runStreamingErrorHook({ + channelName, + config, + error, + event: asyncEndEvent, + span, + startTime, + }); span.log({ error: error.message, }); @@ -638,6 +678,17 @@ export function traceStreamingChannel( } }, error: (event) => { + const spanData = states.get(event as object); + if (spanData) { + runStreamingErrorHook({ + channelName, + config, + error: (event as ErrorOf).error, + event: event as ErrorOf, + span: spanData.span, + startTime: spanData.startTime, + }); + } logErrorAndEnd(states, event as ErrorOf); }, }; diff --git a/js/src/instrumentation/plugins/ai-sdk-channels.ts b/js/src/instrumentation/plugins/ai-sdk-channels.ts index 316a83734..4ae2fea9f 100644 --- a/js/src/instrumentation/plugins/ai-sdk-channels.ts +++ b/js/src/instrumentation/plugins/ai-sdk-channels.ts @@ -140,6 +140,15 @@ export const aiSDKChannels = defineChannels("ai", { channelName: "ToolLoopAgent.stream", kind: "async", }), + workflowAgentStream: channel< + [AISDKCallParams], + AISDKStreamResult, + AISDKChannelContext, + unknown + >({ + channelName: "WorkflowAgent.stream", + kind: "async", + }), v7CreateTelemetryDispatcher: channel< [AISDKV7CreateTelemetryDispatcherArgs], AISDKV7TelemetryDispatcher diff --git a/js/src/instrumentation/plugins/ai-sdk-plugin.streaming.test.ts b/js/src/instrumentation/plugins/ai-sdk-plugin.streaming.test.ts index 3fd0371a6..3837d50ad 100644 --- a/js/src/instrumentation/plugins/ai-sdk-plugin.streaming.test.ts +++ b/js/src/instrumentation/plugins/ai-sdk-plugin.streaming.test.ts @@ -16,8 +16,10 @@ import { Logger, TestBackgroundLogger, } from "../../logger"; -import { wrapAISDK } from "../../wrappers/ai-sdk"; +import { wrapAISDK, wrapAgentClass } from "../../wrappers/ai-sdk"; +import { workflowAgentWrapperSpanCountForTesting } from "../../wrappers/ai-sdk/workflow-agent-context"; import { aiSDKChannels } from "./ai-sdk-channels"; +import { AISDKPlugin } from "./ai-sdk-plugin"; try { configureNode(); @@ -327,6 +329,459 @@ describe("AI SDK streaming instrumentation", () => { expect(doStreamSpan?.output?.text).toBe("DELAYED"); }); + test("wrapAISDK and wrapAgentClass instrument WorkflowAgent.stream", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + class WorkflowAgent { + #_name: string; + + constructor(options: { name: string }) { + this.#_name = options.name; + } + + getName() { + return this.#_name; + } + + async stream(params: any) { + return { + messages: params.messages, + prompt: params.prompt, + steps: [], + text: `Streamed by ${this.#_name}`, + }; + } + } + + const wrappedWorkflow = wrapAISDK({ WorkflowAgent }); + const namespaceAgent = new wrappedWorkflow.WorkflowAgent({ + name: "NamespaceWorkflowAgent", + }); + + expect(namespaceAgent.getName()).toBe("NamespaceWorkflowAgent"); + await namespaceAgent.stream({ + headers: { authorization: "secret" }, + maxOutputTokens: 12, + messages: [{ role: "user", content: "Hello" }], + stopWhen: () => true, + }); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + const WrappedWorkflowAgent = wrapAgentClass(WorkflowAgent); + const directlyWrappedAgent = new WrappedWorkflowAgent({ + name: "DirectWorkflowAgent", + }); + + expect(directlyWrappedAgent.getName()).toBe("DirectWorkflowAgent"); + await directlyWrappedAgent.stream({ + headers: { authorization: "secret" }, + maxOutputTokens: 12, + prompt: "Hello again", + stopWhen: () => true, + system: "You are terse.", + }); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + const spans = (await backgroundLogger.drain()) as any[]; + const workflowSpans = spans.filter( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ); + + expect(workflowSpans).toHaveLength(2); + expect( + workflowSpans.find((span) => Array.isArray(span.input?.messages))?.input, + ).toMatchObject({ + messages: [{ role: "user", content: "Hello" }], + }); + expect( + workflowSpans.find((span) => span.input?.prompt === "Hello again")?.input, + ).toMatchObject({ + prompt: "Hello again", + system: "You are terse.", + }); + for (const span of workflowSpans) { + expect(span.span_attributes).toMatchObject({ + type: "function", + name: "WorkflowAgent.stream", + }); + expect(span.input).not.toHaveProperty("headers"); + expect(span.input).not.toHaveProperty("maxOutputTokens"); + expect(span.input).not.toHaveProperty("stopWhen"); + expect(span.metadata).toMatchObject({ + options: { + maxOutputTokens: 12, + stopWhen: "[Function]", + }, + }); + expect(span.metadata.options).not.toHaveProperty("headers"); + expect(span.output).toBeDefined(); + } + }); + + test("wrapAISDK unregisters WorkflowAgent spans when stream creation fails", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + class WorkflowAgent { + async stream() { + throw new Error("workflow stream failed"); + } + } + + const wrappedWorkflow = wrapAISDK({ WorkflowAgent }); + const agent = new wrappedWorkflow.WorkflowAgent(); + + await expect( + agent.stream({ + messages: [{ role: "user", content: "Hello" }], + }), + ).rejects.toThrow("workflow stream failed"); + + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + }); + + test("wrapAISDK unregisters WorkflowAgent spans when textStream is cancelled early", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + class WorkflowAgent { + async stream(params: any) { + return { + messages: params.messages, + steps: [], + baseStream: new ReadableStream({ + start(controller) { + controller.enqueue({ type: "text-delta", delta: "first" }); + }, + }), + textStream: (async function* () { + yield "first"; + yield "second"; + })(), + }; + } + } + + const wrappedWorkflow = wrapAISDK({ WorkflowAgent }); + const agent = new wrappedWorkflow.WorkflowAgent(); + const result = await agent.stream({ + messages: [{ role: "user", content: "Hello" }], + }); + + let text = ""; + for await (const chunk of result.textStream) { + text += chunk; + break; + } + + expect(text).toBe("first"); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + const spans = (await backgroundLogger.drain()) as any[]; + expect( + spans.find( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ), + ).toBeDefined(); + }); + + test("wrapAISDK unregisters WorkflowAgent spans when baseStream is cancelled", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + let cancelReason: unknown; + class WorkflowAgent { + async stream(params: any) { + return { + messages: params.messages, + steps: [], + baseStream: new ReadableStream({ + start(controller) { + controller.enqueue({ type: "text-delta", delta: "first" }); + }, + cancel(reason) { + cancelReason = reason; + }, + }), + }; + } + } + + const wrappedWorkflow = wrapAISDK({ WorkflowAgent }); + const agent = new wrappedWorkflow.WorkflowAgent(); + const result = await agent.stream({ + messages: [{ role: "user", content: "Hello" }], + }); + + const reader = result.baseStream.getReader(); + const first = await reader.read(); + expect(first.done).toBe(false); + await reader.cancel("done early"); + + expect(cancelReason).toBe("done early"); + expect(workflowAgentWrapperSpanCountForTesting()).toBe(0); + + const spans = (await backgroundLogger.drain()) as any[]; + expect( + spans.find( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ), + ).toBeDefined(); + }); + + test("wrapAISDK records WorkflowAgent instance tool spans", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + + class WorkflowAgent { + model: any; + tools: any; + + constructor(options: { model: any; tools: any }) { + this.model = options.model; + this.tools = options.tools; + } + + async stream(params: any) { + await this.model.doGenerate({ + headers: { authorization: "secret" }, + maxOutputTokens: 8, + messages: params.messages, + temperature: 0, + }); + const output = await this.tools.get_weather.execute({ + location: "Vienna, Austria", + }); + return { + messages: params.messages, + steps: [ + { + toolCalls: [ + { + toolCallId: "tool-1", + toolName: "get_weather", + input: { location: "Vienna, Austria" }, + }, + ], + toolResults: [ + { + toolCallId: "tool-1", + toolName: "get_weather", + output, + }, + ], + }, + ], + toolCalls: [ + { + toolCallId: "tool-1", + toolName: "get_weather", + input: { location: "Vienna, Austria" }, + }, + ], + toolResults: [ + { + toolCallId: "tool-1", + toolName: "get_weather", + output, + }, + ], + }; + } + } + + const wrappedWorkflow = wrapAISDK({ WorkflowAgent }); + const agent = new wrappedWorkflow.WorkflowAgent({ + model: { + modelId: "mock-workflow-model", + provider: "mock-provider", + doGenerate: async () => ({ + text: "Calling get_weather.", + usage: { + inputTokens: 4, + outputTokens: 3, + totalTokens: 7, + }, + }), + }, + tools: { + get_weather: { + execute: async ({ location }: { location: string }) => ({ + condition: "sunny", + location, + temperatureC: 21, + }), + }, + }, + }); + + await agent.stream({ + headers: { authorization: "secret" }, + maxOutputTokens: 12, + messages: [{ role: "user", content: "Use get_weather." }], + }); + + const spans = (await backgroundLogger.drain()) as any[]; + const workflowSpan = spans.find( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ); + const modelSpan = spans.find( + (span) => span.span_attributes?.name === "doGenerate", + ); + const toolSpan = spans.find( + (span) => span.span_attributes?.name === "get_weather", + ); + + expect(workflowSpan).toBeDefined(); + expect(modelSpan).toMatchObject({ + input: { messages: [{ role: "user", content: "Use get_weather." }] }, + metadata: { + options: { + maxOutputTokens: 8, + temperature: 0, + }, + }, + output: { text: "Calling get_weather." }, + span_attributes: { name: "doGenerate", type: "llm" }, + span_parents: [workflowSpan?.span_id], + }); + expect(workflowSpan.input).toEqual({ + messages: [{ role: "user", content: "Use get_weather." }], + }); + expect(workflowSpan.metadata.options).toMatchObject({ + maxOutputTokens: 12, + }); + expect(workflowSpan.input).not.toHaveProperty("headers"); + expect(workflowSpan.metadata.options).not.toHaveProperty("headers"); + expect(modelSpan.input).not.toHaveProperty("headers"); + expect(modelSpan.metadata.options).not.toHaveProperty("headers"); + expect(toolSpan).toMatchObject({ + input: { location: "Vienna, Austria" }, + output: { + condition: "sunny", + location: "Vienna, Austria", + temperatureC: 21, + }, + span_attributes: { name: "get_weather", type: "tool" }, + span_parents: [workflowSpan?.span_id], + }); + }); + + test("wrapAISDK parents concurrent WorkflowAgent child spans to the active stream", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + + let releaseA!: () => void; + let releaseB!: () => void; + const gateA = new Promise((resolve) => { + releaseA = resolve; + }); + const gateB = new Promise((resolve) => { + releaseB = resolve; + }); + + class WorkflowAgent { + model: any; + tools: any; + + constructor(options: { model: any; tools: any }) { + this.model = options.model; + this.tools = options.tools; + } + + async stream(params: any) { + await params.beforeTool; + const generated = await this.model.doGenerate({ + messages: params.messages, + }); + const weather = await this.tools.get_weather.execute({ + run: params.run, + }); + return { + messages: params.messages, + text: `${generated.text} ${weather.run}`, + }; + } + } + + const wrappedWorkflow = wrapAISDK({ WorkflowAgent }); + const agent = new wrappedWorkflow.WorkflowAgent({ + model: { + modelId: "mock-workflow-model", + provider: "mock-provider", + doGenerate: async ({ messages }: any) => ({ + text: messages[0].content, + usage: { + inputTokens: 4, + outputTokens: 2, + totalTokens: 6, + }, + }), + }, + tools: { + get_weather: { + execute: async ({ run }: { run: string }) => { + if (run === "B") { + await sleep(20); + } + return { run }; + }, + }, + }, + }); + + const runA = agent.stream({ + beforeTool: gateA, + messages: [{ role: "user", content: "Run A" }], + run: "A", + }); + const runB = agent.stream({ + beforeTool: gateB, + messages: [{ role: "user", content: "Run B" }], + run: "B", + }); + + releaseA(); + releaseB(); + await Promise.all([runA, runB]); + + const spans = (await backgroundLogger.drain()) as any[]; + const workflowA = spans.find( + (span) => + span.span_attributes?.name === "WorkflowAgent.stream" && + JSON.stringify(span.input).includes("Run A"), + ); + const workflowB = spans.find( + (span) => + span.span_attributes?.name === "WorkflowAgent.stream" && + JSON.stringify(span.input).includes("Run B"), + ); + const modelA = spans.find( + (span) => + span.span_attributes?.name === "doGenerate" && + JSON.stringify(span.input).includes("Run A"), + ); + const modelB = spans.find( + (span) => + span.span_attributes?.name === "doGenerate" && + JSON.stringify(span.input).includes("Run B"), + ); + const toolA = spans.find( + (span) => + span.span_attributes?.name === "get_weather" && span.input?.run === "A", + ); + const toolB = spans.find( + (span) => + span.span_attributes?.name === "get_weather" && span.input?.run === "B", + ); + + expect(workflowA).toBeDefined(); + expect(workflowB).toBeDefined(); + expect(modelA?.span_parents).toEqual([workflowA?.span_id]); + expect(modelB?.span_parents).toEqual([workflowB?.span_id]); + expect(toolA?.span_parents).toEqual([workflowA?.span_id]); + expect(toolB?.span_parents).toEqual([workflowB?.span_id]); + }); + test("streamText time_to_first_token counts streamed tool input arguments", async () => { expect(await backgroundLogger.drain()).toHaveLength(0); @@ -388,4 +843,147 @@ describe("AI SDK streaming instrumentation", () => { contentDelayMs / 1000 / 2, ); }); + + test("baseStream patch preserves derived stream getters", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + + const plugin = new AISDKPlugin(); + plugin.enable(); + + try { + let chunkSent = false; + const result = (await aiSDKChannels.streamText.tracePromise( + async () => { + const resultRecord = { + baseStream: new ReadableStream({ + pull(controller) { + if (chunkSent) { + controller.close(); + return; + } + + chunkSent = true; + controller.enqueue({ + type: "text-delta", + id: "text-1", + delta: "fresh", + }); + }, + }), + text: Promise.resolve("fresh"), + } as any; + + Object.defineProperty(resultRecord, "textStream", { + configurable: true, + enumerable: true, + get() { + const [textBranch, baseBranch] = this.baseStream.tee(); + this.baseStream = baseBranch; + return textBranch.pipeThrough( + new TransformStream({ + transform(chunk: any, controller) { + if (chunk.type === "text-delta") { + controller.enqueue(chunk.delta); + } + }, + }), + ); + }, + }); + + return resultRecord; + }, + { + arguments: [ + { + model: "mock-stream-model", + prompt: "Reply with fresh.", + }, + ], + } as any, + )) as any; + + expect( + Object.getOwnPropertyDescriptor(result, "textStream")?.get, + ).toEqual(expect.any(Function)); + + let firstText = ""; + for await (const chunk of result.textStream) { + firstText += chunk; + } + + let secondText = ""; + for await (const chunk of result.textStream) { + secondText += chunk; + } + + expect(firstText).toBe("fresh"); + expect(secondText).toBe("fresh"); + } finally { + plugin.disable(); + } + }); + + test("async iterable stream accessors preserve ReadableStream methods", async () => { + expect(await backgroundLogger.drain()).toHaveLength(0); + + const plugin = new AISDKPlugin(); + plugin.enable(); + + try { + const result = (await aiSDKChannels.streamText.tracePromise( + async () => { + const resultRecord = { + stream: new ReadableStream({ + start(controller) { + controller.enqueue("v7"); + controller.close(); + }, + }), + text: Promise.resolve("v7"), + } as any; + + Object.defineProperty(resultRecord, "textStream", { + configurable: true, + enumerable: true, + get() { + return this.stream.pipeThrough( + new TransformStream({ + transform(chunk: string, controller) { + controller.enqueue(chunk.toUpperCase()); + }, + }), + ); + }, + }); + + return resultRecord; + }, + { + arguments: [ + { + model: "mock-v7-stream-model", + prompt: "Reply with v7.", + }, + ], + } as any, + )) as any; + + expect(result.stream.pipeThrough).toEqual(expect.any(Function)); + expect(result.stream.getReader).toEqual(expect.any(Function)); + + const textStream = result.textStream; + expect(textStream.pipeThrough).toEqual(expect.any(Function)); + expect(textStream.getReader).toEqual(expect.any(Function)); + + const reader = textStream.getReader(); + const first = await reader.read(); + const second = await reader.read(); + + expect(first).toEqual({ done: false, value: "V7" }); + expect(second).toEqual({ done: true, value: undefined }); + } finally { + plugin.disable(); + } + }); }); diff --git a/js/src/instrumentation/plugins/ai-sdk-plugin.test.ts b/js/src/instrumentation/plugins/ai-sdk-plugin.test.ts index d1ed8f7e8..caf2dd3b7 100644 --- a/js/src/instrumentation/plugins/ai-sdk-plugin.test.ts +++ b/js/src/instrumentation/plugins/ai-sdk-plugin.test.ts @@ -4,8 +4,10 @@ const telemetryMocks = vi.hoisted(() => ({ braintrustAISDKTelemetry: vi.fn(), telemetry: {} as { executeTool?: ReturnType; + onAbort?: ReturnType; onEnd?: ReturnType; onStart?: ReturnType; + onStepEnd?: ReturnType; }, })); @@ -20,10 +22,18 @@ vi.mock("../../wrappers/ai-sdk/telemetry", () => ({ braintrustAISDKTelemetry: telemetryMocks.braintrustAISDKTelemetry, })); -import { AISDKPlugin } from "./ai-sdk-plugin"; +import { + AISDKPlugin, + DEFAULT_DENY_OUTPUT_PATHS, + processAISDKCallInput, + processAISDKWorkflowAgentCallInput, + processAISDKWorkflowAgentModelCallInput, + processAISDKOutput as processAISDKOutputActual, +} from "./ai-sdk-plugin"; import { Attachment } from "../../logger"; import iso from "../../isomorph"; import { serializeAISDKToolsForLogging } from "../../wrappers/ai-sdk/tool-serialization"; +import { BRAINTRUST_AI_SDK_V7_OPERATION_KEY as AI_SDK_V7_OPERATION_KEY } from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; const mockNewTracingChannel = iso.newTracingChannel as ReturnType; type MockTracingChannel = { @@ -45,8 +55,10 @@ describe("AISDKPlugin", () => { mockChannels.clear(); telemetryMocks.telemetry = { executeTool: vi.fn(({ execute }) => execute()), + onAbort: vi.fn(), onEnd: vi.fn(), onStart: vi.fn(), + onStepEnd: vi.fn(), }; telemetryMocks.braintrustAISDKTelemetry.mockReturnValue( telemetryMocks.telemetry, @@ -94,6 +106,93 @@ describe("AISDKPlugin", () => { }); }); + describe("WorkflowAgent input extraction", () => { + it("preserves string prompts and system overrides", () => { + expect( + processAISDKWorkflowAgentCallInput({ + headers: { authorization: "secret" }, + maxOutputTokens: 12, + prompt: "What's the weather in Paris?", + stopWhen: () => true, + system: "You are a helpful weather assistant.", + }).input, + ).toEqual({ + prompt: "What's the weather in Paris?", + system: "You are a helpful weather assistant.", + }); + }); + + it("preserves public prompt message arrays for WorkflowAgent spans", () => { + expect( + processAISDKWorkflowAgentCallInput({ + prompt: [{ role: "user", content: "Hello" }], + system: "You are terse.", + }).input, + ).toEqual({ + prompt: [{ role: "user", content: "Hello" }], + system: "You are terse.", + }); + }); + + it("normalizes model call prompt arrays for WorkflowAgent child spans", () => { + expect( + processAISDKWorkflowAgentModelCallInput({ + instructions: "You are terse.", + prompt: [{ role: "user", content: "Hello" }], + }).input, + ).toEqual({ + instructions: "You are terse.", + messages: [{ role: "user", content: "Hello" }], + }); + }); + + it("does not treat arbitrary prompt objects as public AI SDK prompts", () => { + expect( + processAISDKWorkflowAgentCallInput({ + prompt: { role: "user", content: "Hello" } as any, + system: "You are terse.", + }).input, + ).toEqual({ + system: "You are terse.", + }); + }); + + it("omits SDK internals and function options from call inputs", () => { + const processed = processAISDKCallInput({ + model: { + config: { + provider: "openai.responses", + url: () => "https://example.test", + }, + doGenerate: async () => ({}), + doStream: async () => ({ stream: new ReadableStream() }), + modelId: "gpt-4.1-mini", + }, + experimental_output: { + responseFormat: Promise.resolve({ type: "json" }), + type: "object", + }, + prompt: "Hello", + stopWhen: () => true, + }).input as Record; + + expect(processed).toMatchObject({ + model: { + config: { + provider: "openai.responses", + }, + modelId: "gpt-4.1-mini", + }, + prompt: "Hello", + }); + expect(processed).not.toHaveProperty("experimental_output"); + expect(processed).not.toHaveProperty("stopWhen"); + expect(processed.model).not.toHaveProperty("doGenerate"); + expect(processed.model).not.toHaveProperty("doStream"); + expect(processed.model.config).not.toHaveProperty("url"); + }); + }); + describe("enable/disable", () => { it("should enable plugin", () => { expect(() => plugin.enable()).not.toThrow(); @@ -128,12 +227,16 @@ describe("AISDKPlugin", () => { it("patches dispatcher callbacks through the standard channel", async () => { const existingOnEnd = vi.fn(); const existingOnStart = vi.fn(); + const existingOnStepEnd = vi.fn(); + const existingOnAbort = vi.fn(); const originalExecute = vi.fn(async () => "done"); const existingExecuteTool = vi.fn(({ execute }) => execute()); const dispatcher = { executeTool: existingExecuteTool, + onAbort: existingOnAbort, onEnd: existingOnEnd, onStart: existingOnStart, + onStepEnd: existingOnStepEnd, }; plugin.enable(); @@ -144,7 +247,7 @@ describe("AISDKPlugin", () => { expect(channel?.subscribe).toHaveBeenCalledTimes(1); channel?.handlers[0]?.end({ - arguments: [{ telemetry: { recordInputs: true } }], + arguments: [{ telemetry: {} }], result: dispatcher, }); @@ -168,6 +271,26 @@ describe("AISDKPlugin", () => { operationId: "ai.generateText", }); + await dispatcher.onStepEnd({ + callId: "call-1", + operationId: "ai.workflowAgent.stream", + }); + expect(existingOnStepEnd).toHaveBeenCalledTimes(1); + expect(telemetryMocks.telemetry.onStepEnd).toHaveBeenCalledWith({ + callId: "call-1", + operationId: "ai.workflowAgent.stream", + }); + + await dispatcher.onAbort({ + callId: "call-1", + operationId: "ai.workflowAgent.stream", + }); + expect(existingOnAbort).toHaveBeenCalledTimes(1); + expect(telemetryMocks.telemetry.onAbort).toHaveBeenCalledWith({ + callId: "call-1", + operationId: "ai.workflowAgent.stream", + }); + await expect( dispatcher.executeTool({ callId: "call-1", @@ -180,6 +303,159 @@ describe("AISDKPlugin", () => { expect(originalExecute).toHaveBeenCalledTimes(1); }); + it("passes AI SDK v7 telemetry redaction options to Braintrust callbacks", async () => { + const existingOnStart = vi.fn(); + const dispatcher = { + onEnd: vi.fn(), + onStart: existingOnStart, + }; + + plugin.enable(); + + const channel = mockChannels.get( + "orchestrion:ai:createTelemetryDispatcher", + ); + channel?.handlers[0]?.end({ + arguments: [ + { + telemetry: { + functionId: "redacted-function", + recordInputs: false, + recordOutputs: false, + }, + }, + ], + result: dispatcher, + }); + + const startEvent = { + callId: "call-redacted", + messages: [{ role: "user", content: "hidden input" }], + operationId: "ai.generateText", + }; + await dispatcher.onStart(startEvent); + await dispatcher.onEnd({ + callId: "call-redacted", + operationId: "ai.generateText", + text: "hidden output", + }); + + expect(existingOnStart).toHaveBeenCalledWith(startEvent); + expect(telemetryMocks.telemetry.onStart).toHaveBeenCalledWith( + expect.objectContaining({ + functionId: "redacted-function", + recordInputs: false, + recordOutputs: false, + }), + ); + expect(telemetryMocks.telemetry.onEnd).toHaveBeenCalledWith( + expect.objectContaining({ + functionId: "redacted-function", + recordInputs: false, + recordOutputs: false, + }), + ); + expect(startEvent).not.toHaveProperty("recordInputs"); + }); + + it("stamps a stable unique operation key on each dispatcher", async () => { + const dispatcherA = { + executeTool: vi.fn(({ execute }) => execute()), + onAbort: vi.fn(), + onStart: vi.fn(), + }; + const dispatcherB = { + executeTool: vi.fn(({ execute }) => execute()), + onStart: vi.fn(), + }; + + plugin.enable(); + + const channel = mockChannels.get( + "orchestrion:ai:createTelemetryDispatcher", + ); + channel?.handlers[0]?.end({ + arguments: [{ telemetry: {} }], + result: dispatcherA, + }); + channel?.handlers[0]?.end({ + arguments: [{ telemetry: {} }], + result: dispatcherB, + }); + + await dispatcherA.onStart({ + callId: "workflow-agent", + operationId: "ai.workflowAgent.stream", + }); + await dispatcherB.onStart({ + callId: "workflow-agent", + operationId: "ai.workflowAgent.stream", + }); + await dispatcherA.onAbort({ + callId: "workflow-agent", + operationId: "ai.workflowAgent.stream", + }); + await dispatcherB.executeTool({ + callId: "workflow-agent", + execute: async () => "done", + toolCallId: "tool-b", + }); + + const runAStart = telemetryMocks.telemetry.onStart?.mock.calls[0]?.[0]; + const runBStart = telemetryMocks.telemetry.onStart?.mock.calls[1]?.[0]; + const runAAbort = telemetryMocks.telemetry.onAbort?.mock.calls[0]?.[0]; + const runBTool = telemetryMocks.telemetry.executeTool?.mock.calls[0]?.[0]; + + expect(runAStart?.[AI_SDK_V7_OPERATION_KEY]).toEqual(expect.any(String)); + expect(runBStart?.[AI_SDK_V7_OPERATION_KEY]).toEqual(expect.any(String)); + expect(runAStart?.[AI_SDK_V7_OPERATION_KEY]).not.toBe( + runBStart?.[AI_SDK_V7_OPERATION_KEY], + ); + expect(runAAbort?.[AI_SDK_V7_OPERATION_KEY]).toBe( + runAStart?.[AI_SDK_V7_OPERATION_KEY], + ); + expect(runBTool?.[AI_SDK_V7_OPERATION_KEY]).toBe( + runBStart?.[AI_SDK_V7_OPERATION_KEY], + ); + }); + + it("preserves existing dispatcher callback return and rejection semantics", async () => { + const rejection = new Error("user telemetry failed"); + let rejectExisting: (error: Error) => void; + const existingPromise = new Promise((_resolve, reject) => { + rejectExisting = reject; + }); + const existingOnStart = vi.fn(() => existingPromise); + telemetryMocks.telemetry.onStart = vi.fn(() => + Promise.reject(new Error("braintrust telemetry failed")), + ); + const dispatcher = { + onStart: existingOnStart, + }; + + plugin.enable(); + + const channel = mockChannels.get( + "orchestrion:ai:createTelemetryDispatcher", + ); + channel?.handlers[0]?.end({ + arguments: [{ telemetry: {} }], + result: dispatcher, + }); + + const returned = dispatcher.onStart({ + callId: "call-reject", + operationId: "ai.generateText", + }); + + expect(returned).toBe(existingPromise); + expect(existingOnStart).toHaveBeenCalledTimes(1); + expect(telemetryMocks.telemetry.onStart).toHaveBeenCalledTimes(1); + + rejectExisting!(rejection); + await expect(returned).rejects.toBe(rejection); + }); + it("patches each dispatcher once and respects telemetry opt-out", () => { const dispatcher = { onStart: vi.fn(), @@ -1121,6 +1397,159 @@ describe("AI SDK utility functions", () => { expect(result.roundtrips[0].response.data).toBe("ok"); }); + it("preserves user headers fields while omitting configured transport headers", () => { + const output = { + text: "Hello", + object: { + headers: { "x-user-data": "keep" }, + }, + content: [ + { + type: "text", + text: "Hello", + headers: { source: "tool-payload" }, + }, + ], + request: { + headers: { authorization: "secret" }, + body: "secret-request-body", + providerPayload: { + headers: { authorization: "nested-request-secret" }, + }, + }, + response: { + headers: { authorization: "secret" }, + body: "secret-body", + constructor: "unsafe", + id: "response-id", + messages: [ + { + role: "assistant", + content: [ + { + type: "provider-result", + result: { + headers: { authorization: "nested-secret" }, + id: "nested-provider-response-id", + prototype: "unsafe", + }, + }, + ], + }, + ], + }, + rawResponse: { + headers: { authorization: "secret" }, + }, + responses: [ + { + headers: { authorization: "secret" }, + id: "provider-response-id", + }, + ], + roundtrips: [ + { + request: { + headers: { authorization: "secret" }, + body: "secret-roundtrip-request-body", + providerPayload: { + headers: { authorization: "nested-roundtrip-request-secret" }, + }, + }, + response: { + headers: { authorization: "secret" }, + id: "roundtrip-response-id", + }, + }, + ], + steps: [ + { + request: { + headers: { authorization: "secret" }, + body: "secret-step-request-body", + providerPayload: { + headers: { authorization: "nested-step-request-secret" }, + }, + }, + response: { + headers: { authorization: "secret" }, + body: "secret-step-body", + id: "step-response-id", + messages: [ + { + role: "assistant", + content: [ + { + type: "provider-result", + result: { + headers: { authorization: "nested-step-secret" }, + id: "nested-step-provider-response-id", + }, + }, + ], + }, + ], + }, + output: { + headers: { "x-user-data": "keep-step" }, + }, + responses: [ + { + headers: { authorization: "secret" }, + id: "step-provider-response-id", + }, + ], + }, + ], + }; + + const result = processAISDKOutputActual( + output as any, + DEFAULT_DENY_OUTPUT_PATHS, + ) as Record; + + expect(result.object.headers).toEqual({ "x-user-data": "keep" }); + expect(result.content[0].headers).toEqual({ source: "tool-payload" }); + expect(result.steps[0].output.headers).toEqual({ + "x-user-data": "keep-step", + }); + const serializedResult = JSON.stringify(result); + expect(serializedResult).not.toContain("secret-request-body"); + expect(serializedResult).not.toContain("secret-roundtrip-request-body"); + expect(serializedResult).not.toContain("secret-step-request-body"); + expect(serializedResult).not.toContain("authorization"); + expect(result.request).not.toHaveProperty("headers"); + expect(result.request.providerPayload).not.toHaveProperty("headers"); + expect(result.response).not.toHaveProperty("headers"); + expect(result.response.body).toBe(""); + expect(result.response).not.toHaveProperty("constructor"); + expect(result.response.messages[0].content[0].result).not.toHaveProperty( + "headers", + ); + expect(result.response.messages[0].content[0].result).not.toHaveProperty( + "prototype", + ); + expect(result.rawResponse).not.toHaveProperty("headers"); + expect(result.responses[0]).not.toHaveProperty("headers"); + if (result.roundtrips) { + expect(result.roundtrips[0].request).not.toHaveProperty("headers"); + expect(result.roundtrips[0].request.providerPayload).not.toHaveProperty( + "headers", + ); + expect(result.roundtrips[0].response).not.toHaveProperty("headers"); + } + expect(result.steps[0].request).not.toHaveProperty("headers"); + expect(result.steps[0].request.providerPayload).not.toHaveProperty( + "headers", + ); + expect(result.steps[0].response).not.toHaveProperty("headers"); + expect(result.steps[0].response.body).toBe(""); + expect( + result.steps[0].response.messages[0].content[0].result, + ).not.toHaveProperty("headers"); + expect(result.steps[0].responses[0]).not.toHaveProperty("headers"); + }); + it("should handle null output", () => { const result = processAISDKOutput(null, []); expect(result).toBeNull(); diff --git a/js/src/instrumentation/plugins/ai-sdk-plugin.ts b/js/src/instrumentation/plugins/ai-sdk-plugin.ts index 83a28892e..ad5427b89 100644 --- a/js/src/instrumentation/plugins/ai-sdk-plugin.ts +++ b/js/src/instrumentation/plugins/ai-sdk-plugin.ts @@ -14,7 +14,7 @@ import { isPromiseLike, } from "../../../util/index"; import { getCurrentUnixTimestamp } from "../../util"; -import { Attachment, type Span, withCurrent } from "../../logger"; +import { Attachment, currentSpan, type Span, withCurrent } from "../../logger"; import { convertDataToBlob, getExtensionFromMediaType, @@ -22,6 +22,10 @@ import { import { normalizeAISDKLoggedOutput } from "../../wrappers/ai-sdk/normalize-logged-output"; import { serializeAISDKToolsForLogging } from "../../wrappers/ai-sdk/tool-serialization"; import { braintrustAISDKTelemetry } from "../../wrappers/ai-sdk/telemetry"; +import { + registerWorkflowAgentWrapperSpan, + unregisterWorkflowAgentWrapperSpan, +} from "../../wrappers/ai-sdk/workflow-agent-context"; import { zodToJsonSchema } from "../../zod/utils"; import { aiSDKChannels } from "./ai-sdk-channels"; import type { @@ -41,7 +45,11 @@ import type { AISDKTools, AISDKUsage, } from "../../vendor-sdk-types/ai-sdk"; -import type { AISDKV7Telemetry } from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; +import type { + AISDKV7Telemetry, + AISDKV7TelemetryOptions, +} from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; +import { BRAINTRUST_AI_SDK_V7_OPERATION_KEY as AI_SDK_V7_OPERATION_KEY } from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; export interface AISDKPluginConfig { /** @@ -58,14 +66,19 @@ export interface AISDKPluginConfig { export const DEFAULT_DENY_OUTPUT_PATHS: string[] = [ // v3 "roundtrips[].request.body", + "roundtrips[].request.headers", "roundtrips[].response.headers", "rawResponse.headers", "responseMessages", // v5 "request.body", + "request.headers", + "responses[].headers", "response.body", "response.headers", "steps[].request.body", + "steps[].request.headers", + "steps[].responses[].headers", "steps[].response.body", "steps[].response.headers", ]; @@ -78,6 +91,18 @@ const AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = Symbol.for( const RUNTIME_DENY_OUTPUT_PATHS = Symbol.for( "braintrust.ai-sdk.deny-output-paths", ); +let aiSDKV7TelemetryOperationCounter = 0; +const TRANSPORT_PAYLOAD_ROOT_PATHS = [ + "rawResponse", + "request", + "response", + "responses[]", + "roundtrips[].request", + "roundtrips[].response", + "steps[].request", + "steps[].response", + "steps[].responses[]", +]; const AI_SDK_V7_TELEMETRY_CALLBACKS = [ "onStart", @@ -87,6 +112,7 @@ const AI_SDK_V7_TELEMETRY_CALLBACKS = [ "onToolExecutionStart", "onToolExecutionEnd", "onChunk", + "onStepEnd", "onStepFinish", "onObjectStepStart", "onObjectStepEnd", @@ -95,6 +121,7 @@ const AI_SDK_V7_TELEMETRY_CALLBACKS = [ "onRerankStart", "onRerankEnd", "onEnd", + "onAbort", "onError", ] as const; @@ -114,6 +141,7 @@ const AI_SDK_V7_TELEMETRY_CALLBACKS = [ * - Agent.stream (async method returning stream) * - ToolLoopAgent.generate (async method) * - ToolLoopAgent.stream (async method returning stream) + * - WorkflowAgent.stream (async method returning stream) * * The plugin automatically extracts: * - Model and provider information @@ -328,7 +356,9 @@ export class AISDKPlugin extends BasePlugin { name: "Agent.generate", type: SpanTypeAttribute.FUNCTION, extractInput: ([params], event, span) => - prepareAISDKCallInput(params, event, span, denyOutputPaths), + prepareAISDKCallInput(params, event, span, denyOutputPaths, { + agentOwner: true, + }), extractOutput: (result, endEvent) => { finalizeAISDKChildTracing(endEvent as { [key: string]: unknown }); return processAISDKOutput( @@ -348,7 +378,9 @@ export class AISDKPlugin extends BasePlugin { name: "Agent.stream", type: SpanTypeAttribute.FUNCTION, extractInput: ([params], event, span) => - prepareAISDKCallInput(params, event, span, denyOutputPaths), + prepareAISDKCallInput(params, event, span, denyOutputPaths, { + agentOwner: true, + }), extractOutput: (result, endEvent) => processAISDKOutput( result, @@ -374,7 +406,9 @@ export class AISDKPlugin extends BasePlugin { name: "Agent.stream", type: SpanTypeAttribute.FUNCTION, extractInput: ([params], event, span) => - prepareAISDKCallInput(params, event, span, denyOutputPaths), + prepareAISDKCallInput(params, event, span, denyOutputPaths, { + agentOwner: true, + }), patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({ defaultDenyOutputPaths: denyOutputPaths, @@ -392,7 +426,9 @@ export class AISDKPlugin extends BasePlugin { name: "ToolLoopAgent.generate", type: SpanTypeAttribute.FUNCTION, extractInput: ([params], event, span) => - prepareAISDKCallInput(params, event, span, denyOutputPaths), + prepareAISDKCallInput(params, event, span, denyOutputPaths, { + agentOwner: true, + }), extractOutput: (result, endEvent) => { finalizeAISDKChildTracing(endEvent as { [key: string]: unknown }); return processAISDKOutput( @@ -412,7 +448,9 @@ export class AISDKPlugin extends BasePlugin { name: "ToolLoopAgent.stream", type: SpanTypeAttribute.FUNCTION, extractInput: ([params], event, span) => - prepareAISDKCallInput(params, event, span, denyOutputPaths), + prepareAISDKCallInput(params, event, span, denyOutputPaths, { + agentOwner: true, + }), extractOutput: (result, endEvent) => processAISDKOutput( result, @@ -431,6 +469,47 @@ export class AISDKPlugin extends BasePlugin { }), }), ); + + // WorkflowAgent.stream - async method returning stream + this.unsubscribers.push( + traceStreamingChannel(aiSDKChannels.workflowAgentStream, { + name: "WorkflowAgent.stream", + type: SpanTypeAttribute.FUNCTION, + extractInput: ([params], event, span) => + prepareAISDKWorkflowAgentStreamInput( + params, + event, + span, + denyOutputPaths, + ), + extractOutput: (result, endEvent) => { + finalizeAISDKChildTracing(endEvent as { [key: string]: unknown }); + return processAISDKOutput( + result, + resolveDenyOutputPaths(endEvent, denyOutputPaths), + ); + }, + extractMetrics: (result, _startTime, endEvent) => + extractTopLevelAISDKMetrics(result, endEvent), + aggregateChunks: aggregateAISDKChunks, + onComplete: ({ span }) => { + unregisterWorkflowAgentWrapperSpan(span); + }, + onError: ({ event, span }) => { + finalizeAISDKChildTracing(event as { [key: string]: unknown }); + unregisterWorkflowAgentWrapperSpan(span); + }, + patchResult: ({ endEvent, result, span, startTime }) => + patchAISDKStreamingResult({ + defaultDenyOutputPaths: denyOutputPaths, + endEvent, + onComplete: () => unregisterWorkflowAgentWrapperSpan(span), + result, + span, + startTime, + }), + }), + ); } } @@ -446,7 +525,11 @@ function subscribeToAISDKV7TelemetryDispatcher(): () => void { return; } - patchAISDKV7TelemetryDispatcher(event.result, telemetry); + patchAISDKV7TelemetryDispatcher( + event.result, + telemetry, + telemetryOptions, + ); }, }; @@ -460,6 +543,7 @@ function subscribeToAISDKV7TelemetryDispatcher(): () => void { function patchAISDKV7TelemetryDispatcher( dispatcher: unknown, telemetry: AISDKV7Telemetry, + telemetryOptions?: AISDKV7TelemetryOptions, ): void { if (!isObject(dispatcher)) { return; @@ -470,6 +554,61 @@ function patchAISDKV7TelemetryDispatcher( return; } dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true; + let operationKey: string | undefined; + const telemetryEventFields: AISDKV7TelemetryOptions = {}; + if (typeof telemetryOptions?.recordInputs === "boolean") { + telemetryEventFields.recordInputs = telemetryOptions.recordInputs; + } + if (typeof telemetryOptions?.recordOutputs === "boolean") { + telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs; + } + if (typeof telemetryOptions?.functionId === "string") { + telemetryEventFields.functionId = telemetryOptions.functionId; + } + + const eventWithOperationKey = (event: unknown): unknown => { + if (!isObject(event)) { + return event; + } + + const eventRecord = event as Record; + const callId = + typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown"; + operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`; + + if (Object.keys(telemetryEventFields).length > 0) { + const augmentedEvent = { + ...telemetryEventFields, + ...(event as Record), + }; + try { + Object.defineProperty(augmentedEvent, AI_SDK_V7_OPERATION_KEY, { + configurable: true, + enumerable: false, + value: operationKey, + }); + } catch { + (augmentedEvent as Record)[ + AI_SDK_V7_OPERATION_KEY + ] = operationKey; + } + return augmentedEvent; + } + + try { + Object.defineProperty(eventRecord, AI_SDK_V7_OPERATION_KEY, { + configurable: true, + enumerable: false, + value: operationKey, + }); + return event; + } catch { + return { + ...(event as Record), + [AI_SDK_V7_OPERATION_KEY]: operationKey, + }; + } + }; for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) { const braintrustCallback = telemetry[key]; @@ -483,12 +622,18 @@ function patchAISDKV7TelemetryDispatcher( typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : undefined; - const braintrustResult = braintrustCallback.call(telemetry, event as any); - const pending = [existingResult, braintrustResult].filter(isPromiseLike); - - if (pending.length > 0) { - return Promise.allSettled(pending).then(() => undefined); + try { + const braintrustResult = braintrustCallback.call( + telemetry, + eventWithOperationKey(event) as any, + ); + if (isPromiseLike(braintrustResult)) { + void Promise.resolve(braintrustResult).catch(() => undefined); + } + } catch { + // Keep Braintrust telemetry isolated from the user's callback path. } + return existingResult; }; } @@ -505,6 +650,7 @@ function patchAISDKV7TelemetryDispatcher( }) => braintrustExecuteTool.call(telemetry, { ...args, + ...(operationKey ? { [AI_SDK_V7_OPERATION_KEY]: operationKey } : {}), execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) @@ -546,7 +692,7 @@ function resolveDenyOutputPaths( return defaultDenyOutputPaths; } -interface ProcessCallInputSyncResult { +export interface ProcessCallInputSyncResult { input: AISDKCallParams; outputPromise?: Promise<{ output: { @@ -684,6 +830,8 @@ const processInputAttachmentsSync = ( if (!input) return { input }; const processed: AISDKCallParams = { ...input }; + delete processed.headers; + delete processed.experimental_output; if (input.messages && Array.isArray(input.messages)) { processed.messages = input.messages.map(processMessage); @@ -735,14 +883,10 @@ const processInputAttachmentsSync = ( } } - if ( - "prepareCall" in processed && - typeof processed.prepareCall === "function" - ) { - processed.prepareCall = "[Function]"; - } - - return { input: processed, outputPromise }; + return { + input: sanitizeAISDKCallInputValue(processed) as AISDKCallParams, + outputPromise, + }; }; const processMessage = (message: any): any => { @@ -950,6 +1094,26 @@ export function processAISDKCallInput( return processInputAttachmentsSync(params); } +export function processAISDKWorkflowAgentCallInput( + params: AISDKCallParams, +): ProcessCallInputSyncResult { + const processed = processAISDKCallInput(params); + return { + ...processed, + input: extractWorkflowAgentInput(processed.input), + }; +} + +export function processAISDKWorkflowAgentModelCallInput( + params: AISDKCallParams, +): ProcessCallInputSyncResult { + const processed = processAISDKCallInput(params); + return { + ...processed, + input: extractWorkflowAgentModelInput(processed.input), + }; +} + function prepareAISDKCallInput( params: AISDKCallParams, event: { @@ -960,6 +1124,7 @@ function prepareAISDKCallInput( }, span: Span, defaultDenyOutputPaths: string[], + childTracingOptions: AISDKChildTracingOptions = {}, ): { input: unknown; metadata: Record; @@ -987,6 +1152,43 @@ function prepareAISDKCallInput( span, defaultDenyOutputPaths, event.aiSDK, + childTracingOptions, + ); + event.modelWrapped = childTracing.modelWrapped; + if (childTracing.cleanup) { + event.__braintrust_ai_sdk_cleanup = childTracing.cleanup; + } + + return { + input, + metadata, + }; +} + +function prepareAISDKWorkflowAgentStreamInput( + params: AISDKCallParams, + event: { + aiSDK?: AISDK; + denyOutputPaths?: string[]; + self?: unknown; + [key: string]: unknown; + }, + span: Span, + defaultDenyOutputPaths: string[], +): { + input: unknown; + metadata: Record; +} { + registerWorkflowAgentWrapperSpan(span); + const { input } = processAISDKWorkflowAgentCallInput(params); + const metadata = extractWorkflowMetadataFromCallParams(params, event.self); + const childTracing = prepareAISDKChildTracing( + params, + event.self, + span, + defaultDenyOutputPaths, + event.aiSDK, + { agentOwner: true, workflowAgent: true }, ); event.modelWrapped = childTracing.modelWrapped; if (childTracing.cleanup) { @@ -1053,6 +1255,10 @@ function hasModelChildTracing(event?: { [key: string]: unknown }): boolean { ); } +function serializeToolExecutionInput(args: unknown[]): unknown { + return args.length > 0 ? args[0] : args; +} + export function createAISDKIntegrationMetadata(): Record { return { braintrust: { @@ -1076,6 +1282,19 @@ function resolveModelFromSelf(self?: unknown): AISDKModel | undefined { : undefined; } +function resolveToolsFromSelf(self?: unknown): AISDKTools | undefined { + if (!self || typeof self !== "object") { + return undefined; + } + + const selfRecord = self as { + settings?: { tools?: AISDKTools }; + tools?: AISDKTools; + }; + + return selfRecord.tools ?? selfRecord.settings?.tools; +} + function extractBaseMetadata( model: AISDKModel | undefined, self?: unknown, @@ -1098,13 +1317,249 @@ function extractMetadataFromCallParams( self?: unknown, ): Record { const metadata = extractBaseMetadata(params.model, self); - const tools = serializeAISDKToolsForLogging(params.tools); + const tools = serializeAISDKToolsForLogging( + params.tools ?? resolveToolsFromSelf(self), + ); if (tools) { metadata.tools = tools; } return metadata; } +export function extractWorkflowMetadataFromCallParams( + params: AISDKCallParams, + self?: unknown, +): Record { + const metadata = extractMetadataFromCallParams(params, self); + const options = extractAISDKCallOptionsForMetadata(params); + if (Object.keys(options).length > 0) { + metadata.options = options; + } + return metadata; +} + +function extractWorkflowAgentInput(params: AISDKCallParams): AISDKCallParams { + const input: AISDKCallParams = {}; + if (params.instructions !== undefined) { + input.instructions = params.instructions; + } + if (params.system !== undefined) { + input.system = params.system; + } + + if (Array.isArray(params.messages)) { + return { ...input, messages: params.messages }; + } + + if (typeof params.prompt === "string") { + return { ...input, prompt: params.prompt }; + } + + if (Array.isArray(params.prompt)) { + return { ...input, prompt: params.prompt }; + } + + return input; +} + +function extractWorkflowAgentModelInput( + params: AISDKCallParams, +): AISDKCallParams { + const input: AISDKCallParams = {}; + if (params.instructions !== undefined) { + input.instructions = params.instructions; + } + if (params.system !== undefined) { + input.system = params.system; + } + + if (Array.isArray(params.messages)) { + return { ...input, messages: params.messages }; + } + + if (typeof params.prompt === "string") { + return { ...input, prompt: params.prompt }; + } + + if (Array.isArray(params.prompt)) { + return { ...input, messages: params.prompt }; + } + + return input; +} + +function sanitizeAISDKCallInputValue(value: unknown, depth = 0): unknown { + if (value === undefined || typeof value === "function") { + return undefined; + } + + if (value === null || typeof value !== "object") { + return value; + } + + if (isPromiseLike(value)) { + return "[Promise]"; + } + + if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) { + return "[AbortSignal]"; + } + + if (depth >= 8) { + return "[Object]"; + } + + if (Array.isArray(value)) { + return value + .map((item) => sanitizeAISDKCallInputValue(item, depth + 1)) + .filter((item) => item !== undefined); + } + + if (!isObject(value)) { + return value; + } + + const prototype = Object.getPrototypeOf(value); + if (prototype !== Object.prototype && prototype !== null) { + return value; + } + + const sanitized: Record = {}; + for (const [key, nested] of Object.entries(value)) { + if ( + key === "__proto__" || + key === "constructor" || + key === "prototype" || + key.toLowerCase() === "headers" + ) { + continue; + } + + const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1); + if (sanitizedNested !== undefined) { + sanitized[key] = sanitizedNested; + } + } + + return sanitized; +} + +function extractAISDKCallOptionsForMetadata( + params: AISDKCallParams, +): Record { + const options: Record = {}; + const inputOrTopLevelKeys = new Set([ + "model", + "instructions", + "messages", + "prompt", + "system", + "tools", + "headers", + "abortSignal", + "signal", + "experimental_output", + ]); + + for (const [key, value] of Object.entries(params)) { + if ( + inputOrTopLevelKeys.has(key) || + key === "__proto__" || + key === "constructor" || + key === "prototype" || + (/^on[A-Z]/.test(key) && typeof value === "function") + ) { + continue; + } + + const sanitized = sanitizeAISDKMetadataValue(value); + if (sanitized !== undefined) { + options[key] = sanitized; + } + } + + return options; +} + +function sanitizeAISDKMetadataValue(value: unknown, depth = 0): unknown { + if (value === undefined) { + return undefined; + } + + if (typeof value === "function") { + return "[Function]"; + } + + if (value === null || typeof value !== "object") { + return value; + } + + if (isPromiseLike(value)) { + return "[Promise]"; + } + + if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) { + return "[AbortSignal]"; + } + + if (depth >= 8) { + return "[Object]"; + } + + if (Array.isArray(value)) { + return value + .map((item) => sanitizeAISDKMetadataValue(item, depth + 1)) + .filter((item) => item !== undefined); + } + + if (!isObject(value)) { + return value; + } + + const sanitized: Record = {}; + for (const [key, nested] of Object.entries(value)) { + if ( + key === "__proto__" || + key === "constructor" || + key === "prototype" || + key.toLowerCase() === "headers" + ) { + continue; + } + + const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1); + if (sanitizedNested !== undefined) { + sanitized[key] = sanitizedNested; + } + } + + return sanitized; +} + +function buildAISDKModelStartEvent( + callOptions: AISDKCallParams, + baseMetadata: Record, + options: { workflowAgent?: boolean }, +): { + input: unknown; + metadata: Record; +} { + if (!options.workflowAgent) { + return { + input: processAISDKCallInput(callOptions).input, + metadata: baseMetadata, + }; + } + + return { + input: processAISDKWorkflowAgentModelCallInput(callOptions).input, + metadata: { + ...baseMetadata, + ...extractWorkflowMetadataFromCallParams(callOptions), + }, + }; +} + function extractMetadataFromEmbedParams( params: AISDKEmbedParams, self?: unknown, @@ -1125,7 +1580,134 @@ function extractMetadataFromRerankParams( metadata.document_count = params.documents.length; } - return metadata; + return metadata; +} + +type AISDKChildTracingOptions = { + agentOwner?: boolean; + workflowAgent?: boolean; +}; + +type AISDKModelPatchEntry = { + activeSpanIds: Set; + baseMetadata: Record; + childTracingOptions: AISDKChildTracingOptions; + denyOutputPaths: string[]; + openSpans: Set; + parentSpan: Span; +}; + +type AISDKModelPatchState = { + entries: AISDKModelPatchEntry[]; + originalDoGenerate: NonNullable; + originalDoStream?: AISDKLanguageModel["doStream"]; +}; + +type AISDKToolPatchEntry = { + activeSpanIds: Set; + childTracingOptions: AISDKChildTracingOptions; + name: string; + parentSpan: Span; +}; + +type AISDKToolPatchState = { + entries: AISDKToolPatchEntry[]; + originalExecute: (...args: unknown[]) => unknown; +}; + +function activeAISDKChildPatchEntry< + TEntry extends { activeSpanIds: Set; parentSpan: Span }, +>(entries: TEntry[]): TEntry | undefined { + const activeSpan = currentSpan(); + const activeSpanId = activeSpan.spanId; + if (activeSpanId) { + for (let index = entries.length - 1; index >= 0; index -= 1) { + const entry = entries[index]; + if (entry?.activeSpanIds.has(activeSpanId)) { + return entry; + } + } + } + + const activeParentSpanIds = activeSpan.spanParents ?? []; + for (let index = entries.length - 1; index >= 0; index -= 1) { + const entry = entries[index]; + if ( + entry?.parentSpan.spanId && + activeParentSpanIds.includes(entry.parentSpan.spanId) + ) { + return entry; + } + } + + for (let index = entries.length - 1; index >= 0; index -= 1) { + const entry = entries[index]; + if (entry?.parentSpan.spanId === activeSpanId) { + return entry; + } + } + + return entries[entries.length - 1]; +} + +function attachNestedAISDKChildPatchEntry< + TEntry extends { activeSpanIds: Set; parentSpan: Span }, +>(entries: TEntry[], nestedSpan: Span, cleanup: Array<() => void>): boolean { + const activeSpanId = currentSpan().spanId; + if (!activeSpanId || activeSpanId === nestedSpan.spanId) { + return false; + } + + for (let index = entries.length - 1; index >= 0; index -= 1) { + const entry = entries[index]; + if ( + entry?.parentSpan.spanId === activeSpanId || + entry?.activeSpanIds.has(activeSpanId) + ) { + entry.activeSpanIds.add(nestedSpan.spanId); + cleanup.push(() => { + entry.activeSpanIds.delete(nestedSpan.spanId); + }); + return true; + } + } + + return false; +} + +function shadowActiveAISDKChildPatchEntry< + TEntry extends { activeSpanIds: Set; parentSpan: Span }, +>( + entries: TEntry[], + entry: TEntry, + nestedSpan: Span, + cleanup: Array<() => void>, +) { + const activeSpanId = currentSpan().spanId; + if (!activeSpanId || activeSpanId === nestedSpan.spanId) { + return; + } + + for (let index = entries.length - 1; index >= 0; index -= 1) { + const existingEntry = entries[index]; + if ( + existingEntry?.parentSpan.spanId === activeSpanId || + existingEntry?.activeSpanIds.has(activeSpanId) + ) { + entry.activeSpanIds.add(activeSpanId); + cleanup.push(() => { + entry.activeSpanIds.delete(activeSpanId); + }); + return; + } + } +} + +function closeOpenAISDKModelPatchSpans(entry: AISDKModelPatchEntry): void { + for (const span of entry.openSpans) { + span.end(); + } + entry.openSpans.clear(); } function prepareAISDKChildTracing( @@ -1134,6 +1716,7 @@ function prepareAISDKChildTracing( parentSpan: Span, denyOutputPaths: string[], aiSDK?: AISDK, + childTracingOptions: AISDKChildTracingOptions = {}, ): { cleanup?: () => void; modelWrapped: boolean; @@ -1150,22 +1733,80 @@ function prepareAISDKChildTracing( if ( !resolvedModel || typeof resolvedModel !== "object" || - typeof resolvedModel.doGenerate !== "function" || - (resolvedModel as { [AUTO_PATCHED_MODEL]?: boolean })[AUTO_PATCHED_MODEL] + typeof resolvedModel.doGenerate !== "function" ) { return resolvedModel; } const existingWrappedModel = patchedModels.get(resolvedModel); if (existingWrappedModel) { + modelWrapped = true; return existingWrappedModel; } modelWrapped = true; + const modelRecord = resolvedModel as AISDKLanguageModel & { + [AUTO_PATCHED_MODEL]?: AISDKModelPatchState; + }; + const entry: AISDKModelPatchEntry = { + activeSpanIds: new Set([parentSpan.spanId]), + baseMetadata: buildAISDKChildMetadata(resolvedModel), + childTracingOptions, + denyOutputPaths, + openSpans: new Set(), + parentSpan, + }; + const cleanupModelEntry = ( + state: AISDKModelPatchState, + patchedModel: AISDKLanguageModel & { + [AUTO_PATCHED_MODEL]?: AISDKModelPatchState; + }, + ) => { + closeOpenAISDKModelPatchSpans(entry); + const index = state.entries.indexOf(entry); + if (index >= 0) { + state.entries.splice(index, 1); + } + if (state.entries.length > 0) { + return; + } + patchedModel.doGenerate = state.originalDoGenerate; + patchedModel.doStream = state.originalDoStream; + delete patchedModel[AUTO_PATCHED_MODEL]; + }; + const existingState = modelRecord[AUTO_PATCHED_MODEL]; + if (existingState) { + patchedModels.set(resolvedModel, resolvedModel); + if ( + childTracingOptions.agentOwner && + attachNestedAISDKChildPatchEntry( + existingState.entries, + parentSpan, + cleanup, + ) + ) { + return resolvedModel; + } + + if (!childTracingOptions.agentOwner) { + shadowActiveAISDKChildPatchEntry( + existingState.entries, + entry, + parentSpan, + cleanup, + ); + } + + existingState.entries.push(entry); + cleanup.push(() => { + cleanupModelEntry(existingState, modelRecord); + }); + return resolvedModel; + } + const originalDoGenerate = resolvedModel.doGenerate; const originalDoStream = resolvedModel.doStream; - const baseMetadata = buildAISDKChildMetadata(resolvedModel); const wrappedModel = Object.create( Object.getPrototypeOf(resolvedModel), ) as AISDKLanguageModel; @@ -1173,70 +1814,105 @@ function prepareAISDKChildTracing( wrappedModel, Object.getOwnPropertyDescriptors(resolvedModel), ); + const wrappedModelRecord = wrappedModel as AISDKLanguageModel & { + [AUTO_PATCHED_MODEL]?: AISDKModelPatchState; + }; + const state: AISDKModelPatchState = { + entries: [entry], + originalDoGenerate, + originalDoStream, + }; Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, { configurable: true, - value: true, + value: state, }); wrappedModel.doGenerate = async function doGeneratePatched( - options: AISDKCallParams, + callOptions: AISDKCallParams, ) { - return parentSpan.traced( + const activeEntry = activeAISDKChildPatchEntry(state.entries); + if (!activeEntry) { + return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]); + } + + closeOpenAISDKModelPatchSpans(activeEntry); + return activeEntry.parentSpan.traced( async (span) => { - const result = await Reflect.apply( - originalDoGenerate, - resolvedModel, - [options], - ); + activeEntry.openSpans.add(span); + try { + const result = await Reflect.apply( + originalDoGenerate, + resolvedModel, + [callOptions], + ); - const output = processAISDKOutput(result, denyOutputPaths); - const metrics = extractTokenMetrics(result); - const metadataPayload = buildResolvedMetadataPayload(result); - const missingUsageMetadata = buildMissingUsageMetadata( - output, - metrics, - "ai_sdk_result_missing_usage", - ); + const output = processAISDKOutput( + result, + activeEntry.denyOutputPaths, + ); + const metrics = extractTokenMetrics(result); + const metadataPayload = buildResolvedMetadataPayload(result); + const missingUsageMetadata = buildMissingUsageMetadata( + output, + metrics, + "ai_sdk_result_missing_usage", + ); - span.log({ - output, - metrics, - ...mergeMetadataPayload(metadataPayload, missingUsageMetadata), - }); + span.log({ + output, + metrics, + ...mergeMetadataPayload(metadataPayload, missingUsageMetadata), + }); - return result; + return result; + } finally { + activeEntry.openSpans.delete(span); + } }, { name: "doGenerate", spanAttributes: { type: SpanTypeAttribute.LLM, }, - event: { - input: processAISDKCallInput(options).input, - metadata: baseMetadata, - }, + event: buildAISDKModelStartEvent( + callOptions, + activeEntry.baseMetadata, + { + workflowAgent: activeEntry.childTracingOptions.workflowAgent, + }, + ), }, ); }; if (originalDoStream) { wrappedModel.doStream = async function doStreamPatched( - options: AISDKCallParams, + callOptions: AISDKCallParams, ) { - const span = parentSpan.startSpan({ + const activeEntry = activeAISDKChildPatchEntry(state.entries); + if (!activeEntry) { + return Reflect.apply(originalDoStream, resolvedModel, [callOptions]); + } + + closeOpenAISDKModelPatchSpans(activeEntry); + const span = activeEntry.parentSpan.startSpan({ name: "doStream", spanAttributes: { type: SpanTypeAttribute.LLM, }, - event: { - input: processAISDKCallInput(options).input, - metadata: baseMetadata, - }, + event: buildAISDKModelStartEvent( + callOptions, + activeEntry.baseMetadata, + { + workflowAgent: activeEntry.childTracingOptions.workflowAgent, + }, + ), }); + activeEntry.openSpans.add(span); const streamStartTime = getCurrentUnixTimestamp(); const result = await withCurrent(span, () => - Reflect.apply(originalDoStream, resolvedModel, [options]), + Reflect.apply(originalDoStream, resolvedModel, [callOptions]), ); // firstChunkTime !== streamStartTime because the first few chunks may be actual bookkeeping stuff for the SDK // instead of actual LLM output that can be streamed to users. @@ -1262,7 +1938,10 @@ function prepareAISDKChildTracing( } const metrics = extractTokenMetrics(output as AISDKResult); - if (firstChunkTime !== undefined) { + if ( + firstChunkTime !== undefined && + !activeEntry.childTracingOptions.workflowAgent + ) { metrics.time_to_first_token = Math.max( firstChunkTime - streamStartTime, 1e-6, @@ -1281,10 +1960,14 @@ function prepareAISDKChildTracing( ); span.log({ - output: processAISDKOutput(output as AISDKResult, denyOutputPaths), + output: processAISDKOutput( + output as AISDKResult, + activeEntry.denyOutputPaths, + ), metrics, ...mergeMetadataPayload(metadataPayload, missingUsageMetadata), }); + activeEntry.openSpans.delete(span); span.end(); streamSpanEnded = true; }; @@ -1355,7 +2038,12 @@ function prepareAISDKChildTracing( }; } + cleanup.push(() => { + cleanupModelEntry(state, wrappedModelRecord); + }); + patchedModels.set(resolvedModel, wrappedModel); + patchedModels.set(wrappedModel, wrappedModel); return wrappedModel; }; @@ -1365,27 +2053,84 @@ function prepareAISDKChildTracing( typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || - patchedTools.has(tool) || - (tool as { [AUTO_PATCHED_TOOL]?: boolean })[AUTO_PATCHED_TOOL] + patchedTools.has(tool) ) { return; } patchedTools.add(tool); - (tool as { [AUTO_PATCHED_TOOL]?: boolean })[AUTO_PATCHED_TOOL] = true; - const originalExecute = tool.execute; + const toolRecord = tool as AISDKTool & { + [AUTO_PATCHED_TOOL]?: AISDKToolPatchState; + execute: (...args: unknown[]) => unknown; + }; + const entry: AISDKToolPatchEntry = { + activeSpanIds: new Set([parentSpan.spanId]), + childTracingOptions, + name, + parentSpan, + }; + const cleanupToolEntry = (state: AISDKToolPatchState) => { + const index = state.entries.indexOf(entry); + if (index >= 0) { + state.entries.splice(index, 1); + } + if (state.entries.length > 0) { + return; + } + tool.execute = state.originalExecute; + delete toolRecord[AUTO_PATCHED_TOOL]; + }; + const existingState = toolRecord[AUTO_PATCHED_TOOL]; + if (existingState) { + if ( + childTracingOptions.agentOwner && + attachNestedAISDKChildPatchEntry( + existingState.entries, + parentSpan, + cleanup, + ) + ) { + return; + } + + if (!childTracingOptions.agentOwner) { + shadowActiveAISDKChildPatchEntry( + existingState.entries, + entry, + parentSpan, + cleanup, + ); + } + + existingState.entries.push(entry); + cleanup.push(() => { + cleanupToolEntry(existingState); + }); + return; + } + + const originalExecute = toolRecord.execute; + const state: AISDKToolPatchState = { + entries: [entry], + originalExecute, + }; + toolRecord[AUTO_PATCHED_TOOL] = state; tool.execute = function executePatched(...args: unknown[]) { + const activeEntry = activeAISDKChildPatchEntry(state.entries); const result = Reflect.apply(originalExecute, this, args); + if (!activeEntry) { + return result; + } if (isAsyncGenerator(result)) { return (async function* () { - const span = parentSpan.startSpan({ - name, + const span = activeEntry.parentSpan.startSpan({ + name: activeEntry.name, spanAttributes: { type: SpanTypeAttribute.TOOL, }, }); - span.log({ input: args[0] }); + span.log({ input: serializeToolExecutionInput(args) }); try { let lastValue: unknown; @@ -1403,15 +2148,15 @@ function prepareAISDKChildTracing( })(); } - return parentSpan.traced( + return activeEntry.parentSpan.traced( async (span) => { - span.log({ input: args[0] }); + span.log({ input: serializeToolExecutionInput(args) }); const awaitedResult = await result; span.log({ output: awaitedResult }); return awaitedResult; }, { - name, + name: activeEntry.name, spanAttributes: { type: SpanTypeAttribute.TOOL, }, @@ -1420,8 +2165,7 @@ function prepareAISDKChildTracing( }; cleanup.push(() => { - tool.execute = originalExecute; - delete (tool as { [AUTO_PATCHED_TOOL]?: boolean })[AUTO_PATCHED_TOOL]; + cleanupToolEntry(state); }); }; @@ -1460,6 +2204,7 @@ function prepareAISDKChildTracing( if (self && typeof self === "object") { const selfRecord = self as { model?: AISDKModel; + tools?: AISDKTools; settings?: { model?: AISDKModel; tools?: AISDKTools }; }; @@ -1474,6 +2219,10 @@ function prepareAISDKChildTracing( } } + if (selfRecord.tools !== undefined) { + patchTools(selfRecord.tools); + } + if (selfRecord.settings && typeof selfRecord.settings === "object") { if (selfRecord.settings.model !== undefined) { const originalSettingsModel = selfRecord.settings.model; @@ -1651,11 +2400,19 @@ function isAISDKContentAsyncIterableChunk(chunk: unknown): boolean { function patchAISDKStreamingResult(args: { defaultDenyOutputPaths: string[]; endEvent: { denyOutputPaths?: string[]; [key: string]: unknown }; + onComplete?: () => void; result: AISDKResult; span: Span; startTime: number; }): boolean { - const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args; + const { + defaultDenyOutputPaths, + endEvent, + onComplete, + result, + span, + startTime, + } = args; if (!result || typeof result !== "object") { return false; @@ -1663,11 +2420,151 @@ function patchAISDKStreamingResult(args: { const resultRecord = result as Record; attachKnownResultPromiseHandlers(resultRecord); + let finalized = false; + const finalize = () => { + if (finalized) { + return; + } + finalized = true; + finalizeAISDKChildTracing(endEvent); + span.end(); + onComplete?.(); + }; + let outputLogged = false; + const logStreamingOutput = async (firstChunkTime?: number) => { + if (outputLogged) { + return; + } + outputLogged = true; + + try { + const metrics = extractTopLevelAISDKMetrics(result, endEvent); + if ( + metrics.time_to_first_token === undefined && + firstChunkTime !== undefined + ) { + metrics.time_to_first_token = firstChunkTime - startTime; + } + + const output = await processAISDKStreamingOutput( + result, + resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths), + ); + const metadata = buildResolvedMetadataPayload(result).metadata; + + span.log({ + output, + ...(metadata ? { metadata } : {}), + metrics, + }); + } catch (error) { + span.log({ error: toLoggedError(error) }); + } finally { + finalize(); + } + }; + const createAsyncIterableHooks = () => { + let firstChunkTime: number | undefined; + + return { + onChunk: (chunk: unknown) => { + if ( + firstChunkTime === undefined && + isAISDKContentAsyncIterableChunk(chunk) + ) { + firstChunkTime = getCurrentUnixTimestamp(); + } + }, + onComplete: async () => { + await logStreamingOutput(firstChunkTime); + }, + onError: (error: Error) => { + if (!outputLogged) { + outputLogged = true; + span.log({ + error: error.message, + }); + } + finalize(); + }, + onCancel: finalize, + }; + }; + const patchAsyncIterable = (stream: AsyncIterable) => + isReadableStreamLike(stream) + ? createPatchedReadableStream(stream, createAsyncIterableHooks()) + : createPatchedAsyncIterable(stream, createAsyncIterableHooks()); + const patchAsyncIterableField = (field: string): boolean => { + let descriptorOwner: object | null = resultRecord; + let descriptor: PropertyDescriptor | undefined; + while (descriptorOwner) { + descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field); + if (descriptor) { + break; + } + descriptorOwner = Object.getPrototypeOf(descriptorOwner); + } + + if ( + !descriptor || + (descriptorOwner === resultRecord && !descriptor.configurable) + ) { + return false; + } + + if ("value" in descriptor) { + if (!isAsyncIterable(descriptor.value)) { + return false; + } + + try { + Object.defineProperty(resultRecord, field, { + configurable: + descriptorOwner === resultRecord ? descriptor.configurable : true, + enumerable: descriptor.enumerable, + value: patchAsyncIterable(descriptor.value), + writable: descriptor.writable, + }); + return true; + } catch { + return false; + } + } + + if (typeof descriptor.get !== "function") { + return false; + } + + const originalGet = descriptor.get; + const originalSet = descriptor.set; + try { + Object.defineProperty(resultRecord, field, { + configurable: + descriptorOwner === resultRecord ? descriptor.configurable : true, + enumerable: descriptor.enumerable, + get() { + const stream = originalGet.call(this); + return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream; + }, + ...(originalSet + ? { + set(value: unknown) { + originalSet.call(this, value); + }, + } + : {}), + }); + return true; + } catch { + return false; + } + }; + let patched = false; if (isReadableStreamLike(resultRecord.baseStream)) { let firstChunkTime: number | undefined; - const wrappedBaseStream = resultRecord.baseStream.pipeThrough( + const transformedBaseStream = resultRecord.baseStream.pipeThrough( new TransformStream({ transform(chunk, controller) { if ( @@ -1679,31 +2576,35 @@ function patchAISDKStreamingResult(args: { controller.enqueue(chunk); }, async flush() { - const metrics = extractTopLevelAISDKMetrics(result, endEvent); - if ( - metrics.time_to_first_token === undefined && - firstChunkTime !== undefined - ) { - metrics.time_to_first_token = firstChunkTime - startTime; - } - - const output = await processAISDKStreamingOutput( - result, - resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths), - ); - const metadata = buildResolvedMetadataPayload(result).metadata; - - span.log({ - output, - ...(metadata ? { metadata } : {}), - metrics, - }); - - finalizeAISDKChildTracing(endEvent); - span.end(); + await logStreamingOutput(firstChunkTime); }, }), ); + const reader = transformedBaseStream.getReader(); + const wrappedBaseStream = new ReadableStream({ + async pull(controller) { + try { + const { done, value } = await reader.read(); + if (done) { + controller.close(); + return; + } + + controller.enqueue(value); + } catch (error) { + span.log({ error: toLoggedError(error) }); + finalize(); + controller.error(error); + } + }, + async cancel(reason) { + try { + finalize(); + } finally { + await reader.cancel(reason); + } + }, + }); Object.defineProperty(resultRecord, "baseStream", { configurable: true, @@ -1712,69 +2613,19 @@ function patchAISDKStreamingResult(args: { writable: true, }); - return true; + patched = true; } - const streamField = findAsyncIterableField(resultRecord, [ + for (const field of [ "partialObjectStream", "textStream", "fullStream", "stream", - ]); - if (!streamField) { - return false; + ]) { + patched = patchAsyncIterableField(field) || patched; } - let firstChunkTime: number | undefined; - const wrappedStream = createPatchedAsyncIterable(streamField.stream, { - onChunk: (chunk) => { - if ( - firstChunkTime === undefined && - isAISDKContentAsyncIterableChunk(chunk) - ) { - firstChunkTime = getCurrentUnixTimestamp(); - } - }, - onComplete: async () => { - const metrics = extractTopLevelAISDKMetrics(result, endEvent); - if ( - metrics.time_to_first_token === undefined && - firstChunkTime !== undefined - ) { - metrics.time_to_first_token = firstChunkTime - startTime; - } - - const output = await processAISDKStreamingOutput( - result, - resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths), - ); - const metadata = buildResolvedMetadataPayload(result).metadata; - - span.log({ - output, - ...(metadata ? { metadata } : {}), - metrics, - }); - finalizeAISDKChildTracing(endEvent); - span.end(); - }, - onError: (error) => { - span.log({ - error: error.message, - }); - finalizeAISDKChildTracing(endEvent); - span.end(); - }, - }); - - Object.defineProperty(resultRecord, streamField.field, { - configurable: true, - enumerable: true, - value: wrappedStream, - writable: true, - }); - - return true; + return patched; } function attachKnownResultPromiseHandlers( @@ -1810,37 +2661,79 @@ function attachKnownResultPromiseHandlers( } } -function isReadableStreamLike(value: unknown): value is { +type ReadableStreamLike = { + cancel?: (reason?: unknown) => Promise; + getReader(): ReadableStreamDefaultReader; pipeThrough(transform: TransformStream): ReadableStream; -} { +}; + +function isReadableStreamLike(value: unknown): value is ReadableStreamLike { return ( value != null && typeof value === "object" && + typeof (value as { getReader?: unknown }).getReader === "function" && typeof (value as { pipeThrough?: unknown }).pipeThrough === "function" ); } -function findAsyncIterableField( - result: Record, - candidateFields: string[], -): { field: string; stream: AsyncIterable } | null { - for (const field of candidateFields) { - try { - const stream = result[field]; - if (isAsyncIterable(stream)) { - return { field, stream }; +function createPatchedReadableStream( + stream: ReadableStreamLike, + hooks: { + onCancel?: () => void | Promise; + onChunk: (chunk: unknown) => void; + onComplete: () => Promise; + onError: (error: Error) => void; + }, +): ReadableStream { + let reader: ReadableStreamDefaultReader | undefined; + let completed = false; + + return new ReadableStream({ + async pull(controller) { + reader ??= stream.getReader(); + + try { + const { done, value } = await reader.read(); + if (done) { + completed = true; + await hooks.onComplete(); + controller.close(); + return; + } + + hooks.onChunk(value); + controller.enqueue(value); + } catch (error) { + completed = true; + hooks.onError( + error instanceof Error ? error : new Error(String(error)), + ); + controller.error(error); + } + }, + async cancel(reason) { + if (!completed) { + completed = true; + try { + await hooks.onCancel?.(); + } catch { + // Ignore cleanup errors so stream cancellation keeps its behavior. + } } - } catch { - // Ignore getter failures. - } - } - return null; + if (reader) { + await reader.cancel(reason); + } else if (stream.cancel) { + await stream.cancel(reason); + } + }, + }); } function createPatchedAsyncIterable( stream: AsyncIterable, hooks: { + onCancel?: () => void | Promise; onChunk: (chunk: unknown) => void; onComplete: () => Promise; onError: (error: Error) => void; @@ -1848,17 +2741,28 @@ function createPatchedAsyncIterable( ): AsyncIterable { return { async *[Symbol.asyncIterator]() { + let completed = false; try { for await (const chunk of stream) { hooks.onChunk(chunk); yield chunk; } + completed = true; await hooks.onComplete(); } catch (error) { + completed = true; hooks.onError( error instanceof Error ? error : new Error(String(error)), ); throw error; + } finally { + if (!completed) { + try { + await hooks.onCancel?.(); + } catch { + // Ignore cleanup errors so stream cancellation keeps its behavior. + } + } } }, }; @@ -2067,9 +2971,65 @@ export function processAISDKOutput( if (!output) return output; const merged = extractSerializableOutputFields(output); + const deleteOutputPaths = denyOutputPaths.filter((path) => + path.toLowerCase().endsWith("headers"), + ); + const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths); + + // Transport payloads can contain nested provider request/response headers; keep + // user/model/tool payload fields named "headers" outside these roots intact. + for (const path of TRANSPORT_PAYLOAD_ROOT_PATHS) { + const stack: Array<{ + obj: Record | unknown[] | undefined; + keys: (string | number)[]; + }> = [{ obj: sanitized, keys: parsePath(path) }]; + + while (stack.length > 0) { + const entry = stack.pop(); + if (!entry || entry.keys.length === 0) { + continue; + } + + const firstKey = entry.keys[0]; + const remainingKeys = entry.keys.slice(1); + + if (firstKey === "[]") { + if (Array.isArray(entry.obj)) { + for (const item of entry.obj) { + stack.push({ + obj: item as Record | unknown[] | undefined, + keys: remainingKeys, + }); + } + } + continue; + } + + if ( + !entry.obj || + typeof entry.obj !== "object" || + !(firstKey in entry.obj) + ) { + continue; + } + + const record = entry.obj as Record; + if (remainingKeys.length === 0) { + record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]); + continue; + } + + stack.push({ + obj: record[firstKey] as + | Record + | unknown[] + | undefined, + keys: remainingKeys, + }); + } + } - // Apply omit to remove unwanted paths - return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths)); + return normalizeAISDKLoggedOutput(sanitized); } export function processAISDKEmbeddingOutput( @@ -2374,7 +3334,9 @@ function extractGetterValues( const getterNames = [ "content", + "messages", "text", + "output", "object", "value", "values", @@ -2423,7 +3385,9 @@ function extractSerializableOutputFields( ): Record { const serialized: Record = {}; const directFieldNames = [ + "messages", "steps", + "output", "request", "responseMessages", "warnings", @@ -2686,6 +3650,7 @@ function parsePath(path: string): (string | number)[] { function omitAtPath( obj: Record | unknown[] | undefined, keys: (string | number)[], + deleteLeaf = false, ): void { if (keys.length === 0) return; @@ -2699,13 +3664,18 @@ function omitAtPath( omitAtPath( item as Record | unknown[] | undefined, remainingKeys, + deleteLeaf, ); } }); } } else if (remainingKeys.length === 0) { if (obj && typeof obj === "object" && firstKey in obj) { - (obj as Record)[firstKey] = ""; + if (deleteLeaf) { + delete (obj as Record)[firstKey]; + } else { + (obj as Record)[firstKey] = ""; + } } } else { if (obj && typeof obj === "object" && firstKey in obj) { @@ -2715,6 +3685,7 @@ function omitAtPath( | unknown[] | undefined, remainingKeys, + deleteLeaf, ); } } @@ -2726,12 +3697,14 @@ function omitAtPath( function omit( obj: Record, paths: string[], + deletePaths: string[] = [], ): Record { const result = deepCopy(obj); + const deletePathSet = new Set(deletePaths); for (const path of paths) { const keys = parsePath(path); - omitAtPath(result, keys); + omitAtPath(result, keys, deletePathSet.has(path)); } return result; diff --git a/js/src/instrumentation/plugins/ai-sdk-v7-telemetry.test.ts b/js/src/instrumentation/plugins/ai-sdk-v7-telemetry.test.ts index 4218aa407..8741a0e1f 100644 --- a/js/src/instrumentation/plugins/ai-sdk-v7-telemetry.test.ts +++ b/js/src/instrumentation/plugins/ai-sdk-v7-telemetry.test.ts @@ -1,7 +1,18 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { _exportsForTestingOnly, currentSpan, initLogger } from "../../logger"; +import { + _exportsForTestingOnly, + currentSpan, + initLogger, + startSpan, + withCurrent, +} from "../../logger"; import { configureNode } from "../../node/config"; import { braintrustAISDKTelemetry } from "../../wrappers/ai-sdk/telemetry"; +import { + registerWorkflowAgentWrapperSpan, + unregisterWorkflowAgentWrapperSpan, +} from "../../wrappers/ai-sdk/workflow-agent-context"; +import { BRAINTRUST_AI_SDK_V7_OPERATION_KEY as AI_SDK_V7_OPERATION_KEY } from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; try { configureNode(); @@ -189,6 +200,7 @@ describe("braintrustAISDKTelemetry", () => { telemetry.onStart?.({ callId: "call-1", + instructions: "Be terse.", operationId: "ai.generateText", provider: "openai", modelId: "gpt-4.1-mini", @@ -197,9 +209,10 @@ describe("braintrustAISDKTelemetry", () => { }); telemetry.onLanguageModelCallStart?.({ callId: "call-1", + instructions: "Be terse.", provider: "openai", modelId: "gpt-4.1-mini", - prompt: [{ role: "user", content: "Reply with OK." }], + messages: [{ role: "user", content: "Reply with OK." }], }); telemetry.onLanguageModelCallEnd?.({ callId: "call-1", @@ -239,6 +252,7 @@ describe("braintrustAISDKTelemetry", () => { name: "generateText", }, input: { + instructions: "Be terse.", messages: [{ role: "user", content: "Reply with OK." }], }, metadata: { @@ -263,9 +277,495 @@ describe("braintrustAISDKTelemetry", () => { model: "gpt-4.1-mini", }, }); + expect(modelCall?.input).toMatchObject({ + instructions: "Be terse.", + messages: [{ role: "user", content: "Reply with OK." }], + }); expect(modelCall?.output).toMatchObject({ text: "OK" }); }); + it("normalizes WorkflowAgent stream operation names", async () => { + const telemetry = braintrustAISDKTelemetry(); + + telemetry.onStart?.({ + callId: "workflow-agent", + headers: { authorization: "secret" }, + maxOutputTokens: 32, + operationId: "ai.workflowAgent.stream", + provider: "openai", + modelId: "gpt-4.1-mini", + temperature: 0, + messages: [{ role: "user", content: "Use the weather tool." }], + toolChoice: "required", + tools: { + get_weather: { + description: "Get weather for a location", + }, + }, + }); + telemetry.onLanguageModelCallStart?.({ + callId: "workflow-agent-model-call", + headers: { authorization: "secret" }, + maxOutputTokens: 32, + provider: "openai", + modelId: "gpt-4.1-mini", + temperature: 0, + prompt: [{ role: "user", content: "Use the weather tool." }], + toolChoice: "required", + }); + telemetry.onLanguageModelCallEnd?.({ + callId: "workflow-agent-model-call", + provider: "openai", + modelId: "gpt-4.1-mini", + text: "It is sunny.", + usage: { + inputTokens: 8, + outputTokens: 4, + totalTokens: 12, + }, + }); + telemetry.onToolExecutionStart?.({ + toolCall: { + toolCallId: "tool-workflow", + toolName: "get_weather", + input: { location: "Vienna, Austria" }, + }, + }); + telemetry.onToolExecutionEnd?.({ + durationMs: 12, + output: { + condition: "sunny", + location: "Vienna, Austria", + temperatureC: 21, + }, + success: true, + toolCall: { + toolCallId: "tool-workflow", + toolName: "get_weather", + }, + }); + telemetry.onEnd?.({ + callId: "workflow-agent", + finishReason: "stop", + messages: [{ role: "assistant", content: "It is sunny." }], + operationId: "ai.workflowAgent.stream", + steps: [], + text: "It is sunny.", + totalUsage: { + inputTokens: 8, + outputTokens: 4, + totalTokens: 12, + }, + }); + + const spans = (await backgroundLogger.drain()) as Array< + Record + >; + const operation = spans.find( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ); + const tool = spans.find( + (span) => span.span_attributes?.name === "get_weather", + ); + const model = spans.find( + (span) => span.span_attributes?.name === "doGenerate", + ); + + expect(operation).toMatchObject({ + span_attributes: { + type: "function", + name: "WorkflowAgent.stream", + }, + input: { + messages: [{ role: "user", content: "Use the weather tool." }], + }, + metadata: { + provider: "openai", + model: "gpt-4.1-mini", + options: { + maxOutputTokens: 32, + temperature: 0, + toolChoice: "required", + }, + tools: { + get_weather: { + description: "Get weather for a location", + }, + }, + }, + output: { + text: "It is sunny.", + }, + }); + expect(operation?.input).not.toHaveProperty("headers"); + expect(operation?.input).not.toHaveProperty("maxOutputTokens"); + expect(operation?.metadata?.options).not.toHaveProperty("headers"); + expect(model).toMatchObject({ + span_attributes: { + type: "llm", + name: "doGenerate", + }, + input: { + messages: [{ role: "user", content: "Use the weather tool." }], + }, + metadata: { + provider: "openai", + model: "gpt-4.1-mini", + options: { + maxOutputTokens: 32, + temperature: 0, + toolChoice: "required", + }, + }, + span_parents: [operation?.span_id], + }); + expect(model?.input).not.toHaveProperty("headers"); + expect(model?.metadata?.options).not.toHaveProperty("headers"); + expect(tool).toMatchObject({ + span_attributes: { + type: "tool", + name: "get_weather", + }, + input: { location: "Vienna, Austria" }, + output: { + condition: "sunny", + location: "Vienna, Austria", + temperatureC: 21, + }, + metrics: { duration_ms: 12 }, + span_parents: [operation?.span_id], + }); + }); + + it("backfills WorkflowAgent stream input from model call telemetry", async () => { + const telemetry = braintrustAISDKTelemetry(); + + telemetry.onStart?.({ + callId: "workflow-agent", + operationId: "ai.workflowAgent.stream", + provider: "openai", + modelId: "gpt-4.1-mini", + }); + telemetry.onLanguageModelCallStart?.({ + callId: "workflow-agent-model-call", + headers: { authorization: "secret" }, + maxOutputTokens: 32, + provider: "openai", + modelId: "gpt-4.1-mini", + messages: [{ role: "user", content: "What's the weather in Paris?" }], + toolChoice: "required", + }); + telemetry.onLanguageModelCallEnd?.({ + callId: "workflow-agent-model-call", + provider: "openai", + modelId: "gpt-4.1-mini", + text: "It is sunny.", + usage: { + inputTokens: 8, + outputTokens: 4, + totalTokens: 12, + }, + }); + telemetry.onEnd?.({ + callId: "workflow-agent", + finishReason: "stop", + operationId: "ai.workflowAgent.stream", + text: "It is sunny.", + totalUsage: { + inputTokens: 8, + outputTokens: 4, + totalTokens: 12, + }, + }); + + const spans = (await backgroundLogger.drain()) as Array< + Record + >; + const operation = spans.find( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ); + + expect(operation).toMatchObject({ + input: { + messages: [{ role: "user", content: "What's the weather in Paris?" }], + }, + metadata: { + provider: "openai", + model: "gpt-4.1-mini", + options: { + maxOutputTokens: 32, + toolChoice: "required", + }, + }, + }); + expect(operation?.input).not.toHaveProperty("headers"); + }); + + it("does not create telemetry child spans for wrapper-owned WorkflowAgent streams", async () => { + const telemetry = braintrustAISDKTelemetry(); + const wrapperSpan = startSpan({ name: "WorkflowAgent.stream" }); + registerWorkflowAgentWrapperSpan(wrapperSpan); + + try { + withCurrent(wrapperSpan, () => { + telemetry.onStart?.({ + callId: "workflow-agent", + messages: [{ role: "user", content: "Use the weather tool." }], + operationId: "ai.workflowAgent.stream", + }); + telemetry.onLanguageModelCallStart?.({ + callId: "workflow-agent", + prompt: [{ role: "user", content: "Use the weather tool." }], + }); + telemetry.onLanguageModelCallEnd?.({ + callId: "workflow-agent", + text: "Calling get_weather.", + }); + telemetry.onToolExecutionStart?.({ + toolCall: { + toolCallId: "tool-workflow", + toolName: "get_weather", + input: { location: "Vienna, Austria" }, + }, + }); + telemetry.onToolExecutionEnd?.({ + output: { condition: "sunny" }, + success: true, + toolCall: { + toolCallId: "tool-workflow", + toolName: "get_weather", + }, + }); + telemetry.onEnd?.({ + callId: "workflow-agent", + operationId: "ai.workflowAgent.stream", + text: "It is sunny.", + }); + }); + } finally { + unregisterWorkflowAgentWrapperSpan(wrapperSpan); + wrapperSpan.end(); + } + + const spans = (await backgroundLogger.drain()) as Array< + Record + >; + + expect( + spans.filter((span) => span.span_attributes?.name === "doGenerate"), + ).toHaveLength(0); + expect( + spans.filter((span) => span.span_attributes?.name === "get_weather"), + ).toHaveLength(0); + }); + + it("keeps concurrent WorkflowAgent streams with shared callIds separate", async () => { + const telemetry = braintrustAISDKTelemetry(); + const callId = "workflow-agent"; + const runA = "workflow-agent:run-a"; + const runB = "workflow-agent:run-b"; + + telemetry.onStart?.({ + [AI_SDK_V7_OPERATION_KEY]: runA, + callId, + messages: [{ role: "user", content: "First workflow run" }], + operationId: "ai.workflowAgent.stream", + }); + telemetry.onStart?.({ + [AI_SDK_V7_OPERATION_KEY]: runB, + callId, + messages: [{ role: "user", content: "Second workflow run" }], + operationId: "ai.workflowAgent.stream", + }); + + telemetry.onLanguageModelCallStart?.({ + [AI_SDK_V7_OPERATION_KEY]: runA, + callId, + prompt: [{ role: "user", content: "First workflow run" }], + }); + telemetry.onLanguageModelCallEnd?.({ + [AI_SDK_V7_OPERATION_KEY]: runA, + callId, + text: "First answer", + }); + telemetry.onLanguageModelCallStart?.({ + [AI_SDK_V7_OPERATION_KEY]: runB, + callId, + prompt: [{ role: "user", content: "Second workflow run" }], + }); + telemetry.onLanguageModelCallEnd?.({ + [AI_SDK_V7_OPERATION_KEY]: runB, + callId, + text: "Calling get_weather.", + }); + + telemetry.onToolExecutionStart?.({ + [AI_SDK_V7_OPERATION_KEY]: runB, + toolCall: { + toolCallId: "tool-run-b", + toolName: "get_weather", + input: { location: "Vienna, Austria" }, + }, + }); + telemetry.onToolExecutionEnd?.({ + [AI_SDK_V7_OPERATION_KEY]: runB, + output: { condition: "sunny" }, + success: true, + toolCall: { + toolCallId: "tool-run-b", + toolName: "get_weather", + }, + }); + + telemetry.onEnd?.({ + [AI_SDK_V7_OPERATION_KEY]: runA, + callId, + messages: [{ role: "assistant", content: "First answer" }], + operationId: "ai.workflowAgent.stream", + text: "First answer", + }); + telemetry.onEnd?.({ + [AI_SDK_V7_OPERATION_KEY]: runB, + callId, + messages: [{ role: "assistant", content: "Second answer" }], + operationId: "ai.workflowAgent.stream", + text: "Second answer", + }); + + const spans = (await backgroundLogger.drain()) as Array< + Record + >; + const workflowSpans = spans.filter( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ); + const firstWorkflow = workflowSpans.find((span) => + JSON.stringify(span.input).includes("First workflow run"), + ); + const secondWorkflow = workflowSpans.find((span) => + JSON.stringify(span.input).includes("Second workflow run"), + ); + const firstModel = spans.find( + (span) => + span.span_attributes?.name === "doGenerate" && + JSON.stringify(span.input).includes("First workflow run"), + ); + const secondModel = spans.find( + (span) => + span.span_attributes?.name === "doGenerate" && + JSON.stringify(span.input).includes("Second workflow run"), + ); + const tool = spans.find( + (span) => span.span_attributes?.name === "get_weather", + ); + + expect(workflowSpans).toHaveLength(2); + expect(firstWorkflow?.output).toMatchObject({ text: "First answer" }); + expect(secondWorkflow?.output).toMatchObject({ text: "Second answer" }); + expect(firstModel?.span_parents).toEqual([firstWorkflow?.span_id]); + expect(secondModel?.span_parents).toEqual([secondWorkflow?.span_id]); + expect(tool).toMatchObject({ + input: { location: "Vienna, Austria" }, + output: { condition: "sunny" }, + span_parents: [secondWorkflow?.span_id], + }); + }); + + it("keeps concurrent direct WorkflowAgent telemetry separated without dispatcher keys", async () => { + const telemetry = braintrustAISDKTelemetry(); + const callId = "workflow-agent"; + const sleep = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); + + const runWorkflow = async (label: "First" | "Second", delayMs: number) => { + telemetry.onStart?.({ + callId, + messages: [{ role: "user", content: `${label} workflow run` }], + operationId: "ai.workflowAgent.stream", + }); + + await sleep(delayMs); + + telemetry.onLanguageModelCallStart?.({ + callId, + prompt: [{ role: "user", content: `${label} workflow run` }], + }); + telemetry.onLanguageModelCallEnd?.({ + callId, + text: `${label} model answer`, + }); + telemetry.onToolExecutionStart?.({ + toolCall: { + toolCallId: `tool-${label}`, + toolName: "get_weather", + input: { location: label }, + }, + }); + telemetry.onToolExecutionEnd?.({ + output: { condition: label }, + success: true, + toolCall: { + toolCallId: `tool-${label}`, + toolName: "get_weather", + }, + }); + telemetry.onEnd?.({ + callId, + messages: [{ role: "assistant", content: `${label} answer` }], + operationId: "ai.workflowAgent.stream", + text: `${label} answer`, + }); + }; + + await Promise.all([runWorkflow("First", 20), runWorkflow("Second", 0)]); + + const spans = (await backgroundLogger.drain()) as Array< + Record + >; + const workflowSpans = spans.filter( + (span) => span.span_attributes?.name === "WorkflowAgent.stream", + ); + const firstWorkflow = workflowSpans.find((span) => + JSON.stringify(span.input).includes("First workflow run"), + ); + const secondWorkflow = workflowSpans.find((span) => + JSON.stringify(span.input).includes("Second workflow run"), + ); + const firstModel = spans.find( + (span) => + span.span_attributes?.name === "doGenerate" && + JSON.stringify(span.input).includes("First workflow run"), + ); + const secondModel = spans.find( + (span) => + span.span_attributes?.name === "doGenerate" && + JSON.stringify(span.input).includes("Second workflow run"), + ); + const firstTool = spans.find( + (span) => + span.span_attributes?.name === "get_weather" && + span.input?.location === "First", + ); + const secondTool = spans.find( + (span) => + span.span_attributes?.name === "get_weather" && + span.input?.location === "Second", + ); + + expect(workflowSpans).toHaveLength(2); + expect(firstWorkflow?.output).toMatchObject({ text: "First answer" }); + expect(secondWorkflow?.output).toMatchObject({ text: "Second answer" }); + expect(firstModel?.span_parents).toEqual([firstWorkflow?.span_id]); + expect(secondModel?.span_parents).toEqual([secondWorkflow?.span_id]); + expect(firstTool).toMatchObject({ + output: { condition: "First" }, + span_parents: [firstWorkflow?.span_id], + }); + expect(secondTool).toMatchObject({ + output: { condition: "Second" }, + span_parents: [secondWorkflow?.span_id], + }); + }); + it("honors recordInputs and recordOutputs", async () => { const telemetry = braintrustAISDKTelemetry(); @@ -387,6 +887,57 @@ describe("braintrustAISDKTelemetry", () => { expect(await backgroundLogger.drain()).toHaveLength(0); }); + it("ends open child spans when an operation aborts", async () => { + const telemetry = braintrustAISDKTelemetry(); + const callId = "call-abort"; + const reason = new Error("user aborted stream"); + + telemetry.onStart?.({ + callId, + operationId: "ai.streamText", + }); + telemetry.onLanguageModelCallStart?.({ + callId, + prompt: [{ role: "user", content: "Reply slowly." }], + }); + telemetry.onToolExecutionStart?.({ + callId, + toolCall: { + toolCallId: "tool-abort", + toolName: "lookupWeather", + input: { city: "Vienna" }, + }, + }); + + telemetry.onAbort?.({ callId, reason }); + + const spans = (await backgroundLogger.drain()) as Array< + Record + >; + const errorSpans = spans.filter((span) => + String(span.error).includes("user aborted stream"), + ); + + expect(errorSpans).toHaveLength(3); + expect(errorSpans.map((span) => span.span_attributes?.name)).toEqual( + expect.arrayContaining(["streamText", "doStream", "lookupWeather"]), + ); + + telemetry.onLanguageModelCallEnd?.({ callId, text: "late" }); + telemetry.onToolExecutionEnd?.({ + callId, + toolCall: { toolCallId: "tool-abort", toolName: "lookupWeather" }, + toolOutput: { type: "tool-result", output: "late" }, + }); + telemetry.onEnd?.({ + callId, + operationId: "ai.streamText", + text: "late", + }); + + expect(await backgroundLogger.drain()).toHaveLength(0); + }); + it("ends superseded retry child spans before successful finish", async () => { const telemetry = braintrustAISDKTelemetry(); diff --git a/js/src/instrumentation/registry.test.ts b/js/src/instrumentation/registry.test.ts index f56374051..4fa54be93 100644 --- a/js/src/instrumentation/registry.test.ts +++ b/js/src/instrumentation/registry.test.ts @@ -4,6 +4,11 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; vi.mock("../isomorph", () => ({ default: { newTracingChannel: vi.fn(), + newAsyncLocalStorage: vi.fn(() => ({ + enterWith: vi.fn(), + getStore: vi.fn(() => undefined), + run: vi.fn((_store: unknown, callback: () => unknown) => callback()), + })), getEnv: vi.fn(() => undefined), buildType: "node", }, diff --git a/js/src/vendor-sdk-types/ai-sdk-common.ts b/js/src/vendor-sdk-types/ai-sdk-common.ts index f2cb9311f..62f4ccb21 100644 --- a/js/src/vendor-sdk-types/ai-sdk-common.ts +++ b/js/src/vendor-sdk-types/ai-sdk-common.ts @@ -178,7 +178,9 @@ export interface AISDKRerankParams { export interface AISDKCallParams { model?: AISDKModel; - prompt?: AISDKMessage[] | Record; + instructions?: unknown; + prompt?: string | AISDKMessage[]; + system?: unknown; messages?: AISDKMessage[]; tools?: AISDKTools; schema?: unknown; @@ -265,7 +267,7 @@ export type AISDKGenerateFunction = ( export type AISDKStreamFunction = (params: AISDKCallParams) => AISDKResult; export interface AISDKAgentInstance { - settings: AISDKCallParams; + settings?: AISDKCallParams; generate: AISDKGenerateFunction; stream: AISDKStreamFunction; constructor: { @@ -278,6 +280,18 @@ export interface AISDKAgentClass { new (...args: unknown[]): AISDKAgentInstance; } +export interface AISDKWorkflowAgentInstance { + stream: AISDKStreamFunction; + constructor: { + name: string; + }; + [key: string]: unknown; +} + +export interface AISDKWorkflowAgentClass { + new (...args: unknown[]): AISDKWorkflowAgentInstance; +} + export interface AISDKProviderResolver { languageModel?: (modelId: string) => AISDKLanguageModel; [key: string]: unknown; diff --git a/js/src/vendor-sdk-types/ai-sdk-v7-telemetry.ts b/js/src/vendor-sdk-types/ai-sdk-v7-telemetry.ts index 49b621f0d..a63e44d33 100644 --- a/js/src/vendor-sdk-types/ai-sdk-v7-telemetry.ts +++ b/js/src/vendor-sdk-types/ai-sdk-v7-telemetry.ts @@ -12,6 +12,10 @@ export interface AISDKV7TelemetryOptions { functionId?: string; } +export const BRAINTRUST_AI_SDK_V7_OPERATION_KEY = Symbol.for( + "braintrust.ai-sdk.v7.telemetry-operation-key", +); + export interface AISDKV7ModelInfo { provider?: string; modelId?: string; @@ -21,12 +25,14 @@ export interface AISDKV7OperationEvent extends AISDKV7TelemetryOptions, AISDKV7ModelInfo { callId: string; operationId: string; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } export interface AISDKV7LanguageModelCallStartEvent extends AISDKV7TelemetryOptions, AISDKV7ModelInfo { callId: string; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -37,6 +43,7 @@ export interface AISDKV7LanguageModelCallEndEvent finishReason?: unknown; responseId?: string; usage?: unknown; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -45,6 +52,7 @@ export interface AISDKV7ObjectStepStartEvent callId: string; promptMessages?: unknown; stepNumber?: number; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -59,6 +67,7 @@ export interface AISDKV7ObjectStepEndEvent response?: unknown; usage?: unknown; warnings?: unknown; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -68,6 +77,7 @@ export interface AISDKV7EmbedStartEvent embedCallId: string; operationId: string; values: unknown[]; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -79,6 +89,7 @@ export interface AISDKV7EmbedEndEvent embeddings?: unknown[]; usage?: unknown; values?: unknown[]; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -88,6 +99,7 @@ export interface AISDKV7RerankStartEvent documents?: unknown[]; query?: string; topN?: number; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -95,6 +107,7 @@ export interface AISDKV7RerankEndEvent extends AISDKV7TelemetryOptions, AISDKV7ModelInfo { callId: string; ranking?: Array<{ index?: number; relevanceScore?: number }>; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -106,9 +119,10 @@ export interface AISDKV7ToolCall { } export interface AISDKV7ToolExecutionStartEvent extends AISDKV7TelemetryOptions { - callId: string; + callId?: string; toolCall: AISDKV7ToolCall; toolContext?: unknown; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -120,10 +134,14 @@ export interface AISDKV7ToolOutput { } export interface AISDKV7ToolExecutionEndEvent extends AISDKV7TelemetryOptions { - callId: string; + callId?: string; durationMs?: number; + error?: unknown; + output?: unknown; + success?: boolean; toolCall: AISDKV7ToolCall; toolOutput?: AISDKV7ToolOutput; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; [key: string]: unknown; } @@ -161,13 +179,16 @@ export interface AISDKV7Telemetry { event: AISDKV7ToolExecutionEndEvent, ) => void | PromiseLike; onChunk?: (event: AISDKV7ChunkEvent) => void | PromiseLike; + onStepEnd?: (event: unknown) => void | PromiseLike; onStepFinish?: (event: unknown) => void | PromiseLike; onEnd?: (event: AISDKV7OperationEvent) => void | PromiseLike; + onAbort?: (event: unknown) => void | PromiseLike; onError?: (event: unknown) => void | PromiseLike; executeTool?: (options: { callId: string; toolCallId: string; execute: () => PromiseLike; + [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]?: string; }) => PromiseLike; } diff --git a/js/src/vendor-sdk-types/ai-sdk.ts b/js/src/vendor-sdk-types/ai-sdk.ts index 6bc261a08..15513a2c5 100644 --- a/js/src/vendor-sdk-types/ai-sdk.ts +++ b/js/src/vendor-sdk-types/ai-sdk.ts @@ -30,6 +30,8 @@ import type { AISDKTools, AISDKTokenBucket, AISDKUsage, + AISDKWorkflowAgentClass, + AISDKWorkflowAgentInstance, } from "./ai-sdk-common"; import type { AISDKV3 } from "./ai-sdk-v3"; import type { AISDKV4 } from "./ai-sdk-v4"; @@ -76,4 +78,6 @@ export type { AISDKTools, AISDKTokenBucket, AISDKUsage, + AISDKWorkflowAgentClass, + AISDKWorkflowAgentInstance, }; diff --git a/js/src/wrappers/ai-sdk/ai-sdk.ts b/js/src/wrappers/ai-sdk/ai-sdk.ts index f2f5cc92a..562d2e205 100644 --- a/js/src/wrappers/ai-sdk/ai-sdk.ts +++ b/js/src/wrappers/ai-sdk/ai-sdk.ts @@ -13,7 +13,9 @@ import type { AISDKRerankFunction, AISDKRerankParams, AISDKStreamFunction, + AISDKWorkflowAgentClass, } from "../../vendor-sdk-types/ai-sdk"; +import { currentWorkflowAgentWrapperSpan } from "./workflow-agent-context"; interface WrapAISDKOptions { denyOutputPaths?: string[]; @@ -137,6 +139,7 @@ export function wrapAISDK(aiSDK: T, options: WrapAISDKOptions = {}): T { case "Agent": case "Experimental_Agent": case "ToolLoopAgent": + case "WorkflowAgent": return original ? wrapAgentClass(original, options) : original; } return original; @@ -148,7 +151,9 @@ export const wrapAgentClass = ( AgentClass: any, options: WrapAISDKOptions = {}, ): any => { - const typedAgentClass = AgentClass as AISDKAgentClass; + const typedAgentClass = AgentClass as + | AISDKAgentClass + | AISDKWorkflowAgentClass; return new Proxy(typedAgentClass, { construct(target, args, newTarget) { @@ -161,11 +166,15 @@ export const wrapAgentClass = ( get(instanceTarget, prop, instanceReceiver) { const original = Reflect.get(instanceTarget, prop, instanceTarget); - if (prop === "generate") { + if ( + prop === "generate" && + typeof original === "function" && + instanceTarget.constructor.name !== "WorkflowAgent" + ) { return wrapAgentGenerate(original, instanceTarget, options); } - if (prop === "stream") { + if (prop === "stream" && typeof original === "function") { return wrapAgentStream(original, instanceTarget, options); } @@ -189,7 +198,7 @@ const wrapAgentGenerate = ( const defaultName = `${instance.constructor.name}.generate`; return async (params: AISDKCallParams & SpanInfo) => makeGenerateTextWrapper( - aiSDKChannels.generateText, + generateChannelForAgent(instance.constructor.name), defaultName, generate.bind(instance), { @@ -200,29 +209,62 @@ const wrapAgentGenerate = ( )({ ...instance.settings, ...params }); }; +function generateChannelForAgent(agentName: string) { + if (agentName === "ToolLoopAgent") { + return aiSDKChannels.toolLoopAgentGenerate; + } + + return aiSDKChannels.agentGenerate; +} + const wrapAgentStream = ( stream: AISDKStreamFunction, instance: AISDKAgentInstance, options: WrapAISDKOptions = {}, ) => { const defaultName = `${instance.constructor.name}.stream`; - return (params: AISDKCallParams & SpanInfo) => - makeStreamWrapper( - aiSDKChannels.agentStream, - defaultName, - stream.bind(instance), - { - self: instance, - spanType: SpanTypeAttribute.FUNCTION, - }, - options, - )({ ...instance.settings, ...params }); + return (params: AISDKCallParams & SpanInfo) => { + const workflowAgent = instance.constructor.name === "WorkflowAgent"; + + if (workflowAgent && currentWorkflowAgentWrapperSpan()) { + const { span_info: _spanInfo, ...cleanParams } = params; + return stream.call(instance, { ...instance.settings, ...cleanParams }); + } + + const trace = () => + makeStreamWrapper( + streamChannelForAgent(instance.constructor.name), + defaultName, + stream.bind(instance), + { + self: instance, + spanType: SpanTypeAttribute.FUNCTION, + }, + options, + )({ ...instance.settings, ...params }); + + return trace(); + }; }; +function streamChannelForAgent(agentName: string) { + if (agentName === "ToolLoopAgent") { + return aiSDKChannels.toolLoopAgentStream; + } + + if (agentName === "WorkflowAgent") { + return aiSDKChannels.workflowAgentStream; + } + + return aiSDKChannels.agentStream; +} + const makeGenerateTextWrapper = ( channel: | typeof aiSDKChannels.generateText - | typeof aiSDKChannels.generateObject, + | typeof aiSDKChannels.generateObject + | typeof aiSDKChannels.agentGenerate + | typeof aiSDKChannels.toolLoopAgentGenerate, name: string, generateText: AISDKGenerateFunction, contextOptions: { @@ -384,7 +426,8 @@ const makeStreamWrapper = ( | typeof aiSDKChannels.streamText | typeof aiSDKChannels.streamObject | typeof aiSDKChannels.agentStream - | typeof aiSDKChannels.toolLoopAgentStream, + | typeof aiSDKChannels.toolLoopAgentStream + | typeof aiSDKChannels.workflowAgentStream, name: string, streamText: AISDKStreamFunction, contextOptions: { diff --git a/js/src/wrappers/ai-sdk/telemetry.ts b/js/src/wrappers/ai-sdk/telemetry.ts index c42ef9204..798bcbf7d 100644 --- a/js/src/wrappers/ai-sdk/telemetry.ts +++ b/js/src/wrappers/ai-sdk/telemetry.ts @@ -7,11 +7,14 @@ import { logError, startSpan, withCurrent, type Span } from "../../logger"; import { createAISDKIntegrationMetadata, DEFAULT_DENY_OUTPUT_PATHS, + extractWorkflowMetadataFromCallParams, extractTokenMetrics, processAISDKCallInput, processAISDKEmbeddingOutput, processAISDKOutput, processAISDKRerankOutput, + processAISDKWorkflowAgentCallInput, + processAISDKWorkflowAgentModelCallInput, serializeModelWithProvider, } from "../../instrumentation/plugins/ai-sdk-plugin"; import type { @@ -21,23 +24,30 @@ import type { AISDKResult, AISDKRerankResult, } from "../../vendor-sdk-types/ai-sdk"; +import iso from "../../isomorph"; import type { AISDKV7LanguageModelCallStartEvent, AISDKV7OperationEvent, AISDKV7Telemetry, AISDKV7TelemetryOptions, } from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; +import { BRAINTRUST_AI_SDK_V7_OPERATION_KEY as AI_SDK_V7_OPERATION_KEY } from "../../vendor-sdk-types/ai-sdk-v7-telemetry"; +import { currentWorkflowAgentWrapperSpan } from "./workflow-agent-context"; type OperationState = { + callId: string; firstChunkTime?: number; hadModelChild: boolean; + loggedInput: boolean; operationName: string; + operationKey: string; + ownsSpan: boolean; span: Span; startTime: number; }; type CallSpanState = { - callId: string; + operationKey: string; span: Span; }; @@ -51,11 +61,16 @@ type EmbedSpanState = CallSpanState & { */ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { const operations = new Map(); + const operationKeysByCallId = new Map(); + const workflowOperationKeyStore = iso.newAsyncLocalStorage< + string | undefined + >(); const modelSpans = new Map(); const objectSpans = new Map(); const embedSpans = new Map(); const rerankSpans = new Map(); const toolSpans = new Map(); + let workflowAgentOperationCounter = 0; const runSafely = (name: string, callback: () => void) => { try { @@ -67,31 +82,256 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { }; const startChildSpan = ( - callId: string, + operationKey: string, name: string, type: SpanTypeAttribute, event?: { input?: unknown; metadata?: Record }, ) => { - const parent = operations.get(callId)?.span; + const parent = operations.get(operationKey)?.span; const spanArgs = { name, spanAttributes: { type }, ...(event ? { event } : {}), }; const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs); - const state = operations.get(callId); + const state = operations.get(operationKey); if (state && type === SpanTypeAttribute.LLM) { state.hadModelChild = true; } return span; }; + const registerOperation = (state: OperationState): void => { + operations.set(state.operationKey, state); + const keys = operationKeysByCallId.get(state.callId) ?? []; + keys.push(state.operationKey); + operationKeysByCallId.set(state.callId, keys); + }; + + const deleteOperation = (operationKey: string): void => { + const state = operations.get(operationKey); + if (!state) { + return; + } + + operations.delete(operationKey); + if (workflowOperationKeyStore.getStore() === operationKey) { + // TODO(luca): Replace ALS.enterWith() with ALS.run() once direct + // telemetry can wrap the full WorkflowAgent callback lifecycle. + // eslint-disable-next-line no-restricted-syntax -- Existing ALS.enterWith() usage tracked by the TODO above. + workflowOperationKeyStore.enterWith(undefined); + } + + const keys = operationKeysByCallId.get(state.callId); + if (!keys) { + return; + } + + const index = keys.indexOf(operationKey); + if (index >= 0) { + keys.splice(index, 1); + } + if (keys.length === 0) { + operationKeysByCallId.delete(state.callId); + } + }; + + const explicitOperationKey = (event: unknown): string | undefined => { + if (!isObject(event)) { + return undefined; + } + + const key = (event as { [AI_SDK_V7_OPERATION_KEY]?: unknown })[ + AI_SDK_V7_OPERATION_KEY + ]; + return typeof key === "string" ? key : undefined; + }; + + const createOperationKey = ( + event: AISDKV7OperationEvent, + operationName: string, + ): string => { + const explicit = explicitOperationKey(event); + if (explicit) { + return explicit; + } + + if (operationName === "WorkflowAgent.stream") { + workflowAgentOperationCounter += 1; + return `${event.callId}:${workflowAgentOperationCounter}`; + } + + return event.callId; + }; + + const operationKeyForCallId = ( + callId: string, + mode: "active" | "finish" = "active", + ): string | undefined => { + const keys = operationKeysByCallId.get(callId); + if (!keys || keys.length === 0) { + return operations.has(callId) ? callId : undefined; + } + + if (keys.length === 1) { + return keys[0]; + } + + const wrapperSpan = currentWorkflowAgentWrapperSpan(); + if (wrapperSpan?.spanId) { + const key = keys.find( + (candidate) => + operations.get(candidate)?.span.spanId === wrapperSpan.spanId, + ); + if (key) { + return key; + } + } + + const workflowOperationKey = workflowOperationKeyStore.getStore(); + if (workflowOperationKey && keys.includes(workflowOperationKey)) { + return workflowOperationKey; + } + + if (callId === "workflow-agent") { + return undefined; + } + + return mode === "finish" ? keys[0] : keys[keys.length - 1]; + }; + + const operationKeyFromEvent = ( + event: { callId?: unknown } | unknown, + mode: "active" | "finish" = "active", + ): string | undefined => { + const explicit = explicitOperationKey(event); + if (explicit && operations.has(explicit)) { + return explicit; + } + + if (isObject(event)) { + const callId = (event as { callId?: unknown }).callId; + if (typeof callId === "string") { + const operationKey = operationKeyForCallId(callId, mode); + if (operationKey) { + return operationKey; + } + + const workflowOperationKey = workflowOperationKeyStore.getStore(); + if (workflowOperationKey && operations.has(workflowOperationKey)) { + return workflowOperationKey; + } + + return callId === "workflow-agent" ? undefined : callId; + } + } + + const workflowOperationKey = workflowOperationKeyStore.getStore(); + if (workflowOperationKey && operations.has(workflowOperationKey)) { + return workflowOperationKey; + } + + const wrapperSpan = currentWorkflowAgentWrapperSpan(); + if (wrapperSpan?.spanId) { + for (const [operationKey, state] of operations) { + if ( + state.operationName === "WorkflowAgent.stream" && + state.span.spanId === wrapperSpan.spanId + ) { + return operationKey; + } + } + } + + // WorkflowAgent uses this callId on the operation, but omits it from + // tool start/end callbacks in @ai-sdk/workflow@1.0.x. + const workflowAgentKeys = operationKeysByCallId.get("workflow-agent"); + if (workflowAgentKeys?.length === 1) { + return workflowAgentKeys[0]; + } + + if (operations.size === 1) { + return operations.keys().next().value; + } + + return undefined; + }; + + const closeOpenChildSpans = (operationKey: string, error?: unknown): void => { + const openModelSpans = modelSpans.get(operationKey); + if (openModelSpans) { + for (const span of openModelSpans) { + if (error !== undefined) { + logError(span, error); + } + span.end(); + } + modelSpans.delete(operationKey); + } + + const openObjectSpan = objectSpans.get(operationKey); + if (openObjectSpan) { + if (error !== undefined) { + logError(openObjectSpan, error); + } + openObjectSpan.end(); + objectSpans.delete(operationKey); + } + + for (const [embedCallId, embedState] of embedSpans) { + if (embedState.operationKey === operationKey) { + if (error !== undefined) { + logError(embedState.span, error); + } + embedState.span.end(); + embedSpans.delete(embedCallId); + } + } + + const openRerankSpan = rerankSpans.get(operationKey); + if (openRerankSpan) { + if (error !== undefined) { + logError(openRerankSpan, error); + } + openRerankSpan.end(); + rerankSpans.delete(operationKey); + } + + for (const [toolCallId, toolState] of toolSpans) { + if (toolState.operationKey === operationKey) { + if (error !== undefined) { + logError(toolState.span, error); + } + toolState.span.end(); + toolSpans.delete(toolCallId); + } + } + }; + + const abortReasonFromEvent = (event: unknown): unknown => { + if (isObject(event)) { + const abortEvent = event as { error?: unknown; reason?: unknown }; + if (abortEvent.error !== undefined) { + return abortEvent.error; + } + if (abortEvent.reason !== undefined) { + return abortEvent.reason; + } + } + + return new Error("AI SDK operation aborted"); + }; + + const shouldSkipTelemetryChildren = (state?: OperationState): boolean => + state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan; + const onObjectStepEnd = ( event: Parameters>[0], ) => { runSafely("onObjectStepEnd", () => { - const span = objectSpans.get(event.callId); - if (!span) { + const operationKey = operationKeyFromEvent(event); + const span = operationKey ? objectSpans.get(operationKey) : undefined; + if (!operationKey || !span) { return; } @@ -108,7 +348,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { metrics: extractTokenMetrics(result), }); span.end(); - objectSpans.delete(event.callId); + objectSpans.delete(operationKey); }); }; @@ -145,8 +385,9 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { event: Parameters>[0], ) => { runSafely("onRerankEnd", () => { - const span = rerankSpans.get(event.callId); - if (!span) { + const operationKey = operationKeyFromEvent(event); + const span = operationKey ? rerankSpans.get(operationKey) : undefined; + if (!operationKey || !span) { return; } @@ -167,7 +408,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { : {}), }); span.end(); - rerankSpans.delete(event.callId); + rerankSpans.delete(operationKey); }); }; @@ -175,16 +416,24 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { event: Parameters>[0], ) => { runSafely("onEnd", () => { - const state = operations.get(event.callId); + const operationKey = operationKeyFromEvent(event, "finish"); + const state = operationKey ? operations.get(operationKey) : undefined; if (!state) { return; } + if (!state.ownsSpan) { + deleteOperation(state.operationKey); + return; + } const result = finishResult(event, state.operationName); const metrics: Record = state.hadModelChild ? {} : extractTokenMetrics(result); - const timeToFirstToken = extractTimeToFirstToken(result, state); + const timeToFirstToken = + state.operationName === "WorkflowAgent.stream" + ? undefined + : extractTimeToFirstToken(result, state); if (timeToFirstToken !== undefined) { metrics.time_to_first_token = timeToFirstToken; } @@ -198,7 +447,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { metrics, }); state.span.end(); - operations.delete(event.callId); + deleteOperation(state.operationKey); }); }; @@ -206,30 +455,77 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onStart(event) { runSafely("onStart", () => { const operationName = operationNameFromId(event.operationId); - const span = startSpan({ - name: operationName, - spanAttributes: { type: SpanTypeAttribute.FUNCTION }, - }); - - operations.set(event.callId, { + const workflowAgent = operationName === "WorkflowAgent.stream"; + const wrapperSpan = workflowAgent + ? currentWorkflowAgentWrapperSpan() + : undefined; + const ownsSpan = !wrapperSpan; + const span = ownsSpan + ? startSpan({ + name: operationName, + spanAttributes: { type: SpanTypeAttribute.FUNCTION }, + }) + : wrapperSpan; + const operationKey = createOperationKey(event, operationName); + + registerOperation({ + callId: event.callId, hadModelChild: false, + loggedInput: false, operationName, + operationKey, + ownsSpan, span, startTime: getCurrentUnixTimestamp(), }); - const metadata = metadataFromEvent(event); + if (!ownsSpan) { + return; + } + + if (workflowAgent) { + // Direct registerTelemetry() calls do not receive the hidden + // dispatcher operation key used by auto-instrumentation. + // TODO(luca): Replace ALS.enterWith() with ALS.run() once direct + // telemetry can wrap the full WorkflowAgent callback lifecycle. + // eslint-disable-next-line no-restricted-syntax -- Existing ALS.enterWith() usage tracked by the TODO above. + workflowOperationKeyStore.enterWith(operationKey); + } + + let metadata = metadataFromEvent(event); const logPayload: { input?: unknown; metadata: Record; } = { metadata }; + const workflowAgentCallInput = workflowAgent + ? operationInput(event, operationName) + : undefined; + if (workflowAgentCallInput) { + metadata = { + ...metadata, + ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput), + }; + logPayload.metadata = metadata; + } + if (shouldRecordInputs(event)) { - const { input, outputPromise } = processAISDKCallInput( - operationInput(event, operationName), - ); + const callInput = + workflowAgentCallInput ?? operationInput(event, operationName); + const { input, outputPromise } = workflowAgent + ? processAISDKWorkflowAgentCallInput(callInput) + : processAISDKCallInput(callInput); logPayload.input = input; - if (outputPromise && input && typeof input === "object") { + const state = operations.get(operationKey); + if (state) { + state.loggedInput = hasPromptLikeInput(input); + } + if ( + outputPromise && + !workflowAgent && + input && + typeof input === "object" + ) { outputPromise .then((resolvedData) => { span.log({ @@ -251,47 +547,84 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onLanguageModelCallStart(event) { runSafely("onLanguageModelCallStart", () => { - const state = operations.get(event.callId); - const openSpans = modelSpans.get(event.callId); - if (openSpans) { + const operationKey = operationKeyFromEvent(event); + const state = operationKey ? operations.get(operationKey) : undefined; + if (shouldSkipTelemetryChildren(state)) { + return; + } + const operationName = state?.operationName ?? "generateText"; + const callInput = operationInput(event, operationName); + const workflowAgent = operationName === "WorkflowAgent.stream"; + const processedInput = + shouldRecordInputs(event) && workflowAgent + ? processAISDKWorkflowAgentModelCallInput(callInput).input + : shouldRecordInputs(event) + ? processAISDKCallInput(callInput).input + : undefined; + if ( + workflowAgent && + state?.ownsSpan && + !state.loggedInput && + hasPromptLikeInput(processedInput) + ) { + state.span.log({ + input: processedInput, + metadata: { + ...metadataFromEvent(event), + ...extractWorkflowMetadataFromCallParams(callInput), + }, + }); + state.loggedInput = true; + } + const openSpans = operationKey + ? modelSpans.get(operationKey) + : undefined; + if (operationKey && openSpans) { for (const span of openSpans) { span.end(); } - modelSpans.delete(event.callId); + modelSpans.delete(operationKey); } const span = startChildSpan( - event.callId, - state?.operationName === "streamText" ? "doStream" : "doGenerate", + operationKey ?? event.callId, + operationName === "streamText" ? "doStream" : "doGenerate", SpanTypeAttribute.LLM, { ...(shouldRecordInputs(event) ? { - input: processAISDKCallInput( - operationInput( - event, - state?.operationName ?? "generateText", - ), - ).input, + input: processedInput, } : {}), - metadata: metadataFromEvent(event), + metadata: workflowAgent + ? { + ...metadataFromEvent(event), + ...extractWorkflowMetadataFromCallParams(callInput), + } + : metadataFromEvent(event), }, ); - const spans = modelSpans.get(event.callId) ?? []; + const spanKey = operationKey ?? event.callId; + const spans = modelSpans.get(spanKey) ?? []; spans.push(span); - modelSpans.set(event.callId, spans); + modelSpans.set(spanKey, spans); }); }, onLanguageModelCallEnd(event) { runSafely("onLanguageModelCallEnd", () => { - const span = shiftModelSpan(modelSpans, event.callId); + const operationKey = operationKeyFromEvent(event); + const state = operationKey ? operations.get(operationKey) : undefined; + if (shouldSkipTelemetryChildren(state)) { + return; + } + const span = operationKey + ? shiftModelSpan(modelSpans, operationKey) + : undefined; if (!span) { return; } - const state = operations.get(event.callId); const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs; if ( state?.operationName === "streamText" && @@ -319,15 +652,21 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onObjectStepStart(event) { runSafely("onObjectStepStart", () => { - const state = operations.get(event.callId); - const openSpan = objectSpans.get(event.callId); - if (openSpan) { + const operationKey = operationKeyFromEvent(event); + const state = operationKey ? operations.get(operationKey) : undefined; + if (shouldSkipTelemetryChildren(state)) { + return; + } + const openSpan = operationKey + ? objectSpans.get(operationKey) + : undefined; + if (operationKey && openSpan) { openSpan.end(); - objectSpans.delete(event.callId); + objectSpans.delete(operationKey); } const span = startChildSpan( - event.callId, + operationKey ?? event.callId, state?.operationName === "streamObject" ? "doStream" : "doGenerate", SpanTypeAttribute.LLM, { @@ -341,7 +680,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { metadata: metadataFromEvent(event), }, ); - objectSpans.set(event.callId, span); + objectSpans.set(operationKey ?? event.callId, span); }); }, @@ -349,10 +688,14 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onEmbedStart(event) { runSafely("onEmbedStart", () => { - const state = operations.get(event.callId); + const operationKey = operationKeyFromEvent(event); + const state = operationKey ? operations.get(operationKey) : undefined; + if (shouldSkipTelemetryChildren(state)) { + return; + } for (const [embedCallId, embedState] of embedSpans) { if ( - embedState.callId === event.callId && + embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values) ) { @@ -362,7 +705,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { } const span = startChildSpan( - event.callId, + operationKey ?? event.callId, "doEmbed", SpanTypeAttribute.LLM, { @@ -377,7 +720,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { }, ); embedSpans.set(event.embedCallId, { - callId: event.callId, + operationKey: operationKey ?? event.callId, span, values: event.values, }); @@ -388,14 +731,21 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onRerankStart(event) { runSafely("onRerankStart", () => { - const openSpan = rerankSpans.get(event.callId); - if (openSpan) { + const operationKey = operationKeyFromEvent(event); + const state = operationKey ? operations.get(operationKey) : undefined; + if (shouldSkipTelemetryChildren(state)) { + return; + } + const openSpan = operationKey + ? rerankSpans.get(operationKey) + : undefined; + if (operationKey && openSpan) { openSpan.end(); - rerankSpans.delete(event.callId); + rerankSpans.delete(operationKey); } const span = startChildSpan( - event.callId, + operationKey ?? event.callId, "doRerank", SpanTypeAttribute.LLM, { @@ -411,7 +761,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { metadata: metadataFromEvent(event), }, ); - rerankSpans.set(event.callId, span); + rerankSpans.set(operationKey ?? event.callId, span); }); }, @@ -419,13 +769,18 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onToolExecutionStart(event) { runSafely("onToolExecutionStart", () => { + const operationKey = operationKeyFromEvent(event); + const state = operationKey ? operations.get(operationKey) : undefined; + if (shouldSkipTelemetryChildren(state)) { + return; + } const toolCallId = event.toolCall.toolCallId; - if (!toolCallId) { + if (!operationKey || !toolCallId) { return; } const span = startChildSpan( - event.callId, + operationKey, event.toolCall.toolName || "tool", SpanTypeAttribute.TOOL, { @@ -443,7 +798,7 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { }, }, ); - toolSpans.set(toolCallId, { callId: event.callId, span }); + toolSpans.set(toolCallId, { operationKey, span }); }); }, @@ -456,22 +811,30 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { } const toolOutput = event.toolOutput; - if (toolOutput?.type === "tool-error") { + const workflowToolError = + (event as { success?: unknown }).success === false && "error" in event + ? (event as { error?: unknown }).error + : undefined; + + if ( + toolOutput?.type === "tool-error" || + workflowToolError !== undefined + ) { + const error = toolOutput?.error ?? workflowToolError; state.span.log({ - error: - toolOutput.error instanceof Error - ? toolOutput.error.message - : String(toolOutput?.error), + error: error instanceof Error ? error.message : String(error), metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}, }); } else { + const output = + toolOutput && "output" in toolOutput + ? toolOutput.output + : (event as { output?: unknown }).output; state.span.log({ - ...(shouldRecordOutputs(event) - ? { output: toolOutput?.output } - : {}), + ...(shouldRecordOutputs(event) ? { output } : {}), metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } @@ -489,7 +852,8 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { if (!callId) { return; } - const state = operations.get(callId); + const operationKey = operationKeyForCallId(callId); + const state = operationKey ? operations.get(operationKey) : undefined; if (!state || state.firstChunkTime !== undefined) { return; } @@ -499,65 +863,42 @@ export function braintrustAISDKTelemetry(): AISDKV7Telemetry { onEnd, + onAbort(event) { + runSafely("onAbort", () => { + const operationKey = operationKeyFromEvent(event, "finish"); + const state = operationKey ? operations.get(operationKey) : undefined; + if (!operationKey || !state) { + return; + } + + const error = abortReasonFromEvent(event); + closeOpenChildSpans(operationKey, error); + if (state.ownsSpan) { + logError(state.span, error); + state.span.end(); + } + deleteOperation(operationKey); + }); + }, + onError(event) { runSafely("onError", () => { const errorEvent = isObject(event) ? (event as { callId?: unknown; error?: unknown }) : {}; - const callId = - typeof errorEvent.callId === "string" ? errorEvent.callId : undefined; - if (!callId) { - return; - } - - const state = operations.get(callId); - if (!state) { + const operationKey = operationKeyFromEvent(errorEvent, "finish"); + const state = operationKey ? operations.get(operationKey) : undefined; + if (!operationKey || !state) { return; } const error = errorEvent.error ?? event; - const openModelSpans = modelSpans.get(callId); - if (openModelSpans) { - for (const span of openModelSpans) { - logError(span, error); - span.end(); - } - modelSpans.delete(callId); + closeOpenChildSpans(operationKey, error); + if (state.ownsSpan) { + logError(state.span, error); + state.span.end(); } - - const openObjectSpan = objectSpans.get(callId); - if (openObjectSpan) { - logError(openObjectSpan, error); - openObjectSpan.end(); - objectSpans.delete(callId); - } - - for (const [embedCallId, embedState] of embedSpans) { - if (embedState.callId === callId) { - logError(embedState.span, error); - embedState.span.end(); - embedSpans.delete(embedCallId); - } - } - - const openRerankSpan = rerankSpans.get(callId); - if (openRerankSpan) { - logError(openRerankSpan, error); - openRerankSpan.end(); - rerankSpans.delete(callId); - } - - for (const [toolCallId, toolState] of toolSpans) { - if (toolState.callId === callId) { - logError(toolState.span, error); - toolState.span.end(); - toolSpans.delete(toolCallId); - } - } - - logError(state.span, error); - state.span.end(); - operations.delete(callId); + deleteOperation(operationKey); }); }, @@ -576,7 +917,19 @@ function shouldRecordOutputs(event: AISDKV7TelemetryOptions): boolean { return event.recordOutputs !== false; } +function hasPromptLikeInput(input: unknown): boolean { + if (!isObject(input)) { + return false; + } + + return input.prompt !== undefined || input.messages !== undefined; +} + function operationNameFromId(operationId: string | undefined): string { + if (operationId === "ai.workflowAgent.stream") { + return "WorkflowAgent.stream"; + } + return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk"; @@ -642,6 +995,7 @@ function operationInput( return { model: modelFromEvent(event), + instructions: event.instructions, system: event.system, prompt: event.prompt, messages: event.messages, diff --git a/js/src/wrappers/ai-sdk/workflow-agent-context.ts b/js/src/wrappers/ai-sdk/workflow-agent-context.ts new file mode 100644 index 000000000..cb602bb62 --- /dev/null +++ b/js/src/wrappers/ai-sdk/workflow-agent-context.ts @@ -0,0 +1,33 @@ +import { _internalGetGlobalState, type Span } from "../../logger"; + +const workflowAgentWrapperSpans = new Map(); + +export function registerWorkflowAgentWrapperSpan(span: Span): void { + if (span.spanId) { + workflowAgentWrapperSpans.set(span.spanId, span); + } +} + +export function unregisterWorkflowAgentWrapperSpan(span: Span): void { + if (span.spanId) { + workflowAgentWrapperSpans.delete(span.spanId); + } +} + +export function workflowAgentWrapperSpanCountForTesting(): number { + return workflowAgentWrapperSpans.size; +} + +export function currentWorkflowAgentWrapperSpan(): Span | undefined { + const parentSpanIds = + _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? + []; + for (const parentSpanId of parentSpanIds) { + const span = workflowAgentWrapperSpans.get(parentSpanId); + if (span) { + return span; + } + } + + return undefined; +}