diff --git a/.changeset/thin-spies-train.md b/.changeset/thin-spies-train.md new file mode 100644 index 000000000..28a3612e9 --- /dev/null +++ b/.changeset/thin-spies-train.md @@ -0,0 +1,5 @@ +--- +"braintrust": minor +--- + +feat(flue): Update flue instrumentation to use new observe hooks diff --git a/e2e/config/pr-comment-scenarios.json b/e2e/config/pr-comment-scenarios.json index 25d6fafbe..0b8107e88 100644 --- a/e2e/config/pr-comment-scenarios.json +++ b/e2e/config/pr-comment-scenarios.json @@ -177,17 +177,7 @@ "scenarioDirName": "flue-instrumentation", "label": "Flue Instrumentation", "metadataScenario": "flue-instrumentation", - "variants": [ - { "variantKey": "flue-v0-7-0-wrapped", "label": "v0.7.0 wrapped" }, - { - "variantKey": "flue-v0-7-0-auto-hook", - "label": "v0.7.0 auto-hook" - }, - { - "variantKey": "flue-v0-7-0-openai-auto-hook", - "label": "v0.7.0 OpenAI auto-hook" - } - ] + "variants": [{ "variantKey": "flue-v0-8-0", "label": "v0.8.0" }] }, { "scenarioDirName": "github-copilot-instrumentation", diff --git a/e2e/scenarios/flue-instrumentation/.flue/app.mjs b/e2e/scenarios/flue-instrumentation/.flue/app.mjs new file mode 100644 index 000000000..dca2094c6 --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/.flue/app.mjs @@ -0,0 +1,53 @@ +import { configureProvider, flue, observe } from "@flue/runtime/app"; +import { flush, initLogger } from "braintrust"; + +function projectName() { + const configured = process.env.BRAINTRUST_E2E_PROJECT_NAME; + if (configured) { + return configured; + } + const testRunId = process.env.BRAINTRUST_E2E_RUN_ID ?? "local"; + return `e2e-flue-instrumentation-${testRunId.toLowerCase().replace(/[^a-z0-9-]/g, "-")}`; +} + +initLogger({ projectName: projectName() }); + +if (process.env.FLUE_E2E_EXPLICIT_OBSERVE === "1") { + const { braintrustFlueObserver } = await import("braintrust"); + observe(braintrustFlueObserver); +} + +const openAIBaseUrl = + process.env.OPENAI_BASE_URL ?? process.env.BRAINTRUST_E2E_MODEL_BASE_URL; +if (openAIBaseUrl) { + configureProvider("openai", { baseUrl: openAIBaseUrl }); +} + +const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL; +if (anthropicBaseUrl) { + configureProvider("anthropic", { + apiKey: process.env.ANTHROPIC_API_KEY ?? "test-key", + baseUrl: anthropicBaseUrl, + }); +} + +let didScheduleFlush = false; +process.on("beforeExit", () => { + if (didScheduleFlush) { + return; + } + didScheduleFlush = true; + void flush(); +}); + +const app = flue(); + +export default { + async fetch(request, env, ctx) { + if (new URL(request.url).pathname === "/__braintrust_flush") { + await flush(); + return new Response("ok"); + } + return app.fetch(request, env, ctx); + }, +}; diff --git a/e2e/scenarios/flue-instrumentation/.flue/workflows/instrumentation.mjs b/e2e/scenarios/flue-instrumentation/.flue/workflows/instrumentation.mjs new file mode 100644 index 000000000..eb1355b9b --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/.flue/workflows/instrumentation.mjs @@ -0,0 +1,142 @@ +import { createAgent, Type } from "@flue/runtime"; +import { local } from "@flue/runtime/node"; +import { + FLUE_MODEL, + FLUE_REASONING_MODEL, + SCENARIO_NAME, +} from "../../constants.mjs"; + +function flueModel() { + return process.env.FLUE_E2E_MODEL ?? FLUE_MODEL; +} + +function flueReasoningModel() { + return process.env.FLUE_E2E_REASONING_MODEL ?? FLUE_REASONING_MODEL; +} + +function fluePromptModel() { + return process.env.FLUE_E2E_PROMPT_MODEL ?? flueReasoningModel(); +} + +function fluePromptThinkingLevel() { + return ( + process.env.FLUE_E2E_PROMPT_THINKING_LEVEL ?? flueReasoningThinkingLevel() + ); +} + +function flueReasoningThinkingLevel() { + return process.env.FLUE_E2E_REASONING_THINKING_LEVEL ?? "medium"; +} + +const flueE2EAgent = createAgent(() => ({ + compaction: { + keepRecentTokens: 1, + reserveTokens: 64, + }, + cwd: process.cwd(), + instructions: [ + "You are a deterministic Flue instrumentation test agent.", + "Follow user instructions exactly.", + "When asked for a marker, output only that marker and no extra text.", + "When running a local skill file, read it yourself and do not delegate it to a task.", + ].join(" "), + model: flueModel(), + sandbox: local({ cwd: process.cwd() }), + thinkingLevel: "off", +})); + +const lookupTool = { + description: + "Return a deterministic lookup result with an id needed by web_search.", + execute: async (args) => + JSON.stringify({ + id: "flue-session-2026", + query: args.query, + topic: "session instrumentation", + }), + name: "lookup", + parameters: Type.Object({ + query: Type.String(), + }), +}; + +const webSearchTool = { + description: + "Search a deterministic local web index. Requires the id returned by lookup.", + execute: async (args) => + JSON.stringify({ + lookupId: args.lookupId, + query: args.query, + results: [ + { + title: "Flue reasoning stream instrumentation", + url: "https://example.test/flue/reasoning-streams", + }, + ], + }), + name: "web_search", + parameters: Type.Object({ + lookupId: Type.String(), + query: Type.String(), + }), +}; + +const summarizeSourceTool = { + description: + "Summarize the selected deterministic source after web_search returns a URL.", + execute: async (args) => + JSON.stringify({ + summary: + "Flue emits reasoning, tool execution, and LLM turn events separately.", + url: args.url, + }), + name: "summarize_source", + parameters: Type.Object({ + url: Type.String(), + }), +}; + +export async function route(_ctx, next) { + await next(); +} + +export async function run({ init, payload }) { + const harness = await init(flueE2EAgent, { name: "default" }); + const session = await harness.session("main"); + const skillSession = await harness.session("skill"); + const taskSession = await harness.session("task"); + + await session.prompt( + [ + "Complete this instrumented research flow.", + "Call exactly one tool per turn and wait for each tool result before choosing the next tool.", + 'Step 1: call lookup with query "flue instrumentation".', + 'Step 2: use the lookup result id as lookupId and call web_search with query "Braintrust Flue reasoning stream instrumentation".', + "Step 3: use the first web_search result url and call summarize_source.", + "After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + ].join(" "), + { + model: fluePromptModel(), + thinkingLevel: fluePromptThinkingLevel(), + tools: [lookupTool, webSearchTool, summarizeSourceTool], + }, + ); + + await skillSession.skill("e2e-flue-skill", { + args: { marker: "SKILL_DONE" }, + model: flueReasoningModel(), + thinkingLevel: "off", + }); + + await taskSession.task("Reply with exactly TASK_DONE and no other text.", { + model: FLUE_MODEL, + thinkingLevel: "off", + }); + + await session.compact(); + + return { + scenario: payload?.scenario ?? SCENARIO_NAME, + status: "done", + }; +} diff --git a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-auto-hook.cassette.json b/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-auto-hook.cassette.json deleted file mode 100644 index 51f7e3225..000000000 --- a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-auto-hook.cassette.json +++ /dev/null @@ -1,2348 +0,0 @@ -{ - "entries": [ - { - "callIndex": 0, - "id": "fcd9d51c145fb90b", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:16.879Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01DgnJ1WxXezkCZXuWV4N4UV\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":2184,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":8,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"The user wants me to complete a specific\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" instrumented research flow with these steps:\\n1. Call lookup with query \\\"flue instrumentation\\\"\\n2. Use the lookup result id as lookupId and\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" call web_search with query \\\"Braintrust Flue reasoning stream instrumentation\\\"\\n3. Use the first web_search result url and call summarize_source\\n4. After summarize_source returns, reply with exactly \\\"PROMPT_DONE\\\" and no\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" other text\\n\\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" with step 1.\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll complete this instrumented research flow step by step. Starting with step\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\" 1:\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01QHXkUBddKx6pexY4WSjMR1\",\"name\":\"lookup\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"query\\\": \\\"flue instrumentation\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":2184,\"output_tokens\":208}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:13Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:13Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:13Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:13Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c3e0d7f5db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:14 GMT", - "request-id": "req_011CbHGiiBgdQNkASsMRCwgj", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-6da7462cb717a4ab8a48b5d921204a81-14185ff13cd15781-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1122", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 1, - "id": "ff22a182ea5a9c06", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:19.986Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - "type": "text" - }, - { - "id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01S7r43QJxMWSvMAaBeLZgV4\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":248,\"cache_read_input_tokens\":2184,\"cache_creation\":{\"ephemeral_5m_input_tokens\":248,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Good\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\", I got the lookup result with id \\\"flue-session-2026\\\". Now I need to proceed to step 2: call\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" web_search with this lookupId and the query \\\"Braintrust Flue reasoning stream instrumentation\\\".\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"Now proce\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"eding to step 2:\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01CvT1mSWwETua7LWwSQiyq6\",\"name\":\"web_search\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"lookupId\\\": \\\"flue-session-2026\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\", \\\"query\\\": \\\"Br\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"aintrust Flue reasoning stream instrumentation\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":248,\"cache_read_input_tokens\":2184,\"output_tokens\":158}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:17Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:17Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:17Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:17Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c54d9545db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:18 GMT", - "request-id": "req_011CbHGiyn3iTHWVPAkpZhcY", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-4cdb6d6d0536e1b2d282935aec231b2f-a96d2334e551f8ea-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1178", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 2, - "id": "f1d50a1e6c760d6c", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:23.056Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - "type": "text" - }, - { - "id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==", - "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", - "type": "thinking" - }, - { - "text": "Now proceeding to step 2:", - "type": "text" - }, - { - "id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "name": "web_search", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "is_error": false, - "tool_use_id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01GTvJuwvfvP5uhxvUX85xDb\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":234,\"cache_read_input_tokens\":2432,\"cache_creation\":{\"ephemeral_5m_input_tokens\":234,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Perfect\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"! I got the web_search results. There's one result with the\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" URL \\\"https://example.test/flue/reasoning-streams\\\". Now I need to proceed to step 3: call summarize_source with this URL.\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EowDCm4IDRgCKkCpqmoUHjbaZYvB4bWm+hVDlxgU/iOCEn0v3xAMT4QsjKM7cIZMOWD2eEF8ENjGq0ttAvO8ZNI9YpiASikG2gnNMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI5+VQnffadMSNsXEGgy1YAi10m6jJ39wq2UiMAUy8rg67GdkT4VUKix3ULTWnPfKucap7VLRPGDqK7ZhF0nDl2pcYGshMviSbzOjuyrLAXh3IPAAc3rvDuYAAHaWed6JE7/4gg/gzWhfVeAb0qXzXoiIHh8Z9KyHDfDDfpesr4TzmJHT/T8mhem3UfZc87ZLzFom8Vi+76Y2eVWcoI/EyPuyj+KVxU5kPh030LYWxUeSTUViRu9NAd+Wzz/5ZAgD+TiEmCnpNMI3eGqOiBPtwK7y/JIvxZRWvsJ1ghXNaEVShN3h8OUk9zmzIhBuUujWVZtc5wuM28726mOqMLwKckegl+q2vNrR+U+AqbMSYWUVlWLKZvd1LXiZGAE=\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"Now proce\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"eding to step 3:\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01NHkkJuQNXyRuWk58FCecye\",\"name\":\"summarize_source\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"url\\\": \\\"https://example.test/flue/reasoning-streams\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":234,\"cache_read_input_tokens\":2432,\"output_tokens\":132}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:20Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:20Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:20Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:20Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c684d5d5db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:21 GMT", - "request-id": "req_011CbHGjD7jNriq9KH2cWiZX", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-2bfd6efb042ad6f4d2349d2a08779605-538e2a8207df00c0-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1330", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 3, - "id": "305957222aa1f6e9", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:25.313Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - "type": "text" - }, - { - "id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==", - "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", - "type": "thinking" - }, - { - "text": "Now proceeding to step 2:", - "type": "text" - }, - { - "id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "name": "web_search", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "is_error": false, - "tool_use_id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EowDCm4IDRgCKkCpqmoUHjbaZYvB4bWm+hVDlxgU/iOCEn0v3xAMT4QsjKM7cIZMOWD2eEF8ENjGq0ttAvO8ZNI9YpiASikG2gnNMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI5+VQnffadMSNsXEGgy1YAi10m6jJ39wq2UiMAUy8rg67GdkT4VUKix3ULTWnPfKucap7VLRPGDqK7ZhF0nDl2pcYGshMviSbzOjuyrLAXh3IPAAc3rvDuYAAHaWed6JE7/4gg/gzWhfVeAb0qXzXoiIHh8Z9KyHDfDDfpesr4TzmJHT/T8mhem3UfZc87ZLzFom8Vi+76Y2eVWcoI/EyPuyj+KVxU5kPh030LYWxUeSTUViRu9NAd+Wzz/5ZAgD+TiEmCnpNMI3eGqOiBPtwK7y/JIvxZRWvsJ1ghXNaEVShN3h8OUk9zmzIhBuUujWVZtc5wuM28726mOqMLwKckegl+q2vNrR+U+AqbMSYWUVlWLKZvd1LXiZGAE=", - "thinking": "Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", - "type": "thinking" - }, - { - "text": "Now proceeding to step 3:", - "type": "text" - }, - { - "id": "toolu_01NHkkJuQNXyRuWk58FCecye", - "input": { - "url": "https://example.test/flue/reasoning-streams" - }, - "name": "summarize_source", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "is_error": false, - "tool_use_id": "toolu_01NHkkJuQNXyRuWk58FCecye", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01DePVY82UbrSeVG6FmJbDAw\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":188,\"cache_read_input_tokens\":2666,\"cache_creation\":{\"ephemeral_5m_input_tokens\":188,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"The\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" summarize_source has returned successfully. According to the instructions, I should now reply with exactly\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" \\\"PROMPT_DONE\\\" and no other text.\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EuACCm4IDRgCKkBFFJkLPfdTPaxLI9uliA7Q7HFBV/YIU6/QTIWGrMPbGdbjMR8KXKHC6r4UKTpeAOTR7R0lZ9V3T1GHMwGw0zKUMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMoQyoPhCL7TEv5y6rGgxRN3h6q4vat+wUsB8iME6oLmgjwKuqei/kSCgs/uSR4fB7DLTS+EWcZrZOU1fvrPQ2h7oAwtExZ72a5gucgyqfAVk0ULeWED//olNSNP/7YqX+iYj3K81eZMwKNeOdFICjK4lA9BtxcyI9wgLfu8b/z9DTMh/DO9l+RUVzcLGLgaer+kHbj4qXH9ihYoQOstrdkHRihi9W7oXOUe9xn34XbrvVtsnWmXZWLx0lWbX6xr1E/T5WYb3/d4R1o02dIamFgB/u5Xaw7w1SzgzQZdHFQ3KgkuSkCohay00zaMbkyRgB\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"PROMPT_DONE\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":188,\"cache_read_input_tokens\":2666,\"output_tokens\":48}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2998000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:23Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:23Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:23Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3598000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:23Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c7b99075db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:24 GMT", - "request-id": "req_011CbHGjSJVD4R2rgh6TmzGF", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-21d68585e85af0175a50663b297e1a1c-b80e62b25474b64f-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1213", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 4, - "id": "3d93fe37f72a947f", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:27.558Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "thinking": { - "type": "disabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01VMLMxbJcjsVPZkWat83Xxs\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":1811,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":3,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll read\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" the skill file and execute it according to its instructions.\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01HmmsNYZUC67GqVoKKLbfiQ\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"agents/skills/e2e-flue-skill/SKILL.md\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":1811,\"output_tokens\":83}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:25Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:25Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:25Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:25Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c898c435db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:26 GMT", - "request-id": "req_011CbHGjbpDzh7hV47HWeiWq", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-e2983bef9d410175021182eb9be77d7a-c77c00237b48e432-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1249", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 5, - "id": "fb4ed2bb1569d980", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:29.044Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "text": "I'll read the skill file and execute it according to its instructions.", - "type": "text" - }, - { - "id": "toolu_01HmmsNYZUC67GqVoKKLbfiQ", - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "name": "read", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "is_error": false, - "tool_use_id": "toolu_01HmmsNYZUC67GqVoKKLbfiQ", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "thinking": { - "type": "disabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01TaPPFSvzUDKTNU8n4TA2Ub\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":147,\"cache_read_input_tokens\":1811,\"cache_creation\":{\"ephemeral_5m_input_tokens\":147,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":7,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"SKILL_DONE\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":147,\"cache_read_input_tokens\":1811,\"output_tokens\":8}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:27Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:27Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:27Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:27Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c97bf115db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:28 GMT", - "request-id": "req_011CbHGjmZcbfZvsk78nq5vh", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-d1ba118962f5cad41869cc135494676d-a3266ad88f2939d3-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1209", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 0, - "id": "7c0e162d6794cf5d", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:30.439Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly TASK_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "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_077d996caec5e196016a10102959d4819ca5fb0b8d10048c4b\",\"object\":\"response\",\"created_at\":1779437609,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:f2db752a-32d6-408a-8d80-c1\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_077d996caec5e196016a10102959d4819ca5fb0b8d10048c4b\",\"object\":\"response\",\"created_at\":1779437609,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:f2db752a-32d6-408a-8d80-c1\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"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_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"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\":\"TASK\",\"item_id\":\"msg_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"logprobs\":[],\"obfuscation\":\"hxGcDEHJs4KI\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"_DONE\",\"item_id\":\"msg_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"logprobs\":[],\"obfuscation\":\"codL24VwzOS\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":6,\"text\":\"TASK_DONE\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"},\"sequence_number\":7}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":8}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_077d996caec5e196016a10102959d4819ca5fb0b8d10048c4b\",\"object\":\"response\",\"created_at\":1779437609,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437610,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_077d996caec5e196016a10102a47f8819c9406a2757082ab93\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::task:task:f2db752a-32d6-408a-8d80-c1\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":772,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":4,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":776},\"user\":null,\"metadata\":{}},\"sequence_number\":9}" - ], - "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": "9ffa5ca18a7b325f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:29 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "100", - "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": "req_34e75f7714614368ad57a8ab8c02e0c8" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 1, - "id": "f12aff3913439248", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:33.761Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "max_output_tokens": 32, - "model": "gpt-4o-mini", - "store": false, - "stream": true - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.openai.com/v1/responses" - }, - "response": { - "body": { - "chunks": [ - "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0f13e60caaeaeacb016a10102c8f708192978116e1c09c1c36\",\"object\":\"response\",\"created_at\":1779437612,\"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\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_0f13e60caaeaeacb016a10102c8f708192978116e1c09c1c36\",\"object\":\"response\",\"created_at\":1779437612,\"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\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"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_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"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_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"Zk5AP95xcgbrGq\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Original\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"JNmcRGZ\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Request\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"O7K5LBG6\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\n\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"fPX8shnMg91RYfg\",\"output_index\":0,\"sequence_number\":7}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"The\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"jvcL8meen0c6o\",\"output_index\":0,\"sequence_number\":8}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" user\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"IizuQ41krNa\",\"output_index\":0,\"sequence_number\":9}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" asked\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"WDyPRAeBfW\",\"output_index\":0,\"sequence_number\":10}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" to\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"bpf69o4XuhkAp\",\"output_index\":0,\"sequence_number\":11}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" complete\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"rPuf3k4\",\"output_index\":0,\"sequence_number\":12}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" a\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"kYuPX1nF7hdhQ9\",\"output_index\":0,\"sequence_number\":13}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" step\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"PmeaAOmKg01\",\"output_index\":0,\"sequence_number\":14}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"-by\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"a7Th77M6ZkqdB\",\"output_index\":0,\"sequence_number\":15}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"-step\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"7TkDxFNqlk0\",\"output_index\":0,\"sequence_number\":16}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" instrument\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"4Mspa\",\"output_index\":0,\"sequence_number\":17}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"ed\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"HeGlAZhCYDVwdu\",\"output_index\":0,\"sequence_number\":18}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" research\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"YyNgo2g\",\"output_index\":0,\"sequence_number\":19}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" flow\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"jyMxpRIPzee\",\"output_index\":0,\"sequence_number\":20}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" involving\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"i8dhLo\",\"output_index\":0,\"sequence_number\":21}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" lookup\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"QCW8VTMVe\",\"output_index\":0,\"sequence_number\":22}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"SeZZTXzqYNq9c4A\",\"output_index\":0,\"sequence_number\":23}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" web\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"3QdpjI62mx20\",\"output_index\":0,\"sequence_number\":24}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" search\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"y3dJPx6HJ\",\"output_index\":0,\"sequence_number\":25}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"izeNndQAHqG88Pp\",\"output_index\":0,\"sequence_number\":26}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" and\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"t9sZc5kj0STX\",\"output_index\":0,\"sequence_number\":27}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" summar\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"udbTkclSA\",\"output_index\":0,\"sequence_number\":28}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"ization\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"IHcrLKrJv\",\"output_index\":0,\"sequence_number\":29}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"7nRT45jNwn0jJ2o\",\"output_index\":0,\"sequence_number\":30}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" with\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"NMmxDIFt2A0\",\"output_index\":0,\"sequence_number\":31}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" specific\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"3bSfcsA\",\"output_index\":0,\"sequence_number\":32}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" instructions\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"atz\",\"output_index\":0,\"sequence_number\":33}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" to\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"ConWkiFhiR8RW\",\"output_index\":0,\"sequence_number\":34}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" call\",\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"obfuscation\":\"YPgRMyQB0QX\",\"output_index\":0,\"sequence_number\":35}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":36,\"text\":\"## Original Request\\nThe user asked to complete a step-by-step instrumented research flow involving lookup, web search, and summarization, with specific instructions to call\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user asked to complete a step-by-step instrumented research flow involving lookup, web search, and summarization, with specific instructions to call\"},\"sequence_number\":37}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user asked to complete a step-by-step instrumented research flow involving lookup, web search, and summarization, with specific instructions to call\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":38}", - "event: response.incomplete\ndata: {\"type\":\"response.incomplete\",\"response\":{\"id\":\"resp_0f13e60caaeaeacb016a10102c8f708192978116e1c09c1c36\",\"object\":\"response\",\"created_at\":1779437612,\"status\":\"incomplete\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":{\"reason\":\"max_output_tokens\"},\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0f13e60caaeaeacb016a10102d25e88192992dbed19f1be674\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user asked to complete a step-by-step instrumented research flow involving lookup, web search, and summarization, with specific instructions to call\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":698,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":32,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":730},\"user\":null,\"metadata\":{}},\"sequence_number\":39}" - ], - "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": "9ffa5ca999d4325f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:32 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "232", - "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": "req_16e0d0181a854084b110ca11cb77b277" - }, - "status": 200, - "statusText": "OK" - } - } - ], - "meta": { - "createdAt": "2026-05-20T19:15:29.584Z" - } -} diff --git a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-openai-auto-hook.cassette.json b/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-openai-auto-hook.cassette.json deleted file mode 100644 index cff45539d..000000000 --- a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-openai-auto-hook.cassette.json +++ /dev/null @@ -1,2145 +0,0 @@ -{ - "entries": [ - { - "callIndex": 0, - "id": "7c0e162d6794cf5d", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:35.865Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "name": "lookup", - "parameters": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "name": "web_search", - "parameters": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "name": "summarize_source", - "parameters": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "strict": false, - "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_0a9628fdef0a9b50016a10102ef6ec8190aea42c9384815417\",\"object\":\"response\",\"created_at\":1779437614,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a10102ef6ec8190aea42c9384815417\",\"object\":\"response\",\"created_at\":1779437614,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_xELft1kjhTSvPWAp3Z3i4zWk\",\"name\":\"lookup\"},\"output_index\":0,\"sequence_number\":2}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"kdHmbne8Odsv0r\",\"output_index\":0,\"sequence_number\":3}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"query\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"cakQ2rzCmLJ\",\"output_index\":0,\"sequence_number\":4}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"N775rFu16y6Ut\",\"output_index\":0,\"sequence_number\":5}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"fl\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"zewsf7KenGBc5O\",\"output_index\":0,\"sequence_number\":6}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"ue\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"kUL7Os9Ms5z87q\",\"output_index\":0,\"sequence_number\":7}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" instrumentation\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"\",\"output_index\":0,\"sequence_number\":8}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"obfuscation\":\"WQCLmfqjC6qVKE\",\"output_index\":0,\"sequence_number\":9}", - "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"query\\\":\\\"flue instrumentation\\\"}\",\"item_id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"output_index\":0,\"sequence_number\":10}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"query\\\":\\\"flue instrumentation\\\"}\",\"call_id\":\"call_xELft1kjhTSvPWAp3Z3i4zWk\",\"name\":\"lookup\"},\"output_index\":0,\"sequence_number\":11}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0a9628fdef0a9b50016a10102ef6ec8190aea42c9384815417\",\"object\":\"response\",\"created_at\":1779437614,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437615,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"query\\\":\\\"flue instrumentation\\\"}\",\"call_id\":\"call_xELft1kjhTSvPWAp3Z3i4zWk\",\"name\":\"lookup\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":946,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":16,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":962},\"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": "9ffa5cc4dc2f325f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:35 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "195", - "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": "req_d8c4fb03ab4a4920a732debcff08914b" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 1, - "id": "f12aff3913439248", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:36.926Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - }, - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea", - "name": "lookup", - "type": "function_call" - }, - { - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "function_call_output" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "name": "lookup", - "parameters": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "name": "web_search", - "parameters": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "name": "summarize_source", - "parameters": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "strict": false, - "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_0a9628fdef0a9b50016a1010300e24819095d12ec72332326f\",\"object\":\"response\",\"created_at\":1779437616,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a1010300e24819095d12ec72332326f\",\"object\":\"response\",\"created_at\":1779437616,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_F7zI4fCOw4jk7rTwqbi8umo7\",\"name\":\"web_search\"},\"output_index\":0,\"sequence_number\":2}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"D8DIbFMFfKgIqR\",\"output_index\":0,\"sequence_number\":3}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"lookup\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"oRLHzvqUcC\",\"output_index\":0,\"sequence_number\":4}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Id\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"ctWwYaf4enBlpn\",\"output_index\":0,\"sequence_number\":5}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"Bxex01CZf30mb\",\"output_index\":0,\"sequence_number\":6}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"fl\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"W5EpmSSJSRsh1B\",\"output_index\":0,\"sequence_number\":7}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"ue\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"RXJ3GtNcFEZC3L\",\"output_index\":0,\"sequence_number\":8}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"-session\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"FrptSujR\",\"output_index\":0,\"sequence_number\":9}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"-\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"AOP9L65fcROFADX\",\"output_index\":0,\"sequence_number\":10}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"202\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"4LfPsWU122uTC\",\"output_index\":0,\"sequence_number\":11}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"6\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"a35P79vWwEKC2ZE\",\"output_index\":0,\"sequence_number\":12}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\",\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"tUGGlNr5jHxmu\",\"output_index\":0,\"sequence_number\":13}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"query\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"GmSsogR2hlQ\",\"output_index\":0,\"sequence_number\":14}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"lrY20FxVrF4u8\",\"output_index\":0,\"sequence_number\":15}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"Brain\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"v9CxBEQbCS9\",\"output_index\":0,\"sequence_number\":16}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"trust\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"6i98iwGq0O6\",\"output_index\":0,\"sequence_number\":17}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" Fl\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"uZPT710a30mTB\",\"output_index\":0,\"sequence_number\":18}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"ue\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"U35GKeW5iDdc4n\",\"output_index\":0,\"sequence_number\":19}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" reasoning\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"WrQDfZ\",\"output_index\":0,\"sequence_number\":20}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" stream\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"PuhQQRxiZ\",\"output_index\":0,\"sequence_number\":21}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\" instrumentation\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"\",\"output_index\":0,\"sequence_number\":22}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"obfuscation\":\"xpwncQL0D58C6q\",\"output_index\":0,\"sequence_number\":23}", - "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"lookupId\\\":\\\"flue-session-2026\\\",\\\"query\\\":\\\"Braintrust Flue reasoning stream instrumentation\\\"}\",\"item_id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"output_index\":0,\"sequence_number\":24}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"lookupId\\\":\\\"flue-session-2026\\\",\\\"query\\\":\\\"Braintrust Flue reasoning stream instrumentation\\\"}\",\"call_id\":\"call_F7zI4fCOw4jk7rTwqbi8umo7\",\"name\":\"web_search\"},\"output_index\":0,\"sequence_number\":25}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0a9628fdef0a9b50016a1010300e24819095d12ec72332326f\",\"object\":\"response\",\"created_at\":1779437616,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437616,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"lookupId\\\":\\\"flue-session-2026\\\",\\\"query\\\":\\\"Braintrust Flue reasoning stream instrumentation\\\"}\",\"call_id\":\"call_F7zI4fCOw4jk7rTwqbi8umo7\",\"name\":\"web_search\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":987,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":31,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":1018},\"user\":null,\"metadata\":{}},\"sequence_number\":26}" - ], - "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": "9ffa5ccb9b77325f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:36 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "128", - "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": "req_c40d10c0c5cb48f39a473dbbfdf4ba74" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 2, - "id": "5d2312f425df9f2f", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:38.150Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - }, - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea", - "name": "lookup", - "type": "function_call" - }, - { - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "function_call_output" - }, - { - "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "id": "fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc", - "name": "web_search", - "type": "function_call" - }, - { - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "output": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "function_call_output" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "name": "lookup", - "parameters": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "name": "web_search", - "parameters": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "name": "summarize_source", - "parameters": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "strict": false, - "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_0a9628fdef0a9b50016a1010311bb0819090a41f2b4f42dca1\",\"object\":\"response\",\"created_at\":1779437617,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a1010311bb0819090a41f2b4f42dca1\",\"object\":\"response\",\"created_at\":1779437617,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"type\":\"function_call\",\"status\":\"in_progress\",\"arguments\":\"\",\"call_id\":\"call_0yinp9edeamv8mKgyhkpaCmG\",\"name\":\"summarize_source\"},\"output_index\":0,\"sequence_number\":2}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"{\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"8FFpGF2J29ZOHN\",\"output_index\":0,\"sequence_number\":3}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"url\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"d4fdn4AecZ46t\",\"output_index\":0,\"sequence_number\":4}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\":\\\"\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"rPDoeTBqETi8O\",\"output_index\":0,\"sequence_number\":5}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"https\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"8WF5UppFrHy\",\"output_index\":0,\"sequence_number\":6}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"://\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"PPdSqQktTJe91\",\"output_index\":0,\"sequence_number\":7}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"example\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"jZPIqHEcp\",\"output_index\":0,\"sequence_number\":8}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\".test\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"bnsPzoqO82F\",\"output_index\":0,\"sequence_number\":9}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"/fl\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"dvYhn8RmAWcKF\",\"output_index\":0,\"sequence_number\":10}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"ue\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"GcZKFcsouE5Bux\",\"output_index\":0,\"sequence_number\":11}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"/re\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"JPhCoN74iLW66\",\"output_index\":0,\"sequence_number\":12}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"ason\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"YyLaL8Gys893\",\"output_index\":0,\"sequence_number\":13}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"ing\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"T1KVZueZc1kD3\",\"output_index\":0,\"sequence_number\":14}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"-stream\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"W0Dx2W85S\",\"output_index\":0,\"sequence_number\":15}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"s\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"VS7LtwoGUsSOG0P\",\"output_index\":0,\"sequence_number\":16}", - "event: response.function_call_arguments.delta\ndata: {\"type\":\"response.function_call_arguments.delta\",\"delta\":\"\\\"}\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"obfuscation\":\"jvRLaiM8JWmd7e\",\"output_index\":0,\"sequence_number\":17}", - "event: response.function_call_arguments.done\ndata: {\"type\":\"response.function_call_arguments.done\",\"arguments\":\"{\\\"url\\\":\\\"https://example.test/flue/reasoning-streams\\\"}\",\"item_id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"output_index\":0,\"sequence_number\":18}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"url\\\":\\\"https://example.test/flue/reasoning-streams\\\"}\",\"call_id\":\"call_0yinp9edeamv8mKgyhkpaCmG\",\"name\":\"summarize_source\"},\"output_index\":0,\"sequence_number\":19}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0a9628fdef0a9b50016a1010311bb0819090a41f2b4f42dca1\",\"object\":\"response\",\"created_at\":1779437617,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437617,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d\",\"type\":\"function_call\",\"status\":\"completed\",\"arguments\":\"{\\\"url\\\":\\\"https://example.test/flue/reasoning-streams\\\"}\",\"call_id\":\"call_0yinp9edeamv8mKgyhkpaCmG\",\"name\":\"summarize_source\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":1070,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":27,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":1097},\"user\":null,\"metadata\":{}},\"sequence_number\":20}" - ], - "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": "9ffa5cd21ac7325f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:37 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "165", - "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": "req_f5d74822605549e496e2bcbab5a75621" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 3, - "id": "83cbbf6da482c905", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:39.243Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - }, - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "fc_0a9628fdef0a9b50016a10102fa3308190bfb69b9815d024ea", - "name": "lookup", - "type": "function_call" - }, - { - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "function_call_output" - }, - { - "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "id": "fc_0a9628fdef0a9b50016a101030aa2c8190a6b053f73ee55abc", - "name": "web_search", - "type": "function_call" - }, - { - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "output": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "function_call_output" - }, - { - "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - "id": "fc_0a9628fdef0a9b50016a101031b3fc8190aeb5142bbecd534d", - "name": "summarize_source", - "type": "function_call" - }, - { - "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - "output": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "type": "function_call_output" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "name": "lookup", - "parameters": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "name": "web_search", - "parameters": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "name": "summarize_source", - "parameters": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "strict": false, - "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_0a9628fdef0a9b50016a10103257648190a7953ff23a5d2fb1\",\"object\":\"response\",\"created_at\":1779437618,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a10103257648190a7953ff23a5d2fb1\",\"object\":\"response\",\"created_at\":1779437618,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"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_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"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_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"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\":\"PROM\",\"item_id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"logprobs\":[],\"obfuscation\":\"aIGxUUBY6YDG\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"PT\",\"item_id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"logprobs\":[],\"obfuscation\":\"oYlmnvntzpbIvZ\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"_DONE\",\"item_id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"logprobs\":[],\"obfuscation\":\"70Nz1XwODHd\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":7,\"text\":\"PROMPT_DONE\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"PROMPT_DONE\"},\"sequence_number\":8}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"PROMPT_DONE\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":9}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0a9628fdef0a9b50016a10103257648190a7953ff23a5d2fb1\",\"object\":\"response\",\"created_at\":1779437618,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437619,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0a9628fdef0a9b50016a10103302208190a4d993aaf77f70f7\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"PROMPT_DONE\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::main\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Return a deterministic lookup result with an id needed by web_search.\",\"name\":\"lookup\",\"parameters\":{\"type\":\"object\",\"required\":[\"query\"],\"properties\":{\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search a deterministic local web index. Requires the id returned by lookup.\",\"name\":\"web_search\",\"parameters\":{\"type\":\"object\",\"required\":[\"lookupId\",\"query\"],\"properties\":{\"lookupId\":{\"type\":\"string\"},\"query\":{\"type\":\"string\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Summarize the selected deterministic source after web_search returns a URL.\",\"name\":\"summarize_source\",\"parameters\":{\"type\":\"object\",\"required\":[\"url\"],\"properties\":{\"url\":{\"type\":\"string\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":1136,\"input_tokens_details\":{\"cached_tokens\":1024},\"output_tokens\":5,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":1141},\"user\":null,\"metadata\":{}},\"sequence_number\":10}" - ], - "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": "9ffa5cd9cadf325f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:38 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "119", - "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": "req_3c035efb7de544a1ac3234bcc350ad16" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 0, - "id": "fcd9d51c145fb90b", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:44.842Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "thinking": { - "type": "disabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01462yLZ8F2ESqxQn7Z9PN3f\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":1811,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":8,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll run the e2e-\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"flue-skill by reading its instructions and following them.\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01M5rfFBDvwquiyfz2B1GNYz\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents/skills/e2e-flue-skill/SKILL.md\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":1811,\"output_tokens\":89}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:42Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:42Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:42Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:42Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5cf589335bad-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:43 GMT", - "request-id": "req_011CbHGksnSn5d7nngACrqDc", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-006501fbd24eb2c22ba9da9d184a6314-1a3c07e594884bf9-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1157", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 1, - "id": "ff22a182ea5a9c06", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:49.530Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "text": "I'll run the e2e-flue-skill by reading its instructions and following them.", - "type": "text" - }, - { - "id": "toolu_01M5rfFBDvwquiyfz2B1GNYz", - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "name": "read", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "is_error": false, - "tool_use_id": "toolu_01M5rfFBDvwquiyfz2B1GNYz", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "thinking": { - "type": "disabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01PPxairsbrK6f4zFxdfAAqS\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":1964,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":7,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"SKILL_DONE\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":1964,\"output_tokens\":8}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:45Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:45Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:45Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:45Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5d0399785bad-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:49 GMT", - "request-id": "req_011CbHGm3PeHPrCu5QbjecNn", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-7d974f6ca2035b3d9c8496d4b11ebfd8-fdf893f5e03b8809-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "4327", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 4, - "id": "417e64addcf59da7", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:50.457Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly TASK_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "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_0800f965cc2ee3bf016a10103dc8c881a095690ba4dc3b63cd\",\"object\":\"response\",\"created_at\":1779437629,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:6ace14f1-2bce-44f2-afa7-ec\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_0800f965cc2ee3bf016a10103dc8c881a095690ba4dc3b63cd\",\"object\":\"response\",\"created_at\":1779437629,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:6ace14f1-2bce-44f2-afa7-ec\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"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_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"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\":\"TASK\",\"item_id\":\"msg_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"logprobs\":[],\"obfuscation\":\"Go0E8XPESm7z\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"_DONE\",\"item_id\":\"msg_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"logprobs\":[],\"obfuscation\":\"c8DB1CtA3S6\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":6,\"text\":\"TASK_DONE\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"},\"sequence_number\":7}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":8}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_0800f965cc2ee3bf016a10103dc8c881a095690ba4dc3b63cd\",\"object\":\"response\",\"created_at\":1779437629,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437630,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0800f965cc2ee3bf016a10103e460c81a0a9f3a24e59af07c2\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::task:task:6ace14f1-2bce-44f2-afa7-ec\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":772,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":4,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":776},\"user\":null,\"metadata\":{}},\"sequence_number\":9}" - ], - "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": "9ffa5d21691b804e-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:49 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "147", - "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": "req_263405117afd4b089db94fe44182edb4" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 5, - "id": "341675a0a1a88c63", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:51.643Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "max_output_tokens": 32, - "model": "gpt-4o-mini", - "store": false, - "stream": true - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.openai.com/v1/responses" - }, - "response": { - "body": { - "chunks": [ - "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_084209f23358c95f016a10103e99148191bdeabe7e91f87320\",\"object\":\"response\",\"created_at\":1779437630,\"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\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_084209f23358c95f016a10103e99148191bdeabe7e91f87320\",\"object\":\"response\",\"created_at\":1779437630,\"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\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"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_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"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_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"M3AlJ8uMZsMVoT\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Original\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"YRs1ktR\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Request\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"G9k88ga0\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\n\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"UdQRtbAIKPoI5Km\",\"output_index\":0,\"sequence_number\":7}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"The\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"lU0pjFQSm1oEq\",\"output_index\":0,\"sequence_number\":8}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" user\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"tYWoiXmPt3i\",\"output_index\":0,\"sequence_number\":9}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" requested\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"UGYnE6\",\"output_index\":0,\"sequence_number\":10}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" to\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"Y8c0jT6nW4GwE\",\"output_index\":0,\"sequence_number\":11}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" complete\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"0YSVIf1\",\"output_index\":0,\"sequence_number\":12}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" an\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"2lzdKxno9owFI\",\"output_index\":0,\"sequence_number\":13}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" instrument\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"Yk3lI\",\"output_index\":0,\"sequence_number\":14}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"ed\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"yNJ7UNf6JCrgfT\",\"output_index\":0,\"sequence_number\":15}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" research\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"h6fKawz\",\"output_index\":0,\"sequence_number\":16}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" flow\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"RobYTvkiCGN\",\"output_index\":0,\"sequence_number\":17}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" involving\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"NUS4Lz\",\"output_index\":0,\"sequence_number\":18}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" multiple\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"AGsmURG\",\"output_index\":0,\"sequence_number\":19}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" steps\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"W5EQuh9xDq\",\"output_index\":0,\"sequence_number\":20}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" using\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"HBLHpXQoEi\",\"output_index\":0,\"sequence_number\":21}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" tool\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"PdXhCFHWTZ4\",\"output_index\":0,\"sequence_number\":22}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" calls\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"EYtOQjpO1R\",\"output_index\":0,\"sequence_number\":23}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" for\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"0lXKd0r4r8cU\",\"output_index\":0,\"sequence_number\":24}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" gathering\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"ovBPeL\",\"output_index\":0,\"sequence_number\":25}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" information\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"SVxw\",\"output_index\":0,\"sequence_number\":26}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" about\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"0LRneRdeVW\",\"output_index\":0,\"sequence_number\":27}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" \\\"\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"vz8P6a81mJNQMW\",\"output_index\":0,\"sequence_number\":28}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"fl\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"dla16TkzpV6RXX\",\"output_index\":0,\"sequence_number\":29}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"ue\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"Fu8Auj66IJgtKJ\",\"output_index\":0,\"sequence_number\":30}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" instrumentation\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"\",\"output_index\":0,\"sequence_number\":31}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\".\\\"\\n\\n\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"2kTOhzqCpyYt\",\"output_index\":0,\"sequence_number\":32}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"##\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"VMTlx6jKXne4i6\",\"output_index\":0,\"sequence_number\":33}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Early\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"NKfnbY22gK\",\"output_index\":0,\"sequence_number\":34}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Progress\",\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"obfuscation\":\"j26oekx\",\"output_index\":0,\"sequence_number\":35}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":36,\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow involving multiple steps using tool calls for gathering information about \\\"flue instrumentation.\\\"\\n\\n## Early Progress\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow involving multiple steps using tool calls for gathering information about \\\"flue instrumentation.\\\"\\n\\n## Early Progress\"},\"sequence_number\":37}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow involving multiple steps using tool calls for gathering information about \\\"flue instrumentation.\\\"\\n\\n## Early Progress\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":38}", - "event: response.incomplete\ndata: {\"type\":\"response.incomplete\",\"response\":{\"id\":\"resp_084209f23358c95f016a10103e99148191bdeabe7e91f87320\",\"object\":\"response\",\"created_at\":1779437630,\"status\":\"incomplete\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":{\"reason\":\"max_output_tokens\"},\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_084209f23358c95f016a10103efe4c819198d1e2ffc5e641b7\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow involving multiple steps using tool calls for gathering information about \\\"flue instrumentation.\\\"\\n\\n## Early Progress\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":446,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":32,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":478},\"user\":null,\"metadata\":{}},\"sequence_number\":39}" - ], - "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": "9ffa5d26bae4804e-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:50 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "74", - "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": "req_cf1aa4da0406473ba47a8cddb664cb57" - }, - "status": 200, - "statusText": "OK" - } - } - ], - "meta": { - "createdAt": "2026-05-22T08:11:35.765Z" - } -} diff --git a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-wrapped.cassette.json b/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-wrapped.cassette.json deleted file mode 100644 index 84205d215..000000000 --- a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-7-0-wrapped.cassette.json +++ /dev/null @@ -1,2345 +0,0 @@ -{ - "entries": [ - { - "callIndex": 0, - "id": "fcd9d51c145fb90b", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:12:53.397Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01CABc2tEXNTVK5CC2yf1dBR\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":887,\"cache_read_input_tokens\":1297,\"cache_creation\":{\"ephemeral_5m_input_tokens\":887,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":6,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"The user wants me to complete\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" an instrumented research flow with specific steps:\\n1. Call lookup with query \\\"flue instrumentation\\\"\\n2. Use the lookup result id to call web_search with query \\\"Braintrust Flue reasoning stream instru\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"mentation\\\"\\n3. Use the first web_search result url to call summarize_source\\n4. After summarize_source returns, reply with exactly \\\"PROMPT_DONE\\\"\\n\\nI need to call\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" exactly one tool per turn and wait for each result. Let me start with step 1.\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EqEFCm4IDRgCKkCx4PeMntf8BRtpLH8OUwiMP53HIajGG0HN/LJgm9YmzwCzrRIdbPW6+RRfidn7le5y+DuWJ3BPl1JgKETNcGOcMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMgjs71MGxsxVHe7zLGgzslRkkjDTjHfOSe/QiMJwuB3ScB/LBWqEoaFVkSh1fQFtJgiUlle/UZtA34zfIz7K6LGnqxb1BZAkBKY2o6SrgA7XVIYhi9V8+7n5o2vSbR9Zu5X2ZL4DZxghVngkmw1K9A8fDUjAkwBV34qSMLqozFC4JbcWTpTHqw4HwJ43B4w8pYoeg67QyIwTtH4c+pU5Z6oMzC/9ruNsH/rb6sFceHQb/g/cUAmfV+S4feseEfrHeGpQwzx146NNee8FuICbOSdVDmUa90b+tzHzXjnolSPgMKFbCWX7lCFLbcfDaBxMNcX9BkOUSLfc4/utTn0C38rYhOKzK//A3al4mh5cxYaNZ73KatbFZL4MLPMuT9f44NswmPylRhtcUCgcjP1eal+E8lWzZjX+7DhAzpyPqUY1ZrUVV6GlTddiE3VapSGS5ixtIdgNW6X5jA2W5NiKB1WWaF6aH1PTWPa6PgKIf9+lpHFJcPeeqhskWHV+w9L7Wcjlm7uRg3B+uFBUyEfw1jgsX+wFfGfCq5rEbVk0jjeG498UD1CzeZwdlsKRA5/2laXqk8Migrbqbw95Bhm1D8muVTftvvPkmrBh9rH7Nh2qfgNKBAx5rtQikbnN8299/33EBXQ7CKzByr9aaLVt6CDX4+6m2qGwCi7gXCHur3n4fUZ/aAoo1xb58QUeXwQriGVBzMF5MZ3PuuDQaQTTOHcP0kzTJe4kiP7TWow+9TRgB\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll complete\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\" this instrumented research flow step by step. Starting with Step 1:\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01QcDKhyMNiU8Df4agjz1yt2\",\"name\":\"lookup\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"query\\\": \\\"flue instrumentation\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":887,\"cache_read_input_tokens\":1297,\"output_tokens\":198}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:12:48Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:12:48Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:12:48Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:12:48Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5ba3dd855db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:12:51 GMT", - "request-id": "req_011CbHGgtheP2Dveyaa7uo66", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-f3a9a8447ed937d2e123e98c32a04096-799d23e561c9e80a-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "2523", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 1, - "id": "ff22a182ea5a9c06", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:12:57.115Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EqEFCm4IDRgCKkCx4PeMntf8BRtpLH8OUwiMP53HIajGG0HN/LJgm9YmzwCzrRIdbPW6+RRfidn7le5y+DuWJ3BPl1JgKETNcGOcMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMgjs71MGxsxVHe7zLGgzslRkkjDTjHfOSe/QiMJwuB3ScB/LBWqEoaFVkSh1fQFtJgiUlle/UZtA34zfIz7K6LGnqxb1BZAkBKY2o6SrgA7XVIYhi9V8+7n5o2vSbR9Zu5X2ZL4DZxghVngkmw1K9A8fDUjAkwBV34qSMLqozFC4JbcWTpTHqw4HwJ43B4w8pYoeg67QyIwTtH4c+pU5Z6oMzC/9ruNsH/rb6sFceHQb/g/cUAmfV+S4feseEfrHeGpQwzx146NNee8FuICbOSdVDmUa90b+tzHzXjnolSPgMKFbCWX7lCFLbcfDaBxMNcX9BkOUSLfc4/utTn0C38rYhOKzK//A3al4mh5cxYaNZ73KatbFZL4MLPMuT9f44NswmPylRhtcUCgcjP1eal+E8lWzZjX+7DhAzpyPqUY1ZrUVV6GlTddiE3VapSGS5ixtIdgNW6X5jA2W5NiKB1WWaF6aH1PTWPa6PgKIf9+lpHFJcPeeqhskWHV+w9L7Wcjlm7uRg3B+uFBUyEfw1jgsX+wFfGfCq5rEbVk0jjeG498UD1CzeZwdlsKRA5/2laXqk8Migrbqbw95Bhm1D8muVTftvvPkmrBh9rH7Nh2qfgNKBAx5rtQikbnN8299/33EBXQ7CKzByr9aaLVt6CDX4+6m2qGwCi7gXCHur3n4fUZ/aAoo1xb58QUeXwQriGVBzMF5MZ3PuuDQaQTTOHcP0kzTJe4kiP7TWow+9TRgB", - "thinking": "The user wants me to complete an instrumented research flow with specific steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id to call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url to call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\"\n\nI need to call exactly one tool per turn and wait for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", - "type": "text" - }, - { - "id": "toolu_01QcDKhyMNiU8Df4agjz1yt2", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QcDKhyMNiU8Df4agjz1yt2", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_017nRwMuk7cCWy6y3kKL51vE\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":238,\"cache_read_input_tokens\":2184,\"cache_creation\":{\"ephemeral_5m_input_tokens\":238,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Good\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\", I got the lookup result with id \\\"flue-session-2026\\\". Now I need to proceed to Step 2 and use this\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" id as the lookupId parameter when calling web_search with the query \\\"Braintrust Flue reasoning stream instrumentation\\\".\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"ErADCm4IDRgCKkARgZnDUJ+PLc8xrFDS9ecUz7mwqLm2d3m/N8LK5Mk0rTAtu68mre/Pzn/ZhTi/qFz82Hb5mrxdEkiUqtsqivMhMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM5WDRxd0cfRc2Q7v+GgzP22/9gyiglVHjuwsiMOSnrkUVb3mbmhZUVIc50+orubOjsOtWSRq/NhvyKf/3R70oKKwvPoReenbhZDwjvyrvAVe1dnEhhRKcMZVeabb7qH3A63dU4KykFUas917GFUKUxaGHAd2cO1Ksy+Twz0glNwR7+TImTI9ph3FUKjqAQOoui2je0nCJ4ldrM40Lj10KkXKjxrBktO8lLbZffXB6tshrlThqPmLhgst9sIm/vXPI9/7YT+9Dq8I1Oeh5OQtmvyy0JRiWkaNnDXetugIxC2n4gqeplUkuez54nKt0c1la5q4PwA9MLcQItyNv3gv76iW2kLxwd4BtsxEOo0tma3CNuGrT5Xs0O1CwkguSXJpLKuMPWPu7ow1C3u9gVLguglKMPxR5HJmO1NqwGGxsGAE=\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"Now\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\" proceeding to Step 2 with the lookup ID:\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_0128czRSGDXRjPdjmHVgYk58\",\"name\":\"web_search\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"lookupId\\\": \\\"flue-session-2026\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\", \\\"query\\\": \\\"Braintrust Flue reasoning stream instrumentation\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":238,\"cache_read_input_tokens\":2184,\"output_tokens\":169}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:12:53Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:12:53Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:12:53Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:12:53Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5bc22b055db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:12:55 GMT", - "request-id": "req_011CbHGhFT52pJrjqgL8xPr2", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-c22ad5b71b29d497896e0adf1c6beda6-365b8174c6154769-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1643", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 2, - "id": "f1d50a1e6c760d6c", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:01.740Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EqEFCm4IDRgCKkCx4PeMntf8BRtpLH8OUwiMP53HIajGG0HN/LJgm9YmzwCzrRIdbPW6+RRfidn7le5y+DuWJ3BPl1JgKETNcGOcMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMgjs71MGxsxVHe7zLGgzslRkkjDTjHfOSe/QiMJwuB3ScB/LBWqEoaFVkSh1fQFtJgiUlle/UZtA34zfIz7K6LGnqxb1BZAkBKY2o6SrgA7XVIYhi9V8+7n5o2vSbR9Zu5X2ZL4DZxghVngkmw1K9A8fDUjAkwBV34qSMLqozFC4JbcWTpTHqw4HwJ43B4w8pYoeg67QyIwTtH4c+pU5Z6oMzC/9ruNsH/rb6sFceHQb/g/cUAmfV+S4feseEfrHeGpQwzx146NNee8FuICbOSdVDmUa90b+tzHzXjnolSPgMKFbCWX7lCFLbcfDaBxMNcX9BkOUSLfc4/utTn0C38rYhOKzK//A3al4mh5cxYaNZ73KatbFZL4MLPMuT9f44NswmPylRhtcUCgcjP1eal+E8lWzZjX+7DhAzpyPqUY1ZrUVV6GlTddiE3VapSGS5ixtIdgNW6X5jA2W5NiKB1WWaF6aH1PTWPa6PgKIf9+lpHFJcPeeqhskWHV+w9L7Wcjlm7uRg3B+uFBUyEfw1jgsX+wFfGfCq5rEbVk0jjeG498UD1CzeZwdlsKRA5/2laXqk8Migrbqbw95Bhm1D8muVTftvvPkmrBh9rH7Nh2qfgNKBAx5rtQikbnN8299/33EBXQ7CKzByr9aaLVt6CDX4+6m2qGwCi7gXCHur3n4fUZ/aAoo1xb58QUeXwQriGVBzMF5MZ3PuuDQaQTTOHcP0kzTJe4kiP7TWow+9TRgB", - "thinking": "The user wants me to complete an instrumented research flow with specific steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id to call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url to call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\"\n\nI need to call exactly one tool per turn and wait for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", - "type": "text" - }, - { - "id": "toolu_01QcDKhyMNiU8Df4agjz1yt2", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QcDKhyMNiU8Df4agjz1yt2", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "ErADCm4IDRgCKkARgZnDUJ+PLc8xrFDS9ecUz7mwqLm2d3m/N8LK5Mk0rTAtu68mre/Pzn/ZhTi/qFz82Hb5mrxdEkiUqtsqivMhMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM5WDRxd0cfRc2Q7v+GgzP22/9gyiglVHjuwsiMOSnrkUVb3mbmhZUVIc50+orubOjsOtWSRq/NhvyKf/3R70oKKwvPoReenbhZDwjvyrvAVe1dnEhhRKcMZVeabb7qH3A63dU4KykFUas917GFUKUxaGHAd2cO1Ksy+Twz0glNwR7+TImTI9ph3FUKjqAQOoui2je0nCJ4ldrM40Lj10KkXKjxrBktO8lLbZffXB6tshrlThqPmLhgst9sIm/vXPI9/7YT+9Dq8I1Oeh5OQtmvyy0JRiWkaNnDXetugIxC2n4gqeplUkuez54nKt0c1la5q4PwA9MLcQItyNv3gv76iW2kLxwd4BtsxEOo0tma3CNuGrT5Xs0O1CwkguSXJpLKuMPWPu7ow1C3u9gVLguglKMPxR5HJmO1NqwGGxsGAE=", - "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to Step 2 and use this id as the lookupId parameter when calling web_search with the query \"Braintrust Flue reasoning stream instrumentation\".", - "type": "thinking" - }, - { - "text": "Now proceeding to Step 2 with the lookup ID:", - "type": "text" - }, - { - "id": "toolu_0128czRSGDXRjPdjmHVgYk58", - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "name": "web_search", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "is_error": false, - "tool_use_id": "toolu_0128czRSGDXRjPdjmHVgYk58", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01G9WD4Bo94yWf1xvktj8g2K\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":245,\"cache_read_input_tokens\":2422,\"cache_creation\":{\"ephemeral_5m_input_tokens\":245,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Perfect\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"! I got the web_search results. There's one result with the\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" URL \\\"https://example.test/flue/reasoning-streams\\\". Now I need to proceed to Step 3 and call summarize_source with this URL.\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"Eo8DCm4IDRgCKkCpQxj76pPFD1cIuWNvkSAbn49WWulnuknh8zzSoZQhpuxpRLNr6jyjTVJ27jKKYd3CuNdH9FWYe0yYjBeHkk+AMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMktEsmuylOI6ScMV/GgwYN30KvKWlXjMiJe0iMF3LCPzouFNrmJ4K+VF6l1erxom5lSLw5Ye9q+H53GgGtbC3uYDj7s24ICXcIsS6cCrOAWE337R71wOflWQzsbDBRx+FIYXLSh+8RfMy3WnL/H7zlZIn5iVmStvhkuC0Ky8FyUZ9oBwjw/ud97COuKveDKr/XhVazxA7S022AMViKlO3il4/CCxW9zRNZmLTKaenDjU4MhidXwn+rBYokApHUB4X5/l/3O+dWGeVAmlA7ZIPs0Zz6X7S0lj23zApH01qcyRBH54qMRvLaEB4AaIPhV3GsuK2sbTjOZjhoDkYsCqFtbhabz5PI4ek7WxrbuOGJUmsItk1tkpEd34fzFxUGAE=\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"Now proceeding to Step 3 \"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"with the first result URL:\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_016FXSeX6EbSQ2g6jpZFYuqv\",\"name\":\"summarize_source\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"url\\\": \\\"https://example.test/flue/reasoning-streams\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":245,\"cache_read_input_tokens\":2422,\"output_tokens\":139}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:12:57Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:12:57Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:12:57Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:12:57Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5bd94d865db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:12:59 GMT", - "request-id": "req_011CbHGhXH4yFWDdi7Ba8Dcv", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-e883fcca47cdaea9dceb5b7e6d1b3745-19380135cf39e480-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1954", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 3, - "id": "305957222aa1f6e9", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:04.843Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EqEFCm4IDRgCKkCx4PeMntf8BRtpLH8OUwiMP53HIajGG0HN/LJgm9YmzwCzrRIdbPW6+RRfidn7le5y+DuWJ3BPl1JgKETNcGOcMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMgjs71MGxsxVHe7zLGgzslRkkjDTjHfOSe/QiMJwuB3ScB/LBWqEoaFVkSh1fQFtJgiUlle/UZtA34zfIz7K6LGnqxb1BZAkBKY2o6SrgA7XVIYhi9V8+7n5o2vSbR9Zu5X2ZL4DZxghVngkmw1K9A8fDUjAkwBV34qSMLqozFC4JbcWTpTHqw4HwJ43B4w8pYoeg67QyIwTtH4c+pU5Z6oMzC/9ruNsH/rb6sFceHQb/g/cUAmfV+S4feseEfrHeGpQwzx146NNee8FuICbOSdVDmUa90b+tzHzXjnolSPgMKFbCWX7lCFLbcfDaBxMNcX9BkOUSLfc4/utTn0C38rYhOKzK//A3al4mh5cxYaNZ73KatbFZL4MLPMuT9f44NswmPylRhtcUCgcjP1eal+E8lWzZjX+7DhAzpyPqUY1ZrUVV6GlTddiE3VapSGS5ixtIdgNW6X5jA2W5NiKB1WWaF6aH1PTWPa6PgKIf9+lpHFJcPeeqhskWHV+w9L7Wcjlm7uRg3B+uFBUyEfw1jgsX+wFfGfCq5rEbVk0jjeG498UD1CzeZwdlsKRA5/2laXqk8Migrbqbw95Bhm1D8muVTftvvPkmrBh9rH7Nh2qfgNKBAx5rtQikbnN8299/33EBXQ7CKzByr9aaLVt6CDX4+6m2qGwCi7gXCHur3n4fUZ/aAoo1xb58QUeXwQriGVBzMF5MZ3PuuDQaQTTOHcP0kzTJe4kiP7TWow+9TRgB", - "thinking": "The user wants me to complete an instrumented research flow with specific steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id to call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url to call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\"\n\nI need to call exactly one tool per turn and wait for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", - "type": "text" - }, - { - "id": "toolu_01QcDKhyMNiU8Df4agjz1yt2", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QcDKhyMNiU8Df4agjz1yt2", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "ErADCm4IDRgCKkARgZnDUJ+PLc8xrFDS9ecUz7mwqLm2d3m/N8LK5Mk0rTAtu68mre/Pzn/ZhTi/qFz82Hb5mrxdEkiUqtsqivMhMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM5WDRxd0cfRc2Q7v+GgzP22/9gyiglVHjuwsiMOSnrkUVb3mbmhZUVIc50+orubOjsOtWSRq/NhvyKf/3R70oKKwvPoReenbhZDwjvyrvAVe1dnEhhRKcMZVeabb7qH3A63dU4KykFUas917GFUKUxaGHAd2cO1Ksy+Twz0glNwR7+TImTI9ph3FUKjqAQOoui2je0nCJ4ldrM40Lj10KkXKjxrBktO8lLbZffXB6tshrlThqPmLhgst9sIm/vXPI9/7YT+9Dq8I1Oeh5OQtmvyy0JRiWkaNnDXetugIxC2n4gqeplUkuez54nKt0c1la5q4PwA9MLcQItyNv3gv76iW2kLxwd4BtsxEOo0tma3CNuGrT5Xs0O1CwkguSXJpLKuMPWPu7ow1C3u9gVLguglKMPxR5HJmO1NqwGGxsGAE=", - "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to Step 2 and use this id as the lookupId parameter when calling web_search with the query \"Braintrust Flue reasoning stream instrumentation\".", - "type": "thinking" - }, - { - "text": "Now proceeding to Step 2 with the lookup ID:", - "type": "text" - }, - { - "id": "toolu_0128czRSGDXRjPdjmHVgYk58", - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "name": "web_search", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "is_error": false, - "tool_use_id": "toolu_0128czRSGDXRjPdjmHVgYk58", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "Eo8DCm4IDRgCKkCpQxj76pPFD1cIuWNvkSAbn49WWulnuknh8zzSoZQhpuxpRLNr6jyjTVJ27jKKYd3CuNdH9FWYe0yYjBeHkk+AMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMktEsmuylOI6ScMV/GgwYN30KvKWlXjMiJe0iMF3LCPzouFNrmJ4K+VF6l1erxom5lSLw5Ye9q+H53GgGtbC3uYDj7s24ICXcIsS6cCrOAWE337R71wOflWQzsbDBRx+FIYXLSh+8RfMy3WnL/H7zlZIn5iVmStvhkuC0Ky8FyUZ9oBwjw/ud97COuKveDKr/XhVazxA7S022AMViKlO3il4/CCxW9zRNZmLTKaenDjU4MhidXwn+rBYokApHUB4X5/l/3O+dWGeVAmlA7ZIPs0Zz6X7S0lj23zApH01qcyRBH54qMRvLaEB4AaIPhV3GsuK2sbTjOZjhoDkYsCqFtbhabz5PI4ek7WxrbuOGJUmsItk1tkpEd34fzFxUGAE=", - "thinking": "Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to Step 3 and call summarize_source with this URL.", - "type": "thinking" - }, - { - "text": "Now proceeding to Step 3 with the first result URL:", - "type": "text" - }, - { - "id": "toolu_016FXSeX6EbSQ2g6jpZFYuqv", - "input": { - "url": "https://example.test/flue/reasoning-streams" - }, - "name": "summarize_source", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "is_error": false, - "tool_use_id": "toolu_016FXSeX6EbSQ2g6jpZFYuqv", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "thinking": { - "budget_tokens": 8192, - "display": "summarized", - "type": "enabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - }, - { - "description": "Return a deterministic lookup result with an id needed by web_search.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "query": { - "type": "string" - } - }, - "required": ["query"], - "type": "object" - }, - "name": "lookup" - }, - { - "description": "Search a deterministic local web index. Requires the id returned by lookup.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "lookupId": { - "type": "string" - }, - "query": { - "type": "string" - } - }, - "required": ["lookupId", "query"], - "type": "object" - }, - "name": "web_search" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Summarize the selected deterministic source after web_search returns a URL.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "url": { - "type": "string" - } - }, - "required": ["url"], - "type": "object" - }, - "name": "summarize_source" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01WLfU56Vt3U9D96LFBG1oeT\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":195,\"cache_read_input_tokens\":2667,\"cache_creation\":{\"ephemeral_5m_input_tokens\":195,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"The\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" summarize_source call has returned successfully. According to the instructions, I now need to reply with exactly\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" \\\"PROMPT_DONE\\\" and no other text.\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EuYCCm4IDRgCKkBFujunkFxpgR7g2ctw59ci2mFpOy6UZNKTH1CbcjkAhRRFCEjX3vkfQ+Pc94+7qXzVhvYFWLdCo2wTqIX/+LyIMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMvK0etosFMoYw1Z9RGgxoNtoAqpiqe6v2nWsiMOXu8iWWDmDLnqml/Nixpid9nKvlLp34ehcoP4GelAn8RUkUpwDDgcxpMN9U5juyvyqlAXUF63wuY0dTYfCQs7UylzAPjcwPGoRGDSyCB4+bfhKc8vHh521jgjwv7s9JJyuhp5Xj5+vhcOa6UNuXPojhtSxdBH6DNsvUEH/PICsMcgzpNkjNgXMqtUDm/10+fFpXx7GrnHr4BVXP5AreI8hS6gGydoK7EjDorgpGeJHY/RRRDJZr8XANwPlqC3ZU0wlIBwXWqefdr2bTFUtBNh0Qelx5nEgVpBgB\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"PROMPT_DONE\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":195,\"cache_read_input_tokens\":2667,\"output_tokens\":50}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2998000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:01Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:01Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:01Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3598000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:01Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5bf63c1a5db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:04 GMT", - "request-id": "req_011CbHGhs4TKsmC4kjfmPvcg", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-f79e47b3df03c590ababa226db12841a-4a86810d2176b8a1-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "2146", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 4, - "id": "3d93fe37f72a947f", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:07.903Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "thinking": { - "type": "disabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_016vwzpiWe299rYyUVo36eHU\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":718,\"cache_read_input_tokens\":1093,\"cache_creation\":{\"ephemeral_5m_input_tokens\":718,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":5,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll run the e\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"2e-flue-skill by reading its instructions and following them.\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01QkqnD4JzpMgVFLRk6aTJNM\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents/skills/e2e-flue-skill/SKILL.md\"}}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":718,\"cache_read_input_tokens\":1093,\"output_tokens\":89}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:05Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:05Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:05Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:05Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c099b265db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:06 GMT", - "request-id": "req_011CbHGi6KRcBp98B8HjsFW3", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-18c8d7abc86329d1f68499b6fc11374f-d8a0965520f39348-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1927", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 5, - "id": "fb4ed2bb1569d980", - "matchKey": "POST api.anthropic.com/v1/messages", - "recordedAt": "2026-05-22T08:13:09.385Z", - "request": { - "body": { - "kind": "json", - "value": { - "max_tokens": 64000, - "messages": [ - { - "content": [ - { - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "text": "I'll run the e2e-flue-skill by reading its instructions and following them.", - "type": "text" - }, - { - "id": "toolu_01QkqnD4JzpMgVFLRk6aTJNM", - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "name": "read", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "is_error": false, - "tool_use_id": "toolu_01QkqnD4JzpMgVFLRk6aTJNM", - "type": "tool_result" - } - ], - "role": "user" - } - ], - "model": "claude-sonnet-4-5-20250929", - "stream": true, - "system": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "thinking": { - "type": "disabled" - }, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "name": "read" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "name": "write" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "name": "edit" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "name": "bash" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "grep" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "name": "glob" - }, - { - "cache_control": { - "type": "ephemeral" - }, - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "eager_input_streaming": true, - "input_schema": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "name": "task" - } - ] - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.anthropic.com/v1/messages" - }, - "response": { - "body": { - "chunks": [ - "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01VSnypnj2Dam9xTgTsC2AKn\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":153,\"cache_read_input_tokens\":1811,\"cache_creation\":{\"ephemeral_5m_input_tokens\":153,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":7,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", - "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", - "event: ping\ndata: {\"type\":\"ping\"}", - "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"SKILL_DONE\"}}", - "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", - "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":153,\"cache_read_input_tokens\":1811,\"output_tokens\":8}}", - "event: message_stop\ndata: {\"type\":\"message_stop\"}" - ], - "kind": "sse" - }, - "headers": { - "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", - "anthropic-ratelimit-input-tokens-limit": "3000000", - "anthropic-ratelimit-input-tokens-remaining": "2999000", - "anthropic-ratelimit-input-tokens-reset": "2026-05-22T08:13:08Z", - "anthropic-ratelimit-output-tokens-limit": "600000", - "anthropic-ratelimit-output-tokens-remaining": "600000", - "anthropic-ratelimit-output-tokens-reset": "2026-05-22T08:13:08Z", - "anthropic-ratelimit-requests-limit": "20000", - "anthropic-ratelimit-requests-remaining": "19999", - "anthropic-ratelimit-requests-reset": "2026-05-22T08:13:08Z", - "anthropic-ratelimit-tokens-limit": "3600000", - "anthropic-ratelimit-tokens-remaining": "3599000", - "anthropic-ratelimit-tokens-reset": "2026-05-22T08:13:08Z", - "cache-control": "no-cache", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9ffa5c1cbcdd5db9-VIE", - "connection": "keep-alive", - "content-encoding": "gzip", - "content-security-policy": "default-src 'none'; frame-ancestors 'none'", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:09 GMT", - "request-id": "req_011CbHGiKQyD4CKrnb72HeYh", - "server": "cloudflare", - "set-cookie": "[REDACTED]", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "traceresponse": "00-8da16ded55b300300e9dc89695f1622a-3b76f650e176116b-01", - "transfer-encoding": "chunked", - "vary": "Accept-Encoding", - "x-envoy-upstream-service-time": "1215", - "x-robots-tag": "none" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 0, - "id": "7c0e162d6794cf5d", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:11.160Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Fri, May 22, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/tashkent/e2e/.bt-tmp/run-HpI3r1/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly TASK_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "model": "gpt-4o-mini", - "prompt_cache_key": "[REDACTED]", - "store": false, - "stream": true, - "tools": [ - { - "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", - "name": "read", - "parameters": { - "properties": { - "limit": { - "description": "Maximum number of lines to read", - "type": "number" - }, - "offset": { - "description": "Line number to start from (1-indexed)", - "type": "number" - }, - "path": { - "description": "Path to the file to read", - "type": "string" - } - }, - "required": ["path"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Write content to a file. Creates the file and parent directories if they do not exist.", - "name": "write", - "parameters": { - "properties": { - "content": { - "description": "Content to write to the file", - "type": "string" - }, - "path": { - "description": "Path to the file to write", - "type": "string" - } - }, - "required": ["path", "content"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", - "name": "edit", - "parameters": { - "properties": { - "newText": { - "description": "Replacement text", - "type": "string" - }, - "oldText": { - "description": "Exact text to find (must be unique)", - "type": "string" - }, - "path": { - "description": "Path to the file to edit", - "type": "string" - }, - "replaceAll": { - "description": "Replace all occurrences", - "type": "boolean" - } - }, - "required": ["path", "oldText", "newText"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", - "name": "bash", - "parameters": { - "properties": { - "command": { - "description": "Bash command to execute", - "type": "string" - }, - "timeout": { - "description": "Timeout in seconds", - "type": "number" - } - }, - "required": ["command"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", - "name": "grep", - "parameters": { - "properties": { - "include": { - "description": "Glob filter, e.g. \"*.ts\"", - "type": "string" - }, - "path": { - "description": "Directory or file to search (default: .)", - "type": "string" - }, - "pattern": { - "description": "Search pattern (regex)", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", - "name": "glob", - "parameters": { - "properties": { - "path": { - "description": "Directory to search in (default: .)", - "type": "string" - }, - "pattern": { - "description": "Filename pattern, e.g. \"*.ts\"", - "type": "string" - } - }, - "required": ["pattern"], - "type": "object" - }, - "strict": false, - "type": "function" - }, - { - "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.", - "name": "task", - "parameters": { - "properties": { - "cwd": { - "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", - "type": "string" - }, - "description": { - "description": "Short human-readable label for the delegated work", - "type": "string" - }, - "prompt": { - "description": "Focused instructions for the child agent", - "type": "string" - }, - "role": { - "description": "Role to use for the child agent", - "type": "string" - } - }, - "required": ["prompt"], - "type": "object" - }, - "strict": false, - "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_02acb0b56a57c778016a101015cb608196ba237c741a1ce434\",\"object\":\"response\",\"created_at\":1779437589,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:550c7301-0a1c-47a4-889b-17\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_02acb0b56a57c778016a101015cb608196ba237c741a1ce434\",\"object\":\"response\",\"created_at\":1779437589,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:550c7301-0a1c-47a4-889b-17\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"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_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"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\":\"TASK\",\"item_id\":\"msg_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"logprobs\":[],\"obfuscation\":\"K6AG6tDa94wn\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"_DONE\",\"item_id\":\"msg_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"logprobs\":[],\"obfuscation\":\"XtIFjcwdHFb\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":6,\"text\":\"TASK_DONE\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"},\"sequence_number\":7}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":8}", - "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_02acb0b56a57c778016a101015cb608196ba237c741a1ce434\",\"object\":\"response\",\"created_at\":1779437589,\"status\":\"completed\",\"background\":false,\"completed_at\":1779437590,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_02acb0b56a57c778016a101016e3388196ad49dd6c55f861ab\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::task:task:550c7301-0a1c-47a4-889b-17\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. Available roles: skillRunner.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"role\":{\"type\":\"string\",\"description\":\"Role to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":772,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":4,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":776},\"user\":null,\"metadata\":{}},\"sequence_number\":9}" - ], - "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": "9ffa5c2718d6c31f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:09 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "127", - "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": "req_2a4bc74503354197a53d2b818e417dcc" - }, - "status": 200, - "statusText": "OK" - } - }, - { - "callIndex": 1, - "id": "f12aff3913439248", - "matchKey": "POST api.openai.com/v1/responses", - "recordedAt": "2026-05-22T08:13:12.327Z", - "request": { - "body": { - "kind": "json", - "value": { - "input": [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete an instrumented research flow with specific steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id to call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url to call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\"\n\nI need to call exactly one tool per turn and wait for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with Step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to Step 2 and use this id as the lookupId parameter when calling web_search with the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to Step 2 with the lookup ID:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to Step 3 and call summarize_source with this URL.\n\n[Assistant]: Now proceeding to Step 3 with the first result URL:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "max_output_tokens": 32, - "model": "gpt-4o-mini", - "store": false, - "stream": true - } - }, - "headers": {}, - "method": "POST", - "url": "https://api.openai.com/v1/responses" - }, - "response": { - "body": { - "chunks": [ - "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_0d2b14e39122d1ad016a10101753648197a50d4b2b8228ecfb\",\"object\":\"response\",\"created_at\":1779437591,\"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\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_0d2b14e39122d1ad016a10101753648197a50d4b2b8228ecfb\",\"object\":\"response\",\"created_at\":1779437591,\"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\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"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_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"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_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"l2j9wXUI75mlL0\",\"output_index\":0,\"sequence_number\":4}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Original\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"9GPpYWG\",\"output_index\":0,\"sequence_number\":5}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Request\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"Vkbxcebp\",\"output_index\":0,\"sequence_number\":6}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\n\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"Vsipk4ZEN8K6Ept\",\"output_index\":0,\"sequence_number\":7}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"The\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"E1tFh9aB6fNjV\",\"output_index\":0,\"sequence_number\":8}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" user\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"F5YqKiy40oA\",\"output_index\":0,\"sequence_number\":9}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" asked\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"j3cZjf1sV1\",\"output_index\":0,\"sequence_number\":10}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" the\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"3MOMaNRJmo90\",\"output_index\":0,\"sequence_number\":11}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" assistant\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"xg2YFw\",\"output_index\":0,\"sequence_number\":12}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" to\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"eHeTmYHXADpAt\",\"output_index\":0,\"sequence_number\":13}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" complete\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"bPjj5Hs\",\"output_index\":0,\"sequence_number\":14}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" a\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"0MdoSGeYerfhME\",\"output_index\":0,\"sequence_number\":15}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" specific\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"If4tz8p\",\"output_index\":0,\"sequence_number\":16}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" instrument\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"aI0Wd\",\"output_index\":0,\"sequence_number\":17}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"ed\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"IRb0EgycyGxKxs\",\"output_index\":0,\"sequence_number\":18}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" research\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"m9TwC2x\",\"output_index\":0,\"sequence_number\":19}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" flow\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"Aomp0L5TyGx\",\"output_index\":0,\"sequence_number\":20}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" involving\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"hyCqCo\",\"output_index\":0,\"sequence_number\":21}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" three\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"Eyr5ZXtJbu\",\"output_index\":0,\"sequence_number\":22}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" steps\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"o5q5KG9DTO\",\"output_index\":0,\"sequence_number\":23}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\":\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"b9SEOrMFY76p0K4\",\"output_index\":0,\"sequence_number\":24}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" calling\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"hnq433sU\",\"output_index\":0,\"sequence_number\":25}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" a\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"wZsQBilARIa3uM\",\"output_index\":0,\"sequence_number\":26}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" lookup\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"RmL7qsS0P\",\"output_index\":0,\"sequence_number\":27}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" tool\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"Tt8WJkAFufP\",\"output_index\":0,\"sequence_number\":28}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"S7xI9J0wDFseRpl\",\"output_index\":0,\"sequence_number\":29}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" performing\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"0jZMr\",\"output_index\":0,\"sequence_number\":30}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" a\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"Z8tyWvoyEOJHEH\",\"output_index\":0,\"sequence_number\":31}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" web\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"4DarXUesPl3B\",\"output_index\":0,\"sequence_number\":32}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" search\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"ucA8HbYy6\",\"output_index\":0,\"sequence_number\":33}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" using\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"3Bd45YIJg9\",\"output_index\":0,\"sequence_number\":34}", - "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" the\",\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"obfuscation\":\"BhaEain94nJJ\",\"output_index\":0,\"sequence_number\":35}", - "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":36,\"text\":\"## Original Request\\nThe user asked the assistant to complete a specific instrumented research flow involving three steps: calling a lookup tool, performing a web search using the\"}", - "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user asked the assistant to complete a specific instrumented research flow involving three steps: calling a lookup tool, performing a web search using the\"},\"sequence_number\":37}", - "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user asked the assistant to complete a specific instrumented research flow involving three steps: calling a lookup tool, performing a web search using the\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":38}", - "event: response.incomplete\ndata: {\"type\":\"response.incomplete\",\"response\":{\"id\":\"resp_0d2b14e39122d1ad016a10101753648197a50d4b2b8228ecfb\",\"object\":\"response\",\"created_at\":1779437591,\"status\":\"incomplete\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":{\"reason\":\"max_output_tokens\"},\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_0d2b14e39122d1ad016a101017cac881979435f18a4f122c15\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user asked the assistant to complete a specific instrumented research flow involving three steps: calling a lookup tool, performing a web search using the\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":null,\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":703,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":32,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":735},\"user\":null,\"metadata\":{}},\"sequence_number\":39}" - ], - "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": "9ffa5c311b2bc31f-VIE", - "connection": "keep-alive", - "content-type": "text/event-stream; charset=utf-8", - "date": "Fri, 22 May 2026 08:13:11 GMT", - "openai-organization": "braintrust-data", - "openai-processing-ms": "96", - "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": "req_1fc6894099af434791545a929ffa7b92" - }, - "status": 200, - "statusText": "OK" - } - } - ], - "meta": { - "createdAt": "2026-05-20T19:14:48.342Z" - } -} diff --git a/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-8-0.cassette.json b/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-8-0.cassette.json new file mode 100644 index 000000000..996df5098 --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/__cassettes__/flue-v0-8-0.cassette.json @@ -0,0 +1,3727 @@ +{ + "entries": [ + { + "callIndex": 0, + "id": "fcd9d51c145fb90b", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:40:49.578Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "budget_tokens": 8192, + "display": "summarized", + "type": "enabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + }, + { + "description": "Return a deterministic lookup result with an id needed by web_search.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "query": { + "type": "string" + } + }, + "required": ["query"], + "type": "object" + }, + "name": "lookup" + }, + { + "description": "Search a deterministic local web index. Requires the id returned by lookup.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "lookupId": { + "type": "string" + }, + "query": { + "type": "string" + } + }, + "required": ["lookupId", "query"], + "type": "object" + }, + "name": "web_search" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Summarize the selected deterministic source after web_search returns a URL.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "url": { + "type": "string" + } + }, + "required": ["url"], + "type": "object" + }, + "name": "summarize_source" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01A7K7rFFvpGEkYsKHme6rCx\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":2222,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":2222,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":8,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"The user wants me to complete a research\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" flow with exactly three steps:\\n1. Call lookup with query \\\"flue instrumentation\\\"\\n2. Call web_search with the\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" lookupId from step 1 and query \\\"Braintrust Flue reasoning stream instrumentation\\\"\\n3. Call summarize_source with the first URL from step 2\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\\n4. Reply with exactly \\\"PROMPT_DONE\\\"\\n\\nThe user emphasizes I should call exactly one tool per turn and wait for each result\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\". Let me start with step 1.\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll complete this instrumented research flow step\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\" by step. Starting with Step 1:\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01MbotvqKgQV4ecxQ566vyuC\",\"name\":\"lookup\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"query\\\": \\\"flue instrumentation\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":2222,\"cache_read_input_tokens\":0,\"output_tokens\":196,\"output_tokens_details\":{\"thinking_tokens\":120}}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:40:45Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:40:45Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:40:45Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:40:45Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dac490ea0c301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:40:47 GMT", + "request-id": "req_011CbV4Yrzdciu7aM7XyPJvu", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-def621f99a586b9f40e35c15380d1f90-62267612b2e498ea-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "1355", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 1, + "id": "ff22a182ea5a9c06", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:40:53.810Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "signature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "id": "toolu_01MbotvqKgQV4ecxQ566vyuC", + "input": { + "query": "flue instrumentation" + }, + "name": "lookup", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "is_error": false, + "tool_use_id": "toolu_01MbotvqKgQV4ecxQ566vyuC", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "budget_tokens": 8192, + "display": "summarized", + "type": "enabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + }, + { + "description": "Return a deterministic lookup result with an id needed by web_search.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "query": { + "type": "string" + } + }, + "required": ["query"], + "type": "object" + }, + "name": "lookup" + }, + { + "description": "Search a deterministic local web index. Requires the id returned by lookup.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "lookupId": { + "type": "string" + }, + "query": { + "type": "string" + } + }, + "required": ["lookupId", "query"], + "type": "object" + }, + "name": "web_search" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Summarize the selected deterministic source after web_search returns a URL.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "url": { + "type": "string" + } + }, + "required": ["url"], + "type": "object" + }, + "name": "summarize_source" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01HZbhxuwLjyFGr1czSAWHTh\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":236,\"cache_read_input_tokens\":2222,\"cache_creation\":{\"ephemeral_5m_input_tokens\":236,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Good\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\", I got the lookup result with id \\\"flue-session-2026\\\". Now I need to proceed to step 2:\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" call web_search with this lookupId and the query \\\"Braintrust Flue reasoning stream instrumentation\\\".\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"Now proceeding to Step 2:\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_018rc1ig7vXeron3rLfpUtRT\",\"name\":\"web_search\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"lookupId\\\": \\\"flue-session-2026\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\", \\\"query\\\": \\\"Braintrust Flue reasoning stream instru\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"mentation\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":236,\"cache_read_input_tokens\":2222,\"output_tokens\":158,\"output_tokens_details\":{\"thinking_tokens\":59}}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:40:49Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:40:49Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:40:49Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:40:49Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dac631dbac301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:40:52 GMT", + "request-id": "req_011CbV4ZAqRr9QtjYnVyY69n", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-68d6456f3077bdeb0822f73c39a51d2d-5be926a484ba813d-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "2225", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 2, + "id": "f1d50a1e6c760d6c", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:40:58.541Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "signature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "id": "toolu_01MbotvqKgQV4ecxQ566vyuC", + "input": { + "query": "flue instrumentation" + }, + "name": "lookup", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "is_error": false, + "tool_use_id": "toolu_01MbotvqKgQV4ecxQ566vyuC", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "signature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "id": "toolu_018rc1ig7vXeron3rLfpUtRT", + "input": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "name": "web_search", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "is_error": false, + "tool_use_id": "toolu_018rc1ig7vXeron3rLfpUtRT", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "budget_tokens": 8192, + "display": "summarized", + "type": "enabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + }, + { + "description": "Return a deterministic lookup result with an id needed by web_search.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "query": { + "type": "string" + } + }, + "required": ["query"], + "type": "object" + }, + "name": "lookup" + }, + { + "description": "Search a deterministic local web index. Requires the id returned by lookup.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "lookupId": { + "type": "string" + }, + "query": { + "type": "string" + } + }, + "required": ["lookupId", "query"], + "type": "object" + }, + "name": "web_search" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Summarize the selected deterministic source after web_search returns a URL.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "url": { + "type": "string" + } + }, + "required": ["url"], + "type": "object" + }, + "name": "summarize_source" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01HJoo9ncrvNPVcaq2UWN45L\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":234,\"cache_read_input_tokens\":2458,\"cache_creation\":{\"ephemeral_5m_input_tokens\":234,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":4,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Perfect! I got\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" the web_search results with one result. The first (and only) result has the URL\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\" \\\"https://example.test/flue/reasoning-streams\\\". Now I need to proceed to step 3: call summarize_source with this URL.\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"Now proceeding to Step 3:\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01MRjt3UmRqrUYHt1ZC8gND9\",\"name\":\"summarize_source\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"url\\\": \\\"https://example.test/flue/reasoning-streams\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":234,\"cache_read_input_tokens\":2458,\"output_tokens\":138,\"output_tokens_details\":{\"thinking_tokens\":61}}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2998000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:40:54Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:40:54Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:40:54Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3598000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:40:54Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dac7d4a1fc301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:40:56 GMT", + "request-id": "req_011CbV4ZUiiFpwboN3YtdzkH", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-6392939f911bfe9568c361c78254c370-cb7c6141cf28bb77-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "2757", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 3, + "id": "305957222aa1f6e9", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:01.029Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "signature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "id": "toolu_01MbotvqKgQV4ecxQ566vyuC", + "input": { + "query": "flue instrumentation" + }, + "name": "lookup", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "is_error": false, + "tool_use_id": "toolu_01MbotvqKgQV4ecxQ566vyuC", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "signature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "id": "toolu_018rc1ig7vXeron3rLfpUtRT", + "input": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "name": "web_search", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "is_error": false, + "tool_use_id": "toolu_018rc1ig7vXeron3rLfpUtRT", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "signature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 3:", + "type": "text" + }, + { + "id": "toolu_01MRjt3UmRqrUYHt1ZC8gND9", + "input": { + "url": "https://example.test/flue/reasoning-streams" + }, + "name": "summarize_source", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + "is_error": false, + "tool_use_id": "toolu_01MRjt3UmRqrUYHt1ZC8gND9", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "budget_tokens": 8192, + "display": "summarized", + "type": "enabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + }, + { + "description": "Return a deterministic lookup result with an id needed by web_search.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "query": { + "type": "string" + } + }, + "required": ["query"], + "type": "object" + }, + "name": "lookup" + }, + { + "description": "Search a deterministic local web index. Requires the id returned by lookup.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "lookupId": { + "type": "string" + }, + "query": { + "type": "string" + } + }, + "required": ["lookupId", "query"], + "type": "object" + }, + "name": "web_search" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Summarize the selected deterministic source after web_search returns a URL.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "url": { + "type": "string" + } + }, + "required": ["url"], + "type": "object" + }, + "name": "summarize_source" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_019YC1YEtmEwfw9dyuY3MPdx\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":194,\"cache_read_input_tokens\":2692,\"cache_creation\":{\"ephemeral_5m_input_tokens\":194,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"thinking\",\"thinking\":\"\",\"signature\":\"\"}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"Perfect\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"! The summarize_source call has completed successfully. According to the instructions, I should now reply with exactly \\\"PROMPT_DONE\\\" and no other text.\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"thinking_delta\",\"thinking\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"signature_delta\",\"signature\":\"Eu8CCm4IDhgCKkAn2QOIIlYfvcs6ynsmhCslHDtBsrTA4CfmimK7zyz6+k6dZldV2JBtEBET41It0gFcGEKC0n0mAhaYVuLutpDDMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM1xfLptxSF8rKzou8GgwRLuVmfiBYOT4CZIsiMAYz8TpvchMAWodP+T9uZ+dJ47MVdNv+p86nZXmT5d5EWlCroiAOFHHzJH2o0UjJQSquAX6wu+jIC8/DXwurGIIf2ToldPuJWF5HGj8kHMnwh777XS1NUFl1irM24rvP7kTAv3Dp8YEwb8t3g1EsicY7j+C5DzgwxVsPYCVOCgdMqQjtsqpL7AX5KQ9+hR1gK1DQjshv4Gze3hw/+C+9iptd3RlDIuwO0cm8NY+sVqeWVh3TtQujQlVt1rW/HfWjclrtT0LZSGwc6RypmfMMQi6lncIk/EPgy0XbS1plKW0tLBgB\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"text_delta\",\"text\":\"PROMPT_DONE\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":13,\"cache_creation_input_tokens\":194,\"cache_read_input_tokens\":2692,\"output_tokens\":51,\"output_tokens_details\":{\"thinking_tokens\":40}}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2998000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:40:58Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:40:58Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:40:58Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3598000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:40:58Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dac9afd8fc301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:00 GMT", + "request-id": "req_011CbV4Zq3L7gJxP1Y46qapx", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-e0b4a5e0f6b8f2625262dec81a52e61e-c551de5bb2f6f203-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "1421", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 4, + "id": "3d93fe37f72a947f", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:05.303Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "type": "disabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01SoNm9ntxkXQkRrBSidrXSB\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":670,\"cache_read_input_tokens\":1099,\"cache_creation\":{\"ephemeral_5m_input_tokens\":670,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":5,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll run the e\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"2e-flue-skill. Let me first read the skill file to understand its instructions.\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_0116y5v4MmMkEaDkjkEPPjTH\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents/e2e-flue\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"-skill.md\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":3,\"cache_creation_input_tokens\":670,\"cache_read_input_tokens\":1099,\"output_tokens\":89}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:41:01Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:41:01Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:41:01Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:41:01Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dacab0e1fc301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:04 GMT", + "request-id": "req_011CbV4a2cMY5XByBTCzUoHh", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-e05c9702b7456a4b1c655ed13d92ba42-b48b861130669b0c-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "2864", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 5, + "id": "fb4ed2bb1569d980", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:08.068Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "ENOENT: no such file or directory, open '/Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "is_error": true, + "tool_use_id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "type": "disabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01HWMEiz1LLcSzQG6KkyGVxZ\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":7,\"cache_creation_input_tokens\":183,\"cache_read_input_tokens\":1769,\"cache_creation\":{\"ephemeral_5m_input_tokens\":183,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":52,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01VLK49ybvQa2MZoZ8FxbJCx\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":7,\"cache_creation_input_tokens\":183,\"cache_read_input_tokens\":1769,\"output_tokens\":52}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:41:05Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:41:05Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:41:05Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:41:05Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dacc65c8dc301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:07 GMT", + "request-id": "req_011CbV4aLhY55XXCvF766Z84", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-1467e6f052128317c79e4dcdcc34c0e2-95e633d304e0c3ad-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "2046", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 6, + "id": "2d5b5e2519b5661b", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:10.832Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "ENOENT: no such file or directory, open '/Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "is_error": true, + "tool_use_id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "input": { + "path": ".agents" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "skills", + "is_error": false, + "tool_use_id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "type": "disabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01RRobMzKrtpPcHZAGQrRZCo\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":66,\"cache_read_input_tokens\":1952,\"cache_creation\":{\"ephemeral_5m_input_tokens\":66,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":54,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_018pSd7nKSm3kfi2DVmzQPsA\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents/skills\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":66,\"cache_read_input_tokens\":1952,\"output_tokens\":54}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:41:08Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:41:08Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:41:08Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:41:08Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dacd76bc8c301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:10 GMT", + "request-id": "req_011CbV4aYPzoGb5kYRUcefKG", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-eb3b7c53373bb1de39b3c714cb8004f5-e91254d86c0e7b64-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "2024", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 7, + "id": "2cbc017f3c17c05f", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:13.081Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "ENOENT: no such file or directory, open '/Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "is_error": true, + "tool_use_id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "input": { + "path": ".agents" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "skills", + "is_error": false, + "tool_use_id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_018pSd7nKSm3kfi2DVmzQPsA", + "input": { + "path": ".agents/skills" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "e2e-flue-skill", + "is_error": false, + "tool_use_id": "toolu_018pSd7nKSm3kfi2DVmzQPsA", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "type": "disabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01HaDyq5MaZpVHgVGhHJLmvs\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":74,\"cache_read_input_tokens\":2018,\"cache_creation\":{\"ephemeral_5m_input_tokens\":74,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":63,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_012TAbdNbuuFaDw1naUg1vbT\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents/skills/e2e-flue-skill\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":74,\"cache_read_input_tokens\":2018,\"output_tokens\":63}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:41:11Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:41:11Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:41:11Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:41:11Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dace85ad2c301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:13 GMT", + "request-id": "req_011CbV4ajy1g4mH27mS5Ju8N", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-93ed38ba66b829c67909054d6945c9cb-af18094065e38879-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "1778", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 8, + "id": "4b885efa84390a1f", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:15.608Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "ENOENT: no such file or directory, open '/Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "is_error": true, + "tool_use_id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "input": { + "path": ".agents" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "skills", + "is_error": false, + "tool_use_id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_018pSd7nKSm3kfi2DVmzQPsA", + "input": { + "path": ".agents/skills" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "e2e-flue-skill", + "is_error": false, + "tool_use_id": "toolu_018pSd7nKSm3kfi2DVmzQPsA", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_012TAbdNbuuFaDw1naUg1vbT", + "input": { + "path": ".agents/skills/e2e-flue-skill" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "SKILL.md", + "is_error": false, + "tool_use_id": "toolu_012TAbdNbuuFaDw1naUg1vbT", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "type": "disabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01FCY15E5PvgZ9MKVwMLQfmY\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":79,\"cache_read_input_tokens\":2092,\"cache_creation\":{\"ephemeral_5m_input_tokens\":79,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":66,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01WQVh4vmLxZQhqpoXRvUi68\",\"name\":\"read\",\"input\":{},\"caller\":{\"type\":\"direct\"}}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"path\\\": \\\".agents/skills/e2e-flue-skill/SKILL.md\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\\\"}\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":79,\"cache_read_input_tokens\":2092,\"output_tokens\":68}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:41:13Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:41:13Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:41:13Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:41:13Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dacf599b5c301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:15 GMT", + "request-id": "req_011CbV4atzVFuefiAGaQnZig", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-75d6c58deb0a99da3a3ea03db1ae3fd9-01d8b31ff753a269-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "2118", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 9, + "id": "05dcf3cc09c5aa27", + "matchKey": "POST api.anthropic.com/v1/messages", + "recordedAt": "2026-05-28T13:41:17.354Z", + "request": { + "body": { + "kind": "json", + "value": { + "max_tokens": 64000, + "messages": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "ENOENT: no such file or directory, open '/Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "is_error": true, + "tool_use_id": "toolu_0116y5v4MmMkEaDkjkEPPjTH", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "input": { + "path": ".agents" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "skills", + "is_error": false, + "tool_use_id": "toolu_01VLK49ybvQa2MZoZ8FxbJCx", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_018pSd7nKSm3kfi2DVmzQPsA", + "input": { + "path": ".agents/skills" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "e2e-flue-skill", + "is_error": false, + "tool_use_id": "toolu_018pSd7nKSm3kfi2DVmzQPsA", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_012TAbdNbuuFaDw1naUg1vbT", + "input": { + "path": ".agents/skills/e2e-flue-skill" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "content": "SKILL.md", + "is_error": false, + "tool_use_id": "toolu_012TAbdNbuuFaDw1naUg1vbT", + "type": "tool_result" + } + ], + "role": "user" + }, + { + "content": [ + { + "id": "toolu_01WQVh4vmLxZQhqpoXRvUi68", + "input": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "name": "read", + "type": "tool_use" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "cache_control": { + "type": "ephemeral" + }, + "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + "is_error": false, + "tool_use_id": "toolu_01WQVh4vmLxZQhqpoXRvUi68", + "type": "tool_result" + } + ], + "role": "user" + } + ], + "model": "claude-sonnet-4-5-20250929", + "stream": true, + "system": [ + { + "cache_control": { + "type": "ephemeral" + }, + "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "type": "text" + } + ], + "thinking": { + "type": "disabled" + }, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "name": "read" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "name": "write" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "name": "edit" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "name": "bash" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "grep" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "name": "glob" + }, + { + "cache_control": { + "type": "ephemeral" + }, + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "eager_input_streaming": true, + "input_schema": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "name": "task" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.anthropic.com/v1/messages" + }, + "response": { + "body": { + "chunks": [ + "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"model\":\"claude-sonnet-4-5-20250929\",\"id\":\"msg_01F7J8rewVTLnDMtxDcVdkiQ\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"stop_details\":null,\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":135,\"cache_read_input_tokens\":2171,\"cache_creation\":{\"ephemeral_5m_input_tokens\":135,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":3,\"service_tier\":\"standard\",\"inference_geo\":\"not_available\"}}}", + "event: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}", + "event: ping\ndata: {\"type\":\"ping\"}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"SKILL_\"}}", + "event: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"DONE\"}}", + "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}", + "event: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"stop_details\":null},\"usage\":{\"input_tokens\":6,\"cache_creation_input_tokens\":135,\"cache_read_input_tokens\":2171,\"output_tokens\":8}}", + "event: message_stop\ndata: {\"type\":\"message_stop\"}" + ], + "kind": "sse" + }, + "headers": { + "anthropic-organization-id": "27796668-7351-40ac-acc4-024aee8995a5", + "anthropic-ratelimit-input-tokens-limit": "3000000", + "anthropic-ratelimit-input-tokens-remaining": "2999000", + "anthropic-ratelimit-input-tokens-reset": "2026-05-28T13:41:15Z", + "anthropic-ratelimit-output-tokens-limit": "600000", + "anthropic-ratelimit-output-tokens-remaining": "600000", + "anthropic-ratelimit-output-tokens-reset": "2026-05-28T13:41:15Z", + "anthropic-ratelimit-requests-limit": "20000", + "anthropic-ratelimit-requests-remaining": "19999", + "anthropic-ratelimit-requests-reset": "2026-05-28T13:41:15Z", + "anthropic-ratelimit-tokens-limit": "3600000", + "anthropic-ratelimit-tokens-remaining": "3599000", + "anthropic-ratelimit-tokens-reset": "2026-05-28T13:41:15Z", + "cache-control": "no-cache", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a02dad05abc5c301-VIE", + "connection": "keep-alive", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'; frame-ancestors 'none'", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:17 GMT", + "request-id": "req_011CbV4b62WtkEAN1uuw6ZTa", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "traceresponse": "00-a95abb0aa0dc3ddebd7bd3e84f6431b6-69727f41ec2a9c74-01", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding", + "x-envoy-upstream-service-time": "1258", + "x-robots-tag": "none" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 0, + "id": "7c0e162d6794cf5d", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-05-28T13:41:20.282Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\nYou are a deterministic Flue instrumentation test agent. Follow user instructions exactly. When asked for a marker, output only that marker and no extra text. When running a local skill file, read it yourself and do not delegate it to a task.\n\n## Available Skills\n\nThe following skills provide specialized instructions for specific tasks. When a task matches a skill description, activate that skill before proceeding so its full instructions are loaded. Skill instructions and supporting resources stay lazy until activation or explicit file reads.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: Thu, May 28, 2026\nWorking directory: /Users/lucaforstner/conductor/workspaces/braintrust-sdk-javascript/shanghai-v1/e2e/.bt-tmp/run-u9uXnv/scenarios/flue-instrumentation\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", + "role": "system" + }, + { + "content": [ + { + "text": "Reply with exactly TASK_DONE and no other text.", + "type": "input_text" + } + ], + "role": "user" + } + ], + "model": "gpt-4o-mini", + "prompt_cache_key": "[REDACTED]", + "store": false, + "stream": true, + "tools": [ + { + "description": "Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.", + "name": "read", + "parameters": { + "properties": { + "limit": { + "description": "Maximum number of lines to read", + "type": "number" + }, + "offset": { + "description": "Line number to start from (1-indexed)", + "type": "number" + }, + "path": { + "description": "Path to the file to read", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + }, + "strict": false, + "type": "function" + }, + { + "description": "Write content to a file. Creates the file and parent directories if they do not exist.", + "name": "write", + "parameters": { + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Path to the file to write", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + }, + "strict": false, + "type": "function" + }, + { + "description": "Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.", + "name": "edit", + "parameters": { + "properties": { + "newText": { + "description": "Replacement text", + "type": "string" + }, + "oldText": { + "description": "Exact text to find (must be unique)", + "type": "string" + }, + "path": { + "description": "Path to the file to edit", + "type": "string" + }, + "replaceAll": { + "description": "Replace all occurrences", + "type": "boolean" + } + }, + "required": ["path", "oldText", "newText"], + "type": "object" + }, + "strict": false, + "type": "function" + }, + { + "description": "Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.", + "name": "bash", + "parameters": { + "properties": { + "command": { + "description": "Bash command to execute", + "type": "string" + }, + "timeout": { + "description": "Timeout in seconds", + "type": "number" + } + }, + "required": ["command"], + "type": "object" + }, + "strict": false, + "type": "function" + }, + { + "description": "Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.", + "name": "grep", + "parameters": { + "properties": { + "include": { + "description": "Glob filter, e.g. \"*.ts\"", + "type": "string" + }, + "path": { + "description": "Directory or file to search (default: .)", + "type": "string" + }, + "pattern": { + "description": "Search pattern (regex)", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "strict": false, + "type": "function" + }, + { + "description": "Find files by filename pattern using shell find -name semantics. Returns matching file paths.", + "name": "glob", + "parameters": { + "properties": { + "path": { + "description": "Directory to search in (default: .)", + "type": "string" + }, + "pattern": { + "description": "Filename pattern, e.g. \"*.ts\"", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + }, + "strict": false, + "type": "function" + }, + { + "description": "Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.", + "name": "task", + "parameters": { + "properties": { + "agent": { + "description": "Declared subagent to use for the child agent", + "type": "string" + }, + "cwd": { + "description": "Working directory for the child agent. AGENTS.md and skills are discovered from here.", + "type": "string" + }, + "description": { + "description": "Short human-readable label for the delegated work", + "type": "string" + }, + "prompt": { + "description": "Focused instructions for the child agent", + "type": "string" + } + }, + "required": ["prompt"], + "type": "object" + }, + "strict": false, + "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_09b32b2821e9a4d8016a1845ff2ea88192a734cf6ba6abcb9d\",\"object\":\"response\",\"created_at\":1779975679,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:4cfd6e11-bac1-4736-9b87-b0\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"agent\":{\"type\":\"string\",\"description\":\"Declared subagent to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_09b32b2821e9a4d8016a1845ff2ea88192a734cf6ba6abcb9d\",\"object\":\"response\",\"created_at\":1779975679,\"status\":\"in_progress\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"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\":\"flue-e2e-instance::default::task:task:4cfd6e11-bac1-4736-9b87-b0\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"auto\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"agent\":{\"type\":\"string\",\"description\":\"Declared subagent to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"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_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"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_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"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\":\"TASK\",\"item_id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"logprobs\":[],\"obfuscation\":\"pyb2YZ3HkAzp\",\"output_index\":0,\"sequence_number\":4}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"_DONE\",\"item_id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"logprobs\":[],\"obfuscation\":\"zDbKM0sYFZQ\",\"output_index\":0,\"sequence_number\":5}", + "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":6,\"text\":\"TASK_DONE\"}", + "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"},\"sequence_number\":7}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":8}", + "event: response.completed\ndata: {\"type\":\"response.completed\",\"response\":{\"id\":\"resp_09b32b2821e9a4d8016a1845ff2ea88192a734cf6ba6abcb9d\",\"object\":\"response\",\"created_at\":1779975679,\"status\":\"completed\",\"background\":false,\"completed_at\":1779975680,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":null,\"instructions\":null,\"max_output_tokens\":null,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\",\"type\":\"message\",\"status\":\"completed\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"TASK_DONE\"}],\"role\":\"assistant\"}],\"parallel_tool_calls\":true,\"presence_penalty\":0,\"previous_response_id\":null,\"prompt_cache_key\":\"flue-e2e-instance::default::task:task:4cfd6e11-bac1-4736-9b87-b0\",\"prompt_cache_retention\":\"in_memory\",\"reasoning\":{\"context\":null,\"effort\":null,\"summary\":null},\"safety_identifier\":null,\"service_tier\":\"default\",\"store\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[{\"type\":\"function\",\"description\":\"Read a file or list a directory. For files, output is truncated to 2000 lines or 50KB — use offset/limit for large files. For directories, returns the list of entries.\",\"name\":\"read\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to read\"},\"offset\":{\"type\":\"number\",\"description\":\"Line number to start from (1-indexed)\"},\"limit\":{\"type\":\"number\",\"description\":\"Maximum number of lines to read\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Write content to a file. Creates the file and parent directories if they do not exist.\",\"name\":\"write\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to write\"},\"content\":{\"type\":\"string\",\"description\":\"Content to write to the file\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Edit a file using exact text replacement. The oldText must match a unique region of the file. Use replaceAll to replace all occurrences.\",\"name\":\"edit\",\"parameters\":{\"type\":\"object\",\"required\":[\"path\",\"oldText\",\"newText\"],\"properties\":{\"path\":{\"type\":\"string\",\"description\":\"Path to the file to edit\"},\"oldText\":{\"type\":\"string\",\"description\":\"Exact text to find (must be unique)\"},\"newText\":{\"type\":\"string\",\"description\":\"Replacement text\"},\"replaceAll\":{\"type\":\"boolean\",\"description\":\"Replace all occurrences\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Execute a bash command. Returns stdout and stderr. Output is truncated to the last 2000 lines or 50KB.\",\"name\":\"bash\",\"parameters\":{\"type\":\"object\",\"required\":[\"command\"],\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"Bash command to execute\"},\"timeout\":{\"type\":\"number\",\"description\":\"Timeout in seconds\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Search file contents for a regex pattern. Returns matching lines with file paths and line numbers.\",\"name\":\"grep\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Search pattern (regex)\"},\"path\":{\"type\":\"string\",\"description\":\"Directory or file to search (default: .)\"},\"include\":{\"type\":\"string\",\"description\":\"Glob filter, e.g. \\\"*.ts\\\"\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Find files by filename pattern using shell find -name semantics. Returns matching file paths.\",\"name\":\"glob\",\"parameters\":{\"type\":\"object\",\"required\":[\"pattern\"],\"properties\":{\"pattern\":{\"type\":\"string\",\"description\":\"Filename pattern, e.g. \\\"*.ts\\\"\"},\"path\":{\"type\":\"string\",\"description\":\"Directory to search in (default: .)\"}}},\"strict\":false},{\"type\":\"function\",\"description\":\"Delegate a focused task to a detached child agent with its own context. Use this for independent research, file exploration, or parallel work. The task returns only its final answer to this conversation. No subagents are currently defined.\",\"name\":\"task\",\"parameters\":{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"description\":{\"type\":\"string\",\"description\":\"Short human-readable label for the delegated work\"},\"prompt\":{\"type\":\"string\",\"description\":\"Focused instructions for the child agent\"},\"agent\":{\"type\":\"string\",\"description\":\"Declared subagent to use for the child agent\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the child agent. AGENTS.md and skills are discovered from here.\"}}},\"strict\":false}],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":804,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":4,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":808},\"user\":null,\"metadata\":{}},\"sequence_number\":9}" + ], + "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": "a02dad1668335adb-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:19 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "321", + "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": "req_fdef3765899a4c91bc975a65974dd9bb" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 1, + "id": "f12aff3913439248", + "matchKey": "POST api.openai.com/v1/responses", + "recordedAt": "2026-05-28T13:41:21.738Z", + "request": { + "body": { + "kind": "json", + "value": { + "input": [ + { + "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", + "role": "system" + }, + { + "content": [ + { + "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with Step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to Step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to Step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", + "type": "input_text" + } + ], + "role": "user" + } + ], + "max_output_tokens": 32, + "model": "gpt-4o-mini", + "store": false, + "stream": true + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/responses" + }, + "response": { + "body": { + "chunks": [ + "event: response.created\ndata: {\"type\":\"response.created\",\"response\":{\"id\":\"resp_01ecf68325f9e202016a184600a16881a08ded2a1961eda9f9\",\"object\":\"response\",\"created_at\":1779975680,\"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\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_01ecf68325f9e202016a184600a16881a08ded2a1961eda9f9\",\"object\":\"response\",\"created_at\":1779975680,\"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\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"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_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"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_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"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_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"d6v2dmzPZ7YChr\",\"output_index\":0,\"sequence_number\":4}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Original\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"AQ3m9tJ\",\"output_index\":0,\"sequence_number\":5}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Request\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"UKhv1LKl\",\"output_index\":0,\"sequence_number\":6}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"\\n\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"5muwgiakPkjQduY\",\"output_index\":0,\"sequence_number\":7}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"The\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"gYHJ7xqWx893Q\",\"output_index\":0,\"sequence_number\":8}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" user\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"ta2Vk95LgSS\",\"output_index\":0,\"sequence_number\":9}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" requested\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"T18OOl\",\"output_index\":0,\"sequence_number\":10}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" to\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"CgWTkMgs6kW4s\",\"output_index\":0,\"sequence_number\":11}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" complete\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"PQ7u3KE\",\"output_index\":0,\"sequence_number\":12}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" an\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"fyFt8NlmxkL8T\",\"output_index\":0,\"sequence_number\":13}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" instrument\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"idBTA\",\"output_index\":0,\"sequence_number\":14}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"ed\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"Jqp8Abx3NlEpYO\",\"output_index\":0,\"sequence_number\":15}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" research\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"2Z7W3UL\",\"output_index\":0,\"sequence_number\":16}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" flow\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"CWcmUwdOK0I\",\"output_index\":0,\"sequence_number\":17}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" consisting\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"5A8K0\",\"output_index\":0,\"sequence_number\":18}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" of\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"8mUUf5KvarpcJ\",\"output_index\":0,\"sequence_number\":19}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" three\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"RpVzByEpb2\",\"output_index\":0,\"sequence_number\":20}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" specific\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"9qbTunN\",\"output_index\":0,\"sequence_number\":21}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" steps\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"sRljhC5wZy\",\"output_index\":0,\"sequence_number\":22}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\",\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"LQiEbRM4fizUNQm\",\"output_index\":0,\"sequence_number\":23}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" involving\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"CFyfLz\",\"output_index\":0,\"sequence_number\":24}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" calling\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"E6cI70HR\",\"output_index\":0,\"sequence_number\":25}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" various\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"GFRuEgJV\",\"output_index\":0,\"sequence_number\":26}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" tools\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"X4Ttj2uHGX\",\"output_index\":0,\"sequence_number\":27}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" in\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"9vlDZO40VZwFr\",\"output_index\":0,\"sequence_number\":28}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" a\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"tWdPAInHFKDip7\",\"output_index\":0,\"sequence_number\":29}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" sequential\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"Rct1b\",\"output_index\":0,\"sequence_number\":30}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" manner\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"0x4W3URIt\",\"output_index\":0,\"sequence_number\":31}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\".\\n\\n\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"EscdvHRY9LVkB\",\"output_index\":0,\"sequence_number\":32}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\"##\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"7fE3Nivp8RY0eK\",\"output_index\":0,\"sequence_number\":33}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Early\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"qsGDoylwsO\",\"output_index\":0,\"sequence_number\":34}", + "event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"content_index\":0,\"delta\":\" Progress\",\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"obfuscation\":\"WxaVUkk\",\"output_index\":0,\"sequence_number\":35}", + "event: response.output_text.done\ndata: {\"type\":\"response.output_text.done\",\"content_index\":0,\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"logprobs\":[],\"output_index\":0,\"sequence_number\":36,\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\\n\\n## Early Progress\"}", + "event: response.content_part.done\ndata: {\"type\":\"response.content_part.done\",\"content_index\":0,\"item_id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"output_index\":0,\"part\":{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\\n\\n## Early Progress\"},\"sequence_number\":37}", + "event: response.output_item.done\ndata: {\"type\":\"response.output_item.done\",\"item\":{\"id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\\n\\n## Early Progress\"}],\"role\":\"assistant\"},\"output_index\":0,\"sequence_number\":38}", + "event: response.incomplete\ndata: {\"type\":\"response.incomplete\",\"response\":{\"id\":\"resp_01ecf68325f9e202016a184600a16881a08ded2a1961eda9f9\",\"object\":\"response\",\"created_at\":1779975680,\"status\":\"incomplete\",\"background\":false,\"completed_at\":null,\"error\":null,\"frequency_penalty\":0,\"incomplete_details\":{\"reason\":\"max_output_tokens\"},\"instructions\":null,\"max_output_tokens\":32,\"max_tool_calls\":null,\"model\":\"gpt-4o-mini-2024-07-18\",\"moderation\":null,\"output\":[{\"id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\",\"type\":\"message\",\"status\":\"incomplete\",\"content\":[{\"type\":\"output_text\",\"annotations\":[],\"logprobs\":[],\"text\":\"## Original Request\\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\\n\\n## Early Progress\"}],\"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\":false,\"temperature\":1,\"text\":{\"format\":{\"type\":\"text\"},\"verbosity\":\"medium\"},\"tool_choice\":\"auto\",\"tools\":[],\"top_logprobs\":0,\"top_p\":1,\"truncation\":\"disabled\",\"usage\":{\"input_tokens\":694,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens\":32,\"output_tokens_details\":{\"reasoning_tokens\":0},\"total_tokens\":726},\"user\":null,\"metadata\":{}},\"sequence_number\":39}" + ], + "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": "a02dad234c015adb-VIE", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Thu, 28 May 2026 13:41:20 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "90", + "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": "req_2bb8f213d8be45a8a8c6368e34e80335" + }, + "status": 200, + "statusText": "OK" + } + } + ], + "meta": { + "createdAt": "2026-05-28T13:01:46.277Z" + } +} diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-auto-hook.span-tree.json b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-auto-hook.span-tree.json deleted file mode 100644 index 3bb3bbda2..000000000 --- a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-auto-hook.span-tree.json +++ /dev/null @@ -1,806 +0,0 @@ -{ - "span_tree": [ - { - "name": "flue-root", - "type": "task", - "children": [ - { - "name": "flue-prompt-operation", - "children": [ - { - "name": "flue.session.prompt", - "type": "task", - "children": [ - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - }, - { - "name": "tool: lookup", - "type": "tool", - "children": [], - "input": { - "query": "flue instrumentation" - }, - "output": { - "content": [ - { - "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "text" - } - ], - "details": { - "customTool": "lookup" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "lookup", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - "type": "text" - }, - { - "id": "", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - }, - { - "name": "tool: web_search", - "type": "tool", - "children": [], - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "output": { - "content": [ - { - "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "text" - } - ], - "details": { - "customTool": "web_search" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "web_search", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - "type": "text" - }, - { - "id": "", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==", - "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", - "type": "thinking" - }, - { - "text": "Now proceeding to step 2:", - "type": "text" - }, - { - "id": "", - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "name": "web_search", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "is_error": false, - "tool_use_id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - }, - { - "name": "tool: summarize_source", - "type": "tool", - "children": [], - "input": { - "url": "https://example.test/flue/reasoning-streams" - }, - "output": { - "content": [ - { - "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "type": "text" - } - ], - "details": { - "customTool": "summarize_source" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "summarize_source", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - "type": "thinking" - }, - { - "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - "type": "text" - }, - { - "id": "", - "input": { - "query": "flue instrumentation" - }, - "name": "lookup", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "is_error": false, - "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==", - "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", - "type": "thinking" - }, - { - "text": "Now proceeding to step 2:", - "type": "text" - }, - { - "id": "", - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "name": "web_search", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "is_error": false, - "tool_use_id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "signature": "EowDCm4IDRgCKkCpqmoUHjbaZYvB4bWm+hVDlxgU/iOCEn0v3xAMT4QsjKM7cIZMOWD2eEF8ENjGq0ttAvO8ZNI9YpiASikG2gnNMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI5+VQnffadMSNsXEGgy1YAi10m6jJ39wq2UiMAUy8rg67GdkT4VUKix3ULTWnPfKucap7VLRPGDqK7ZhF0nDl2pcYGshMviSbzOjuyrLAXh3IPAAc3rvDuYAAHaWed6JE7/4gg/gzWhfVeAb0qXzXoiIHh8Z9KyHDfDDfpesr4TzmJHT/T8mhem3UfZc87ZLzFom8Vi+76Y2eVWcoI/EyPuyj+KVxU5kPh030LYWxUeSTUViRu9NAd+Wzz/5ZAgD+TiEmCnpNMI3eGqOiBPtwK7y/JIvxZRWvsJ1ghXNaEVShN3h8OUk9zmzIhBuUujWVZtc5wuM28726mOqMLwKckegl+q2vNrR+U+AqbMSYWUVlWLKZvd1LXiZGAE=", - "thinking": "Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", - "type": "thinking" - }, - { - "text": "Now proceeding to step 3:", - "type": "text" - }, - { - "id": "", - "input": { - "url": "https://example.test/flue/reasoning-streams" - }, - "name": "summarize_source", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "is_error": false, - "tool_use_id": "toolu_01NHkkJuQNXyRuWk58FCecye", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - } - ], - "input": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "output": "PROMPT_DONE", - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.operation": "prompt", - "flue.session": "main", - "flue.thinking_level": "medium", - "flue.tools_count": 3, - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 546, - "duration_ms": 0, - "estimated_cost": 0.0136893, - "prompt_cache_creation_tokens": 670, - "prompt_cached_tokens": 9466, - "prompt_tokens": 49, - "tokens": 10731 - } - } - ], - "metadata": { - "operation": "prompt" - } - }, - { - "name": "flue-skill-operation", - "children": [ - { - "name": "flue.session.skill", - "type": "task", - "children": [ - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - }, - { - "name": "tool: read", - "type": "tool", - "children": [], - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "output": { - "content": [ - { - "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "type": "text" - } - ], - "details": { - "lines": 7, - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - } - }, - "metadata": { - "flue.session": "skill", - "flue.tool_name": "read", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "text": "I'll read the skill file and execute it according to its instructions.", - "type": "text" - }, - { - "id": "", - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "name": "read", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "is_error": false, - "tool_use_id": "toolu_01HmmsNYZUC67GqVoKKLbfiQ", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - } - ], - "input": { - "args": { - "marker": "SKILL_DONE" - }, - "name": "e2e-flue-skill" - }, - "output": "SKILL_DONE", - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.operation": "skill", - "flue.role": "skillRunner", - "flue.session": "skill", - "flue.skill_name": "e2e-flue-skill", - "flue.thinking_level": "off", - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 91, - "duration_ms": 0, - "estimated_cost": 0.0030298499999999997, - "prompt_cache_creation_tokens": 147, - "prompt_cached_tokens": 3622, - "prompt_tokens": 9, - "tokens": 3869 - } - } - ], - "metadata": { - "operation": "skill" - } - }, - { - "name": "flue-task-operation", - "children": [ - { - "name": "flue.session.task", - "type": "task", - "children": [ - { - "name": "flue.task", - "type": "task", - "children": [], - "input": "Reply with exactly TASK_DONE and no other text.", - "output": "TASK_DONE", - "metadata": { - "flue.session": "task", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly TASK_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "output": [ - { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "TASK_DONE", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" - } - ], - "metadata": { - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 4, - "prompt_cached_tokens": 0, - "prompt_tokens": 772, - "time_to_first_token": 0, - "tokens": 776 - } - } - ], - "input": "Reply with exactly TASK_DONE and no other text.", - "output": "TASK_DONE", - "metadata": { - "flue.model": "gpt-4o-mini", - "flue.operation": "task", - "flue.session": "task", - "flue.thinking_level": "off", - "model": "gpt-4o-mini", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 4, - "duration_ms": 0, - "estimated_cost": 0.0001182, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 772, - "tokens": 776 - } - } - ], - "metadata": { - "operation": "task" - } - }, - { - "name": "flue-compact-operation", - "children": [ - { - "name": "flue.session.compact", - "type": "task", - "children": [ - { - "name": "flue.compaction", - "type": "task", - "children": [], - "input": { - "estimatedTokens": 2915, - "reason": "manual" - }, - "output": { - "messagesAfter": 2, - "messagesBefore": 8 - }, - "metadata": { - "flue.compaction_reason": "manual", - "flue.session": "main", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 0, - "duration_ms": 0, - "estimated_cost": 0, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 0, - "tokens": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "metadata": { - "model": "gpt-4o-mini", - "provider": "openai" - }, - "metrics": { - "time_to_first_token": 0 - } - } - ], - "metadata": { - "flue.operation": "compact", - "flue.session": "main", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - } - ], - "metadata": { - "operation": "compact" - } - } - ], - "metadata": { - "scenario": "flue-instrumentation" - } - } - ] -} diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-auto-hook.span-tree.txt b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-auto-hook.span-tree.txt deleted file mode 100644 index 531dd15d1..000000000 --- a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-auto-hook.span-tree.txt +++ /dev/null @@ -1,706 +0,0 @@ -span_tree: -└── flue-root [task] - metadata: { - "scenario": "flue-instrumentation" - } - ├── flue-prompt-operation - │ metadata: { - │ "operation": "prompt" - │ } - │ └── flue.session.prompt [task] - │ input: "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text." - │ output: "PROMPT_DONE" - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.operation": "prompt", - │ "flue.session": "main", - │ "flue.thinking_level": "medium", - │ "flue.tools_count": 3, - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 546, - │ "duration_ms": 0, - │ "estimated_cost": 0.0136893, - │ "prompt_cache_creation_tokens": 670, - │ "prompt_cached_tokens": 9466, - │ "prompt_tokens": 49, - │ "tokens": 10731 - │ } - │ ├── anthropic.messages.create [llm] - │ │ input: [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "system" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "anthropic" - │ │ } - │ ├── tool: lookup [tool] - │ │ input: { - │ │ "query": "flue instrumentation" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "lookup" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "lookup", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ ├── anthropic.messages.create [llm] - │ │ input: [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - │ │ "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - │ │ "type": "thinking" - │ │ }, - │ │ { - │ │ "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - │ │ "type": "text" - │ │ }, - │ │ { - │ │ "id": "", - │ │ "input": { - │ │ "query": "flue instrumentation" - │ │ }, - │ │ "name": "lookup", - │ │ "type": "tool_use" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "is_error": false, - │ │ "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - │ │ "type": "tool_result" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "system" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "anthropic" - │ │ } - │ ├── tool: web_search [tool] - │ │ input: { - │ │ "lookupId": "flue-session-2026", - │ │ "query": "Braintrust Flue reasoning stream instrumentation" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "web_search" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "web_search", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ ├── anthropic.messages.create [llm] - │ │ input: [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - │ │ "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - │ │ "type": "thinking" - │ │ }, - │ │ { - │ │ "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - │ │ "type": "text" - │ │ }, - │ │ { - │ │ "id": "", - │ │ "input": { - │ │ "query": "flue instrumentation" - │ │ }, - │ │ "name": "lookup", - │ │ "type": "tool_use" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "is_error": false, - │ │ "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - │ │ "type": "tool_result" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "signature": "EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==", - │ │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", - │ │ "type": "thinking" - │ │ }, - │ │ { - │ │ "text": "Now proceeding to step 2:", - │ │ "type": "text" - │ │ }, - │ │ { - │ │ "id": "", - │ │ "input": { - │ │ "lookupId": "flue-session-2026", - │ │ "query": "Braintrust Flue reasoning stream instrumentation" - │ │ }, - │ │ "name": "web_search", - │ │ "type": "tool_use" - │ │ } - │ │ ], - │ │ "role": "assistant" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ │ "is_error": false, - │ │ "tool_use_id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - │ │ "type": "tool_result" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "system" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "anthropic" - │ │ } - │ ├── tool: summarize_source [tool] - │ │ input: { - │ │ "url": "https://example.test/flue/reasoning-streams" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "summarize_source" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "summarize_source", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── anthropic.messages.create [llm] - │ input: [ - │ { - │ "content": [ - │ { - │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "signature": "EtYFCm4IDRgCKkC/lJUT/EhYE72Jr10vREWOZ4vwSSugL9RsNrhJg9wjli7iCBt2/hEandW2KZpRqluVbV3ehHY/n0Mge6VmWF1cMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMHcfwfYOEmmJZGyBBGgyYm8sT/W36vQdF0dQiMFC5CVRWmqhR2r90pB0R8Wjbq0ITTIN0abxhOezE1NDsrj6CM4/DXLaOsJp4TD5DNCqVBEgEEzFdeaRrRB0CeXdlWoo+wf7yR9EMOVhLmyRf3nItrqN/cb30rpaexhXDm0/Hj3WxQH+o0K73Oyr6qtiDVe9xGNt6v5DrUz31HcE+GJ0Yw8ThoufXvqNyFQV3lLhpZExUDX6hwlmKvaRpj5YH+q5TTx3jAIgzD+zGkgUS0vC7Muftm2VZcuI/2wVsbtWo6hYdvbbdxr+8FzJsCOWc3ptVaUBimC5//HRSNBXFJ9zlkt6l7YxnUeKWiesSdE6h1EJ08Rp4OrAP+oaYWU4v6IODdnJmsqGKbN//i6gGCnAHBBAZr/pnnmEyUOsBGc6ARMOtcwjFIN3/B1YkJi8r8QbbtGHJHfH/v102MSZG8UJk2RXxt1fTQUWNbp0DjA7gUn00H3dnmSAQyqFjKLIFncnhiH5PSSgdvErNB7y/2UBk2CY2i4dpevr+7uvHZDLPjSBcovpvgJ4ihdUM9S080xCm1NNkjs+QP+AQAh20t33t7EN6aZS0+CZcfJxf1QV6mGIkL7BKAPeIXjD8TKuW/at4pqwrvvesI2cZY5RDjC7v7tz/+tqiEkob1s8J3jx2dbIgPBFOR5PFFwPby0H9Guv4ZB63YAlP3sXX+F5fC6fQifQeJK8fuWK+FKe3v+gK/hZcuBuU/Jfhrst4CsEWeaBhmPktZOHu5f85KZ/layh4Pp39yxR0FiHY5eXibsTh2SfDN3K6GAE=", - │ "thinking": "The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.", - │ "type": "thinking" - │ }, - │ { - │ "text": "I'll complete this instrumented research flow step by step. Starting with step 1:", - │ "type": "text" - │ }, - │ { - │ "id": "", - │ "input": { - │ "query": "flue instrumentation" - │ }, - │ "name": "lookup", - │ "type": "tool_use" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "content": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ "is_error": false, - │ "tool_use_id": "toolu_01QHXkUBddKx6pexY4WSjMR1", - │ "type": "tool_result" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "signature": "EpEDCm4IDRgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI25UM/xFQ9Bh625NGgyP2lwn3SKJlMxLUwciMH3VyS+uXCYaj8hlEdHVLz3HDLA5DCge72pzSyECwbUqqdxyZgtWjWYo/v0qA6XIsirQAQUbwyS/JWdGjeoTVbN2wMlsvu6j2cZmYMhk2HDKvmRIKpFTX5Ha82HBMwuM+f/7faDeQM5ldk8a5Tnm6iWFUj5jOoNqCYa+lBzhWor1vuZ5ieA569nGcMa0z1QmEP8WC3zNkI+kDazdS9FcuJP8KltHVfNr/wf/5AgAYFMt8fIaolvtJmN7uZ0yJKVfuJ58yx0nlQyEkxK8siXz7in2ulTuflohdD37ZErfxQNM3iYlCEfBOfa6kuJhwOwQ+HWJA1LXmUxzR/9AHRq0f3euNXkYAQ==", - │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", - │ "type": "thinking" - │ }, - │ { - │ "text": "Now proceeding to step 2:", - │ "type": "text" - │ }, - │ { - │ "id": "", - │ "input": { - │ "lookupId": "flue-session-2026", - │ "query": "Braintrust Flue reasoning stream instrumentation" - │ }, - │ "name": "web_search", - │ "type": "tool_use" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "content": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ "is_error": false, - │ "tool_use_id": "toolu_01CvT1mSWwETua7LWwSQiyq6", - │ "type": "tool_result" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "signature": "EowDCm4IDRgCKkCpqmoUHjbaZYvB4bWm+hVDlxgU/iOCEn0v3xAMT4QsjKM7cIZMOWD2eEF8ENjGq0ttAvO8ZNI9YpiASikG2gnNMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMI5+VQnffadMSNsXEGgy1YAi10m6jJ39wq2UiMAUy8rg67GdkT4VUKix3ULTWnPfKucap7VLRPGDqK7ZhF0nDl2pcYGshMviSbzOjuyrLAXh3IPAAc3rvDuYAAHaWed6JE7/4gg/gzWhfVeAb0qXzXoiIHh8Z9KyHDfDDfpesr4TzmJHT/T8mhem3UfZc87ZLzFom8Vi+76Y2eVWcoI/EyPuyj+KVxU5kPh030LYWxUeSTUViRu9NAd+Wzz/5ZAgD+TiEmCnpNMI3eGqOiBPtwK7y/JIvxZRWvsJ1ghXNaEVShN3h8OUk9zmzIhBuUujWVZtc5wuM28726mOqMLwKckegl+q2vNrR+U+AqbMSYWUVlWLKZvd1LXiZGAE=", - │ "thinking": "Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", - │ "type": "thinking" - │ }, - │ { - │ "text": "Now proceeding to step 3:", - │ "type": "text" - │ }, - │ { - │ "id": "", - │ "input": { - │ "url": "https://example.test/flue/reasoning-streams" - │ }, - │ "name": "summarize_source", - │ "type": "tool_use" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "cache_control": { - │ "type": "ephemeral" - │ }, - │ "content": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ "is_error": false, - │ "tool_use_id": "toolu_01NHkkJuQNXyRuWk58FCecye", - │ "type": "tool_result" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "cache_control": { - │ "type": "ephemeral" - │ }, - │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ "type": "text" - │ } - │ ], - │ "role": "system" - │ } - │ ] - │ metadata: { - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "anthropic" - │ } - ├── flue-skill-operation - │ metadata: { - │ "operation": "skill" - │ } - │ └── flue.session.skill [task] - │ input: { - │ "args": { - │ "marker": "SKILL_DONE" - │ }, - │ "name": "e2e-flue-skill" - │ } - │ output: "SKILL_DONE" - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.operation": "skill", - │ "flue.role": "skillRunner", - │ "flue.session": "skill", - │ "flue.skill_name": "e2e-flue-skill", - │ "flue.thinking_level": "off", - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 91, - │ "duration_ms": 0, - │ "estimated_cost": 0.0030298499999999997, - │ "prompt_cache_creation_tokens": 147, - │ "prompt_cached_tokens": 3622, - │ "prompt_tokens": 9, - │ "tokens": 3869 - │ } - │ ├── anthropic.messages.create [llm] - │ │ input: [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "system" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "anthropic" - │ │ } - │ ├── tool: read [tool] - │ │ input: { - │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "lines": 7, - │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "skill", - │ │ "flue.tool_name": "read", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── anthropic.messages.create [llm] - │ input: [ - │ { - │ "content": [ - │ { - │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "text": "I'll read the skill file and execute it according to its instructions.", - │ "type": "text" - │ }, - │ { - │ "id": "", - │ "input": { - │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ }, - │ "name": "read", - │ "type": "tool_use" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "cache_control": { - │ "type": "ephemeral" - │ }, - │ "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - │ "is_error": false, - │ "tool_use_id": "toolu_01HmmsNYZUC67GqVoKKLbfiQ", - │ "type": "tool_result" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "cache_control": { - │ "type": "ephemeral" - │ }, - │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - │ "type": "text" - │ } - │ ], - │ "role": "system" - │ } - │ ] - │ metadata: { - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "anthropic" - │ } - ├── flue-task-operation - │ metadata: { - │ "operation": "task" - │ } - │ └── flue.session.task [task] - │ input: "Reply with exactly TASK_DONE and no other text." - │ output: "TASK_DONE" - │ metadata: { - │ "flue.model": "gpt-4o-mini", - │ "flue.operation": "task", - │ "flue.session": "task", - │ "flue.thinking_level": "off", - │ "model": "gpt-4o-mini", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 4, - │ "duration_ms": 0, - │ "estimated_cost": 0.0001182, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 772, - │ "tokens": 776 - │ } - │ ├── flue.task [task] - │ │ input: "Reply with exactly TASK_DONE and no other text." - │ │ output: "TASK_DONE" - │ │ metadata: { - │ │ "flue.session": "task", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── openai.responses.create [llm] - │ input: [ - │ { - │ "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ "role": "system" - │ }, - │ { - │ "content": [ - │ { - │ "text": "Reply with exactly TASK_DONE and no other text.", - │ "type": "input_text" - │ } - │ ], - │ "role": "user" - │ } - │ ] - │ output: [ - │ { - │ "content": [ - │ { - │ "annotations": [], - │ "logprobs": [], - │ "text": "TASK_DONE", - │ "type": "output_text" - │ } - │ ], - │ "id": "", - │ "role": "assistant", - │ "status": "completed", - │ "type": "message" - │ } - │ ] - │ metadata: { - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai" - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 4, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 772, - │ "time_to_first_token": 0, - │ "tokens": 776 - │ } - └── flue-compact-operation - metadata: { - "operation": "compact" - } - └── flue.session.compact [task] - metadata: { - "flue.operation": "compact", - "flue.session": "main", - "provider": "flue" - } - metrics: { - "duration_ms": 0 - } - ├── flue.compaction [task] - │ input: { - │ "estimatedTokens": 2915, - │ "reason": "manual" - │ } - │ output: { - │ "messagesAfter": 2, - │ "messagesBefore": 8 - │ } - │ metadata: { - │ "flue.compaction_reason": "manual", - │ "flue.session": "main", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 0, - │ "duration_ms": 0, - │ "estimated_cost": 0, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 0, - │ "tokens": 0 - │ } - └── openai.responses.create [llm] - input: [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a specific instrumented research flow with these steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url and call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\" and no other text\n\nThe user emphasizes calling exactly one tool per turn and waiting for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ] - metadata: { - "model": "gpt-4o-mini", - "provider": "openai" - } - metrics: { - "time_to_first_token": 0 - } diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-openai-auto-hook.span-tree.json b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-openai-auto-hook.span-tree.json deleted file mode 100644 index 5a7a2b108..000000000 --- a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-openai-auto-hook.span-tree.json +++ /dev/null @@ -1,712 +0,0 @@ -{ - "span_tree": [ - { - "name": "flue-root", - "type": "task", - "children": [ - { - "name": "flue-prompt-operation", - "children": [ - { - "name": "flue.session.prompt", - "type": "task", - "children": [ - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "output": [ - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "", - "name": "lookup", - "status": "completed", - "type": "function_call" - } - ], - "metadata": { - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 16, - "prompt_cached_tokens": 0, - "prompt_tokens": 946, - "time_to_first_token": 0, - "tokens": 962 - } - }, - { - "name": "tool: lookup", - "type": "tool", - "children": [], - "input": { - "query": "flue instrumentation" - }, - "output": { - "content": [ - { - "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "text" - } - ], - "details": { - "customTool": "lookup" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "lookup", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - }, - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "", - "name": "lookup", - "type": "function_call" - }, - { - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "function_call_output" - } - ], - "output": [ - { - "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "id": "", - "name": "web_search", - "status": "completed", - "type": "function_call" - } - ], - "metadata": { - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 31, - "prompt_cached_tokens": 0, - "prompt_tokens": 987, - "time_to_first_token": 0, - "tokens": 1018 - } - }, - { - "name": "tool: web_search", - "type": "tool", - "children": [], - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "output": { - "content": [ - { - "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "text" - } - ], - "details": { - "customTool": "web_search" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "web_search", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - }, - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "", - "name": "lookup", - "type": "function_call" - }, - { - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "function_call_output" - }, - { - "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "id": "", - "name": "web_search", - "type": "function_call" - }, - { - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "output": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "function_call_output" - } - ], - "output": [ - { - "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - "id": "", - "name": "summarize_source", - "status": "completed", - "type": "function_call" - } - ], - "metadata": { - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 27, - "prompt_cached_tokens": 0, - "prompt_tokens": 1070, - "time_to_first_token": 0, - "tokens": 1097 - } - }, - { - "name": "tool: summarize_source", - "type": "tool", - "children": [], - "input": { - "url": "https://example.test/flue/reasoning-streams" - }, - "output": { - "content": [ - { - "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "type": "text" - } - ], - "details": { - "customTool": "summarize_source" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "summarize_source", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - }, - { - "arguments": "{\"query\":\"flue instrumentation\"}", - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "id": "", - "name": "lookup", - "type": "function_call" - }, - { - "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "function_call_output" - }, - { - "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "id": "", - "name": "web_search", - "type": "function_call" - }, - { - "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - "output": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "function_call_output" - }, - { - "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - "id": "", - "name": "summarize_source", - "type": "function_call" - }, - { - "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - "output": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "type": "function_call_output" - } - ], - "output": [ - { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "PROMPT_DONE", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" - } - ], - "metadata": { - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 5, - "prompt_cached_tokens": 1024, - "prompt_tokens": 1136, - "time_to_first_token": 0, - "tokens": 1141 - } - } - ], - "input": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "output": "PROMPT_DONE", - "metadata": { - "flue.model": "gpt-4o-mini", - "flue.operation": "prompt", - "flue.session": "main", - "flue.thinking_level": "off", - "flue.tools_count": 3, - "model": "gpt-4o-mini", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 79, - "duration_ms": 0, - "estimated_cost": 0.00059657, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 1024, - "prompt_tokens": 3115, - "tokens": 4218 - } - } - ], - "metadata": { - "operation": "prompt" - } - }, - { - "name": "flue-skill-operation", - "children": [ - { - "name": "flue.session.skill", - "type": "task", - "children": [ - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - }, - { - "name": "tool: read", - "type": "tool", - "children": [], - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "output": { - "content": [ - { - "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "type": "text" - } - ], - "details": { - "lines": 7, - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - } - }, - "metadata": { - "flue.session": "skill", - "flue.tool_name": "read", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "anthropic.messages.create", - "type": "llm", - "children": [], - "input": [ - { - "content": [ - { - "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - "type": "text" - } - ], - "role": "user" - }, - { - "content": [ - { - "text": "I'll run the e2e-flue-skill by reading its instructions and following them.", - "type": "text" - }, - { - "id": "", - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "name": "read", - "type": "tool_use" - } - ], - "role": "assistant" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "is_error": false, - "tool_use_id": "toolu_01M5rfFBDvwquiyfz2B1GNYz", - "type": "tool_result" - } - ], - "role": "user" - }, - { - "content": [ - { - "cache_control": { - "type": "ephemeral" - }, - "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - "type": "text" - } - ], - "role": "system" - } - ], - "metadata": { - "model": "claude-sonnet-4-5-20250929", - "provider": "anthropic" - } - } - ], - "input": { - "args": { - "marker": "SKILL_DONE" - }, - "name": "e2e-flue-skill" - }, - "output": "SKILL_DONE", - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.operation": "skill", - "flue.role": "skillRunner", - "flue.session": "skill", - "flue.skill_name": "e2e-flue-skill", - "flue.thinking_level": "off", - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 97, - "duration_ms": 0, - "estimated_cost": 0.0026144999999999996, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 3775, - "prompt_tokens": 9, - "tokens": 3881 - } - } - ], - "metadata": { - "operation": "skill" - } - }, - { - "name": "flue-task-operation", - "children": [ - { - "name": "flue.session.task", - "type": "task", - "children": [ - { - "name": "flue.task", - "type": "task", - "children": [], - "input": "Reply with exactly TASK_DONE and no other text.", - "output": "TASK_DONE", - "metadata": { - "flue.session": "task", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - "role": "system" - }, - { - "content": [ - { - "text": "Reply with exactly TASK_DONE and no other text.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "output": [ - { - "content": [ - { - "annotations": [], - "logprobs": [], - "text": "TASK_DONE", - "type": "output_text" - } - ], - "id": "", - "role": "assistant", - "status": "completed", - "type": "message" - } - ], - "metadata": { - "model": "gpt-4o-mini-2024-07-18", - "provider": "openai" - }, - "metrics": { - "completion_reasoning_tokens": 0, - "completion_tokens": 4, - "prompt_cached_tokens": 0, - "prompt_tokens": 772, - "time_to_first_token": 0, - "tokens": 776 - } - } - ], - "input": "Reply with exactly TASK_DONE and no other text.", - "output": "TASK_DONE", - "metadata": { - "flue.model": "gpt-4o-mini", - "flue.operation": "task", - "flue.session": "task", - "flue.thinking_level": "off", - "model": "gpt-4o-mini", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 4, - "duration_ms": 0, - "estimated_cost": 0.0001182, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 772, - "tokens": 776 - } - } - ], - "metadata": { - "operation": "task" - } - }, - { - "name": "flue-compact-operation", - "children": [ - { - "name": "flue.session.compact", - "type": "task", - "children": [ - { - "name": "flue.compaction", - "type": "task", - "children": [], - "input": { - "estimatedTokens": 1141, - "reason": "manual" - }, - "output": { - "messagesAfter": 2, - "messagesBefore": 8 - }, - "metadata": { - "flue.compaction_reason": "manual", - "flue.session": "main", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 0, - "duration_ms": 0, - "estimated_cost": 0, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 0, - "tokens": 0 - } - }, - { - "name": "openai.responses.create", - "type": "llm", - "children": [], - "input": [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ], - "metadata": { - "model": "gpt-4o-mini", - "provider": "openai" - }, - "metrics": { - "time_to_first_token": 0 - } - } - ], - "metadata": { - "flue.operation": "compact", - "flue.session": "main", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - } - ], - "metadata": { - "operation": "compact" - } - } - ], - "metadata": { - "scenario": "flue-instrumentation" - } - } - ] -} diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-openai-auto-hook.span-tree.txt b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-openai-auto-hook.span-tree.txt deleted file mode 100644 index b75469cd2..000000000 --- a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-openai-auto-hook.span-tree.txt +++ /dev/null @@ -1,612 +0,0 @@ -span_tree: -└── flue-root [task] - metadata: { - "scenario": "flue-instrumentation" - } - ├── flue-prompt-operation - │ metadata: { - │ "operation": "prompt" - │ } - │ └── flue.session.prompt [task] - │ input: "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text." - │ output: "PROMPT_DONE" - │ metadata: { - │ "flue.model": "gpt-4o-mini", - │ "flue.operation": "prompt", - │ "flue.session": "main", - │ "flue.thinking_level": "off", - │ "flue.tools_count": 3, - │ "model": "gpt-4o-mini", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 79, - │ "duration_ms": 0, - │ "estimated_cost": 0.00059657, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 1024, - │ "prompt_tokens": 3115, - │ "tokens": 4218 - │ } - │ ├── openai.responses.create [llm] - │ │ input: [ - │ │ { - │ │ "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ │ "role": "system" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ │ "type": "input_text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ } - │ │ ] - │ │ output: [ - │ │ { - │ │ "arguments": "{\"query\":\"flue instrumentation\"}", - │ │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ │ "id": "", - │ │ "name": "lookup", - │ │ "status": "completed", - │ │ "type": "function_call" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "gpt-4o-mini-2024-07-18", - │ │ "provider": "openai" - │ │ } - │ │ metrics: { - │ │ "completion_reasoning_tokens": 0, - │ │ "completion_tokens": 16, - │ │ "prompt_cached_tokens": 0, - │ │ "prompt_tokens": 946, - │ │ "time_to_first_token": 0, - │ │ "tokens": 962 - │ │ } - │ ├── tool: lookup [tool] - │ │ input: { - │ │ "query": "flue instrumentation" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "lookup" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "lookup", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ ├── openai.responses.create [llm] - │ │ input: [ - │ │ { - │ │ "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ │ "role": "system" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ │ "type": "input_text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "arguments": "{\"query\":\"flue instrumentation\"}", - │ │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ │ "id": "", - │ │ "name": "lookup", - │ │ "type": "function_call" - │ │ }, - │ │ { - │ │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ │ "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "type": "function_call_output" - │ │ } - │ │ ] - │ │ output: [ - │ │ { - │ │ "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - │ │ "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - │ │ "id": "", - │ │ "name": "web_search", - │ │ "status": "completed", - │ │ "type": "function_call" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "gpt-4o-mini-2024-07-18", - │ │ "provider": "openai" - │ │ } - │ │ metrics: { - │ │ "completion_reasoning_tokens": 0, - │ │ "completion_tokens": 31, - │ │ "prompt_cached_tokens": 0, - │ │ "prompt_tokens": 987, - │ │ "time_to_first_token": 0, - │ │ "tokens": 1018 - │ │ } - │ ├── tool: web_search [tool] - │ │ input: { - │ │ "lookupId": "flue-session-2026", - │ │ "query": "Braintrust Flue reasoning stream instrumentation" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "web_search" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "web_search", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ ├── openai.responses.create [llm] - │ │ input: [ - │ │ { - │ │ "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ │ "role": "system" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ │ "type": "input_text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "arguments": "{\"query\":\"flue instrumentation\"}", - │ │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ │ "id": "", - │ │ "name": "lookup", - │ │ "type": "function_call" - │ │ }, - │ │ { - │ │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ │ "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "type": "function_call_output" - │ │ }, - │ │ { - │ │ "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - │ │ "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - │ │ "id": "", - │ │ "name": "web_search", - │ │ "type": "function_call" - │ │ }, - │ │ { - │ │ "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - │ │ "output": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ │ "type": "function_call_output" - │ │ } - │ │ ] - │ │ output: [ - │ │ { - │ │ "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ │ "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - │ │ "id": "", - │ │ "name": "summarize_source", - │ │ "status": "completed", - │ │ "type": "function_call" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "gpt-4o-mini-2024-07-18", - │ │ "provider": "openai" - │ │ } - │ │ metrics: { - │ │ "completion_reasoning_tokens": 0, - │ │ "completion_tokens": 27, - │ │ "prompt_cached_tokens": 0, - │ │ "prompt_tokens": 1070, - │ │ "time_to_first_token": 0, - │ │ "tokens": 1097 - │ │ } - │ ├── tool: summarize_source [tool] - │ │ input: { - │ │ "url": "https://example.test/flue/reasoning-streams" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "summarize_source" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "summarize_source", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── openai.responses.create [llm] - │ input: [ - │ { - │ "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ "role": "system" - │ }, - │ { - │ "content": [ - │ { - │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - │ "type": "input_text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "arguments": "{\"query\":\"flue instrumentation\"}", - │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ "id": "", - │ "name": "lookup", - │ "type": "function_call" - │ }, - │ { - │ "call_id": "call_xELft1kjhTSvPWAp3Z3i4zWk", - │ "output": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ "type": "function_call_output" - │ }, - │ { - │ "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - │ "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - │ "id": "", - │ "name": "web_search", - │ "type": "function_call" - │ }, - │ { - │ "call_id": "call_F7zI4fCOw4jk7rTwqbi8umo7", - │ "output": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ "type": "function_call_output" - │ }, - │ { - │ "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - │ "id": "", - │ "name": "summarize_source", - │ "type": "function_call" - │ }, - │ { - │ "call_id": "call_0yinp9edeamv8mKgyhkpaCmG", - │ "output": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ "type": "function_call_output" - │ } - │ ] - │ output: [ - │ { - │ "content": [ - │ { - │ "annotations": [], - │ "logprobs": [], - │ "text": "PROMPT_DONE", - │ "type": "output_text" - │ } - │ ], - │ "id": "", - │ "role": "assistant", - │ "status": "completed", - │ "type": "message" - │ } - │ ] - │ metadata: { - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai" - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 5, - │ "prompt_cached_tokens": 1024, - │ "prompt_tokens": 1136, - │ "time_to_first_token": 0, - │ "tokens": 1141 - │ } - ├── flue-skill-operation - │ metadata: { - │ "operation": "skill" - │ } - │ └── flue.session.skill [task] - │ input: { - │ "args": { - │ "marker": "SKILL_DONE" - │ }, - │ "name": "e2e-flue-skill" - │ } - │ output: "SKILL_DONE" - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.operation": "skill", - │ "flue.role": "skillRunner", - │ "flue.session": "skill", - │ "flue.skill_name": "e2e-flue-skill", - │ "flue.thinking_level": "off", - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 97, - │ "duration_ms": 0, - │ "estimated_cost": 0.0026144999999999996, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 3775, - │ "prompt_tokens": 9, - │ "tokens": 3881 - │ } - │ ├── anthropic.messages.create [llm] - │ │ input: [ - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "user" - │ │ }, - │ │ { - │ │ "content": [ - │ │ { - │ │ "cache_control": { - │ │ "type": "ephemeral" - │ │ }, - │ │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "role": "system" - │ │ } - │ │ ] - │ │ metadata: { - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "anthropic" - │ │ } - │ ├── tool: read [tool] - │ │ input: { - │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "lines": 7, - │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "skill", - │ │ "flue.tool_name": "read", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── anthropic.messages.create [llm] - │ input: [ - │ { - │ "content": [ - │ { - │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", - │ "type": "text" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "text": "I'll run the e2e-flue-skill by reading its instructions and following them.", - │ "type": "text" - │ }, - │ { - │ "id": "", - │ "input": { - │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ }, - │ "name": "read", - │ "type": "tool_use" - │ } - │ ], - │ "role": "assistant" - │ }, - │ { - │ "content": [ - │ { - │ "cache_control": { - │ "type": "ephemeral" - │ }, - │ "content": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - │ "is_error": false, - │ "tool_use_id": "toolu_01M5rfFBDvwquiyfz2B1GNYz", - │ "type": "tool_result" - │ } - │ ], - │ "role": "user" - │ }, - │ { - │ "content": [ - │ { - │ "cache_control": { - │ "type": "ephemeral" - │ }, - │ "text": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts\n\n\nNever call the task tool. Do not delegate e2e-flue-skill to another session. If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool. Return the marker from the Arguments object exactly, with no other text.\n", - │ "type": "text" - │ } - │ ], - │ "role": "system" - │ } - │ ] - │ metadata: { - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "anthropic" - │ } - ├── flue-task-operation - │ metadata: { - │ "operation": "task" - │ } - │ └── flue.session.task [task] - │ input: "Reply with exactly TASK_DONE and no other text." - │ output: "TASK_DONE" - │ metadata: { - │ "flue.model": "gpt-4o-mini", - │ "flue.operation": "task", - │ "flue.session": "task", - │ "flue.thinking_level": "off", - │ "model": "gpt-4o-mini", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 4, - │ "duration_ms": 0, - │ "estimated_cost": 0.0001182, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 772, - │ "tokens": 776 - │ } - │ ├── flue.task [task] - │ │ input: "Reply with exactly TASK_DONE and no other text." - │ │ output: "TASK_DONE" - │ │ metadata: { - │ │ "flue.session": "task", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── openai.responses.create [llm] - │ input: [ - │ { - │ "content": "You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input. Make your best judgment and proceed independently.\n\n## Available Skills\n\nEach skill below is documented in a markdown file under `.agents/skills/` (relative to your working directory). The default location is `.agents/skills//SKILL.md`. When asked to run a skill, read its file from disk and follow the instructions there literally — the skill body is not provided inline.\n\n- **e2e-flue-skill** — Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n\nDate: \nWorking directory: /e2e/scenarios/flue-instrumentation/\n\nDirectory structure:\n.agents\n__cassettes__\n__snapshots__\nassertions.ts\ncassette-filter.mjs\nconstants.mjs\nnode_modules\npackage.json\npnpm-lock.yaml\nscenario.impl.mjs\nscenario.mjs\nscenario.test.ts\nscenario.ts", - │ "role": "system" - │ }, - │ { - │ "content": [ - │ { - │ "text": "Reply with exactly TASK_DONE and no other text.", - │ "type": "input_text" - │ } - │ ], - │ "role": "user" - │ } - │ ] - │ output: [ - │ { - │ "content": [ - │ { - │ "annotations": [], - │ "logprobs": [], - │ "text": "TASK_DONE", - │ "type": "output_text" - │ } - │ ], - │ "id": "", - │ "role": "assistant", - │ "status": "completed", - │ "type": "message" - │ } - │ ] - │ metadata: { - │ "model": "gpt-4o-mini-2024-07-18", - │ "provider": "openai" - │ } - │ metrics: { - │ "completion_reasoning_tokens": 0, - │ "completion_tokens": 4, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 772, - │ "time_to_first_token": 0, - │ "tokens": 776 - │ } - └── flue-compact-operation - metadata: { - "operation": "compact" - } - └── flue.session.compact [task] - metadata: { - "flue.operation": "compact", - "flue.session": "main", - "provider": "flue" - } - metrics: { - "duration_ms": 0 - } - ├── flue.compaction [task] - │ input: { - │ "estimatedTokens": 1141, - │ "reason": "manual" - │ } - │ output: { - │ "messagesAfter": 2, - │ "messagesBefore": 8 - │ } - │ metadata: { - │ "flue.compaction_reason": "manual", - │ "flue.session": "main", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 0, - │ "duration_ms": 0, - │ "estimated_cost": 0, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 0, - │ "tokens": 0 - │ } - └── openai.responses.create [llm] - input: [ - { - "content": "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.", - "role": "system" - }, - { - "content": [ - { - "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", - "type": "input_text" - } - ], - "role": "user" - } - ] - metadata: { - "model": "gpt-4o-mini", - "provider": "openai" - } - metrics: { - "time_to_first_token": 0 - } diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-wrapped.span-tree.json b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-wrapped.span-tree.json deleted file mode 100644 index 1ce6af8fb..000000000 --- a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-wrapped.span-tree.json +++ /dev/null @@ -1,551 +0,0 @@ -{ - "span_tree": [ - { - "name": "flue-root", - "type": "task", - "children": [ - { - "name": "flue-prompt-operation", - "children": [ - { - "name": "flue.session.prompt", - "type": "task", - "children": [ - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "toolUse", - "index": 0, - "message": { - "content": "I'll complete this instrumented research flow step by step. Starting with Step 1:", - "reasoning": "The user wants me to complete an instrumented research flow with specific steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id to call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url to call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\"\n\nI need to call exactly one tool per turn and wait for each result. Let me start with step 1.", - "role": "assistant", - "tool_calls": [ - { - "function": { - "arguments": "{\"query\":\"flue instrumentation\"}", - "name": "lookup" - }, - "id": "", - "type": "function" - } - ] - } - } - ], - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.session": "main", - "flue.thinking": true, - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 198, - "duration_ms": 0, - "estimated_cost": 0.00671535, - "prompt_cache_creation_tokens": 887, - "prompt_cached_tokens": 1297, - "prompt_tokens": 10, - "tokens": 2392 - } - }, - { - "name": "tool: lookup", - "type": "tool", - "children": [], - "input": { - "query": "flue instrumentation" - }, - "output": { - "content": [ - { - "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - "type": "text" - } - ], - "details": { - "customTool": "lookup" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "lookup", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "toolUse", - "index": 0, - "message": { - "content": "Now proceeding to Step 2 with the lookup ID:", - "reasoning": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to Step 2 and use this id as the lookupId parameter when calling web_search with the query \"Braintrust Flue reasoning stream instrumentation\".", - "role": "assistant", - "tool_calls": [ - { - "function": { - "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - "name": "web_search" - }, - "id": "", - "type": "function" - } - ] - } - } - ], - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.session": "main", - "flue.thinking": true, - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 169, - "duration_ms": 0, - "estimated_cost": 0.0041217, - "prompt_cache_creation_tokens": 238, - "prompt_cached_tokens": 2184, - "prompt_tokens": 13, - "tokens": 2604 - } - }, - { - "name": "tool: web_search", - "type": "tool", - "children": [], - "input": { - "lookupId": "flue-session-2026", - "query": "Braintrust Flue reasoning stream instrumentation" - }, - "output": { - "content": [ - { - "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - "type": "text" - } - ], - "details": { - "customTool": "web_search" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "web_search", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "toolUse", - "index": 0, - "message": { - "content": "Now proceeding to Step 3 with the first result URL:", - "reasoning": "Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to Step 3 and call summarize_source with this URL.", - "role": "assistant", - "tool_calls": [ - { - "function": { - "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - "name": "summarize_source" - }, - "id": "", - "type": "function" - } - ] - } - } - ], - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.session": "main", - "flue.thinking": true, - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 139, - "duration_ms": 0, - "estimated_cost": 0.00376935, - "prompt_cache_creation_tokens": 245, - "prompt_cached_tokens": 2422, - "prompt_tokens": 13, - "tokens": 2819 - } - }, - { - "name": "tool: summarize_source", - "type": "tool", - "children": [], - "input": { - "url": "https://example.test/flue/reasoning-streams" - }, - "output": { - "content": [ - { - "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - "type": "text" - } - ], - "details": { - "customTool": "summarize_source" - } - }, - "metadata": { - "flue.session": "main", - "flue.tool_name": "summarize_source", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "stop", - "index": 0, - "message": { - "content": "PROMPT_DONE", - "reasoning": "The summarize_source call has returned successfully. According to the instructions, I now need to reply with exactly \"PROMPT_DONE\" and no other text.", - "role": "assistant" - } - } - ], - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.session": "main", - "flue.thinking": true, - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 50, - "duration_ms": 0, - "estimated_cost": 0.00232035, - "prompt_cache_creation_tokens": 195, - "prompt_cached_tokens": 2667, - "prompt_tokens": 13, - "tokens": 2925 - } - } - ], - "input": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - "output": "PROMPT_DONE", - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.operation": "prompt", - "flue.session": "main", - "flue.thinking_level": "medium", - "flue.tools_count": 3, - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 556, - "duration_ms": 0, - "estimated_cost": 0.01692675, - "prompt_cache_creation_tokens": 1565, - "prompt_cached_tokens": 8570, - "prompt_tokens": 49, - "tokens": 10740 - } - } - ], - "metadata": { - "operation": "prompt" - } - }, - { - "name": "flue-skill-operation", - "children": [ - { - "name": "flue.session.skill", - "type": "task", - "children": [ - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "toolUse", - "index": 0, - "message": { - "content": "I'll run the e2e-flue-skill by reading its instructions and following them.", - "role": "assistant", - "tool_calls": [ - { - "function": { - "arguments": "{\"path\":\".agents/skills/e2e-flue-skill/SKILL.md\"}", - "name": "read" - }, - "id": "", - "type": "function" - } - ] - } - } - ], - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.session": "skill", - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 89, - "duration_ms": 0, - "estimated_cost": 0.0043644, - "prompt_cache_creation_tokens": 718, - "prompt_cached_tokens": 1093, - "prompt_tokens": 3, - "tokens": 1903 - } - }, - { - "name": "tool: read", - "type": "tool", - "children": [], - "input": { - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - }, - "output": { - "content": [ - { - "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - "type": "text" - } - ], - "details": { - "lines": 7, - "path": ".agents/skills/e2e-flue-skill/SKILL.md" - } - }, - "metadata": { - "flue.session": "skill", - "flue.tool_name": "read", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "stop", - "index": 0, - "message": { - "content": "SKILL_DONE", - "role": "assistant" - } - } - ], - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.session": "skill", - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 8, - "duration_ms": 0, - "estimated_cost": 0.00125505, - "prompt_cache_creation_tokens": 153, - "prompt_cached_tokens": 1811, - "prompt_tokens": 6, - "tokens": 1978 - } - } - ], - "input": { - "args": { - "marker": "SKILL_DONE" - }, - "name": "e2e-flue-skill" - }, - "output": "SKILL_DONE", - "metadata": { - "flue.model": "claude-sonnet-4-5-20250929", - "flue.operation": "skill", - "flue.role": "skillRunner", - "flue.session": "skill", - "flue.skill_name": "e2e-flue-skill", - "flue.thinking_level": "off", - "model": "claude-sonnet-4-5-20250929", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 97, - "duration_ms": 0, - "estimated_cost": 0.00561945, - "prompt_cache_creation_tokens": 871, - "prompt_cached_tokens": 2904, - "prompt_tokens": 9, - "tokens": 3881 - } - } - ], - "metadata": { - "operation": "skill" - } - }, - { - "name": "flue-task-operation", - "children": [ - { - "name": "flue.session.task", - "type": "task", - "children": [ - { - "name": "flue.task", - "type": "task", - "children": [], - "input": "Reply with exactly TASK_DONE and no other text.", - "output": "TASK_DONE", - "metadata": { - "flue.session": "task", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - }, - { - "name": "flue.turn", - "type": "llm", - "children": [], - "output": [ - { - "finish_reason": "stop", - "index": 0, - "message": { - "content": "TASK_DONE", - "role": "assistant" - } - } - ], - "metadata": { - "flue.model": "gpt-4o-mini", - "flue.session": "task:task:", - "model": "gpt-4o-mini", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 4, - "duration_ms": 0, - "estimated_cost": 0.0001182, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 772, - "tokens": 776 - } - } - ], - "input": "Reply with exactly TASK_DONE and no other text.", - "output": "TASK_DONE", - "metadata": { - "flue.model": "gpt-4o-mini", - "flue.operation": "task", - "flue.session": "task", - "flue.thinking_level": "off", - "model": "gpt-4o-mini", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 4, - "duration_ms": 0, - "estimated_cost": 0.0001182, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 772, - "tokens": 776 - } - } - ], - "metadata": { - "operation": "task" - } - }, - { - "name": "flue-compact-operation", - "children": [ - { - "name": "flue.session.compact", - "type": "task", - "children": [ - { - "name": "flue.compaction", - "type": "task", - "children": [], - "input": { - "estimatedTokens": 2925, - "reason": "manual" - }, - "output": { - "messagesAfter": 2, - "messagesBefore": 8 - }, - "metadata": { - "flue.compaction_reason": "manual", - "flue.session": "main", - "provider": "flue" - }, - "metrics": { - "completion_tokens": 0, - "duration_ms": 0, - "estimated_cost": 0, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 0, - "tokens": 0 - } - } - ], - "metadata": { - "flue.operation": "compact", - "flue.session": "main", - "provider": "flue" - }, - "metrics": { - "duration_ms": 0 - } - } - ], - "metadata": { - "operation": "compact" - } - } - ], - "metadata": { - "scenario": "flue-instrumentation" - } - } - ] -} diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-wrapped.span-tree.txt b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-wrapped.span-tree.txt deleted file mode 100644 index 2fd3e69cd..000000000 --- a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-7-0-wrapped.span-tree.txt +++ /dev/null @@ -1,455 +0,0 @@ -span_tree: -└── flue-root [task] - metadata: { - "scenario": "flue-instrumentation" - } - ├── flue-prompt-operation - │ metadata: { - │ "operation": "prompt" - │ } - │ └── flue.session.prompt [task] - │ input: "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text." - │ output: "PROMPT_DONE" - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.operation": "prompt", - │ "flue.session": "main", - │ "flue.thinking_level": "medium", - │ "flue.tools_count": 3, - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 556, - │ "duration_ms": 0, - │ "estimated_cost": 0.01692675, - │ "prompt_cache_creation_tokens": 1565, - │ "prompt_cached_tokens": 8570, - │ "prompt_tokens": 49, - │ "tokens": 10740 - │ } - │ ├── flue.turn [llm] - │ │ output: [ - │ │ { - │ │ "finish_reason": "toolUse", - │ │ "index": 0, - │ │ "message": { - │ │ "content": "I'll complete this instrumented research flow step by step. Starting with Step 1:", - │ │ "reasoning": "The user wants me to complete an instrumented research flow with specific steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Use the lookup result id to call web_search with query \"Braintrust Flue reasoning stream instrumentation\"\n3. Use the first web_search result url to call summarize_source\n4. After summarize_source returns, reply with exactly \"PROMPT_DONE\"\n\nI need to call exactly one tool per turn and wait for each result. Let me start with step 1.", - │ │ "role": "assistant", - │ │ "tool_calls": [ - │ │ { - │ │ "function": { - │ │ "arguments": "{\"query\":\"flue instrumentation\"}", - │ │ "name": "lookup" - │ │ }, - │ │ "id": "", - │ │ "type": "function" - │ │ } - │ │ ] - │ │ } - │ │ } - │ │ ] - │ │ metadata: { - │ │ "flue.model": "claude-sonnet-4-5-20250929", - │ │ "flue.session": "main", - │ │ "flue.thinking": true, - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "completion_tokens": 198, - │ │ "duration_ms": 0, - │ │ "estimated_cost": 0.00671535, - │ │ "prompt_cache_creation_tokens": 887, - │ │ "prompt_cached_tokens": 1297, - │ │ "prompt_tokens": 10, - │ │ "tokens": 2392 - │ │ } - │ ├── tool: lookup [tool] - │ │ input: { - │ │ "query": "flue instrumentation" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "lookup" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "lookup", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ ├── flue.turn [llm] - │ │ output: [ - │ │ { - │ │ "finish_reason": "toolUse", - │ │ "index": 0, - │ │ "message": { - │ │ "content": "Now proceeding to Step 2 with the lookup ID:", - │ │ "reasoning": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to Step 2 and use this id as the lookupId parameter when calling web_search with the query \"Braintrust Flue reasoning stream instrumentation\".", - │ │ "role": "assistant", - │ │ "tool_calls": [ - │ │ { - │ │ "function": { - │ │ "arguments": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\"}", - │ │ "name": "web_search" - │ │ }, - │ │ "id": "", - │ │ "type": "function" - │ │ } - │ │ ] - │ │ } - │ │ } - │ │ ] - │ │ metadata: { - │ │ "flue.model": "claude-sonnet-4-5-20250929", - │ │ "flue.session": "main", - │ │ "flue.thinking": true, - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "completion_tokens": 169, - │ │ "duration_ms": 0, - │ │ "estimated_cost": 0.0041217, - │ │ "prompt_cache_creation_tokens": 238, - │ │ "prompt_cached_tokens": 2184, - │ │ "prompt_tokens": 13, - │ │ "tokens": 2604 - │ │ } - │ ├── tool: web_search [tool] - │ │ input: { - │ │ "lookupId": "flue-session-2026", - │ │ "query": "Braintrust Flue reasoning stream instrumentation" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "web_search" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "web_search", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ ├── flue.turn [llm] - │ │ output: [ - │ │ { - │ │ "finish_reason": "toolUse", - │ │ "index": 0, - │ │ "message": { - │ │ "content": "Now proceeding to Step 3 with the first result URL:", - │ │ "reasoning": "Perfect! I got the web_search results. There's one result with the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to Step 3 and call summarize_source with this URL.", - │ │ "role": "assistant", - │ │ "tool_calls": [ - │ │ { - │ │ "function": { - │ │ "arguments": "{\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ │ "name": "summarize_source" - │ │ }, - │ │ "id": "", - │ │ "type": "function" - │ │ } - │ │ ] - │ │ } - │ │ } - │ │ ] - │ │ metadata: { - │ │ "flue.model": "claude-sonnet-4-5-20250929", - │ │ "flue.session": "main", - │ │ "flue.thinking": true, - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "completion_tokens": 139, - │ │ "duration_ms": 0, - │ │ "estimated_cost": 0.00376935, - │ │ "prompt_cache_creation_tokens": 245, - │ │ "prompt_cached_tokens": 2422, - │ │ "prompt_tokens": 13, - │ │ "tokens": 2819 - │ │ } - │ ├── tool: summarize_source [tool] - │ │ input: { - │ │ "url": "https://example.test/flue/reasoning-streams" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "customTool": "summarize_source" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "main", - │ │ "flue.tool_name": "summarize_source", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── flue.turn [llm] - │ output: [ - │ { - │ "finish_reason": "stop", - │ "index": 0, - │ "message": { - │ "content": "PROMPT_DONE", - │ "reasoning": "The summarize_source call has returned successfully. According to the instructions, I now need to reply with exactly \"PROMPT_DONE\" and no other text.", - │ "role": "assistant" - │ } - │ } - │ ] - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.session": "main", - │ "flue.thinking": true, - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 50, - │ "duration_ms": 0, - │ "estimated_cost": 0.00232035, - │ "prompt_cache_creation_tokens": 195, - │ "prompt_cached_tokens": 2667, - │ "prompt_tokens": 13, - │ "tokens": 2925 - │ } - ├── flue-skill-operation - │ metadata: { - │ "operation": "skill" - │ } - │ └── flue.session.skill [task] - │ input: { - │ "args": { - │ "marker": "SKILL_DONE" - │ }, - │ "name": "e2e-flue-skill" - │ } - │ output: "SKILL_DONE" - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.operation": "skill", - │ "flue.role": "skillRunner", - │ "flue.session": "skill", - │ "flue.skill_name": "e2e-flue-skill", - │ "flue.thinking_level": "off", - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 97, - │ "duration_ms": 0, - │ "estimated_cost": 0.00561945, - │ "prompt_cache_creation_tokens": 871, - │ "prompt_cached_tokens": 2904, - │ "prompt_tokens": 9, - │ "tokens": 3881 - │ } - │ ├── flue.turn [llm] - │ │ output: [ - │ │ { - │ │ "finish_reason": "toolUse", - │ │ "index": 0, - │ │ "message": { - │ │ "content": "I'll run the e2e-flue-skill by reading its instructions and following them.", - │ │ "role": "assistant", - │ │ "tool_calls": [ - │ │ { - │ │ "function": { - │ │ "arguments": "{\"path\":\".agents/skills/e2e-flue-skill/SKILL.md\"}", - │ │ "name": "read" - │ │ }, - │ │ "id": "", - │ │ "type": "function" - │ │ } - │ │ ] - │ │ } - │ │ } - │ │ ] - │ │ metadata: { - │ │ "flue.model": "claude-sonnet-4-5-20250929", - │ │ "flue.session": "skill", - │ │ "model": "claude-sonnet-4-5-20250929", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "completion_tokens": 89, - │ │ "duration_ms": 0, - │ │ "estimated_cost": 0.0043644, - │ │ "prompt_cache_creation_tokens": 718, - │ │ "prompt_cached_tokens": 1093, - │ │ "prompt_tokens": 3, - │ │ "tokens": 1903 - │ │ } - │ ├── tool: read [tool] - │ │ input: { - │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ │ } - │ │ output: { - │ │ "content": [ - │ │ { - │ │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", - │ │ "type": "text" - │ │ } - │ │ ], - │ │ "details": { - │ │ "lines": 7, - │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" - │ │ } - │ │ } - │ │ metadata: { - │ │ "flue.session": "skill", - │ │ "flue.tool_name": "read", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── flue.turn [llm] - │ output: [ - │ { - │ "finish_reason": "stop", - │ "index": 0, - │ "message": { - │ "content": "SKILL_DONE", - │ "role": "assistant" - │ } - │ } - │ ] - │ metadata: { - │ "flue.model": "claude-sonnet-4-5-20250929", - │ "flue.session": "skill", - │ "model": "claude-sonnet-4-5-20250929", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 8, - │ "duration_ms": 0, - │ "estimated_cost": 0.00125505, - │ "prompt_cache_creation_tokens": 153, - │ "prompt_cached_tokens": 1811, - │ "prompt_tokens": 6, - │ "tokens": 1978 - │ } - ├── flue-task-operation - │ metadata: { - │ "operation": "task" - │ } - │ └── flue.session.task [task] - │ input: "Reply with exactly TASK_DONE and no other text." - │ output: "TASK_DONE" - │ metadata: { - │ "flue.model": "gpt-4o-mini", - │ "flue.operation": "task", - │ "flue.session": "task", - │ "flue.thinking_level": "off", - │ "model": "gpt-4o-mini", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 4, - │ "duration_ms": 0, - │ "estimated_cost": 0.0001182, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 772, - │ "tokens": 776 - │ } - │ ├── flue.task [task] - │ │ input: "Reply with exactly TASK_DONE and no other text." - │ │ output: "TASK_DONE" - │ │ metadata: { - │ │ "flue.session": "task", - │ │ "provider": "flue" - │ │ } - │ │ metrics: { - │ │ "duration_ms": 0 - │ │ } - │ └── flue.turn [llm] - │ output: [ - │ { - │ "finish_reason": "stop", - │ "index": 0, - │ "message": { - │ "content": "TASK_DONE", - │ "role": "assistant" - │ } - │ } - │ ] - │ metadata: { - │ "flue.model": "gpt-4o-mini", - │ "flue.session": "task:task:", - │ "model": "gpt-4o-mini", - │ "provider": "flue" - │ } - │ metrics: { - │ "completion_tokens": 4, - │ "duration_ms": 0, - │ "estimated_cost": 0.0001182, - │ "prompt_cache_creation_tokens": 0, - │ "prompt_cached_tokens": 0, - │ "prompt_tokens": 772, - │ "tokens": 776 - │ } - └── flue-compact-operation - metadata: { - "operation": "compact" - } - └── flue.session.compact [task] - metadata: { - "flue.operation": "compact", - "flue.session": "main", - "provider": "flue" - } - metrics: { - "duration_ms": 0 - } - └── flue.compaction [task] - input: { - "estimatedTokens": 2925, - "reason": "manual" - } - output: { - "messagesAfter": 2, - "messagesBefore": 8 - } - metadata: { - "flue.compaction_reason": "manual", - "flue.session": "main", - "provider": "flue" - } - metrics: { - "completion_tokens": 0, - "duration_ms": 0, - "estimated_cost": 0, - "prompt_cache_creation_tokens": 0, - "prompt_cached_tokens": 0, - "prompt_tokens": 0, - "tokens": 0 - } diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-auto-hook.span-tree.json b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-auto-hook.span-tree.json new file mode 100644 index 000000000..d01ffbe04 --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-auto-hook.span-tree.json @@ -0,0 +1,1610 @@ +{ + "span_tree": [ + { + "name": "workflow:instrumentation", + "type": "task", + "children": [ + { + "name": "flue.prompt", + "type": "task", + "children": [ + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:lookup", + "type": "tool", + "children": [], + "input": { + "query": "flue instrumentation" + }, + "output": { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "details": { + "customTool": "lookup" + } + }, + "metadata": { + "flue.session": "main", + "flue.tool_name": "lookup", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 196, + "duration_ms": 0, + "estimated_cost": 0.0113025, + "prompt_cache_creation_tokens": 2222, + "prompt_cached_tokens": 0, + "prompt_tokens": 10, + "tokens": 2428 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:web_search", + "type": "tool", + "children": [], + "input": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "output": { + "content": [ + { + "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "type": "text" + } + ], + "details": { + "customTool": "web_search" + } + }, + "metadata": { + "flue.session": "main", + "flue.tool_name": "web_search", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "lookup" + } + ], + "output": { + "content": [ + { + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "arguments": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "id": "", + "name": "web_search", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 158, + "duration_ms": 0, + "estimated_cost": 0.0039606, + "prompt_cache_creation_tokens": 236, + "prompt_cached_tokens": 2222, + "prompt_tokens": 13, + "tokens": 2629 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:summarize_source", + "type": "tool", + "children": [], + "input": { + "url": "https://example.test/flue/reasoning-streams" + }, + "output": { + "content": [ + { + "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + "type": "text" + } + ], + "details": { + "customTool": "summarize_source" + } + }, + "metadata": { + "flue.session": "main", + "flue.tool_name": "summarize_source", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "lookup" + }, + { + "content": [ + { + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "arguments": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "id": "", + "name": "web_search", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "web_search" + } + ], + "output": { + "content": [ + { + "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 3:", + "type": "text" + }, + { + "arguments": { + "url": "https://example.test/flue/reasoning-streams" + }, + "id": "", + "name": "summarize_source", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 138, + "duration_ms": 0, + "estimated_cost": 0.0037239000000000005, + "prompt_cache_creation_tokens": 234, + "prompt_cached_tokens": 2458, + "prompt_tokens": 13, + "tokens": 2843 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "lookup" + }, + { + "content": [ + { + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "arguments": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "id": "", + "name": "web_search", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "web_search" + }, + { + "content": [ + { + "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 3:", + "type": "text" + }, + { + "arguments": { + "url": "https://example.test/flue/reasoning-streams" + }, + "id": "", + "name": "summarize_source", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "summarize_source" + } + ], + "output": { + "content": [ + { + "thinking": "Perfect! The summarize_source call has completed successfully. According to the instructions, I should now reply with exactly \"PROMPT_DONE\" and no other text.", + "thinkingSignature": "Eu8CCm4IDhgCKkAn2QOIIlYfvcs6ynsmhCslHDtBsrTA4CfmimK7zyz6+k6dZldV2JBtEBET41It0gFcGEKC0n0mAhaYVuLutpDDMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM1xfLptxSF8rKzou8GgwRLuVmfiBYOT4CZIsiMAYz8TpvchMAWodP+T9uZ+dJ47MVdNv+p86nZXmT5d5EWlCroiAOFHHzJH2o0UjJQSquAX6wu+jIC8/DXwurGIIf2ToldPuJWF5HGj8kHMnwh777XS1NUFl1irM24rvP7kTAv3Dp8YEwb8t3g1EsicY7j+C5DzgwxVsPYCVOCgdMqQjtsqpL7AX5KQ9+hR1gK1DQjshv4Gze3hw/+C+9iptd3RlDIuwO0cm8NY+sVqeWVh3TtQujQlVt1rW/HfWjclrtT0LZSGwc6RypmfMMQi6lncIk/EPgy0XbS1plKW0tLBgB", + "type": "thinking" + }, + { + "text": "PROMPT_DONE", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "stop", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 51, + "duration_ms": 0, + "estimated_cost": 0.0023391, + "prompt_cache_creation_tokens": 194, + "prompt_cached_tokens": 2692, + "prompt_tokens": 13, + "tokens": 2950 + } + } + ], + "output": { + "model": { + "id": "" + }, + "text": "PROMPT_DONE", + "usage": { + "cacheRead": 7372, + "cacheWrite": 2886, + "cost": { + "cacheRead": 0.0022115999999999998, + "cacheWrite": 0.0108225, + "input": 0.000147, + "output": 0.008145000000000001, + "total": 0.0213261 + }, + "input": 49, + "output": 543, + "totalTokens": 10850 + } + }, + "metadata": { + "flue.operation": "prompt", + "flue.session": "main", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "flue.skill", + "type": "task", + "children": [ + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "output": { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "details": {} + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + }, + "error": "{\"content\":[{\"type\":\"text\",\"text\":\"ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'\"}],\"details\":{}}" + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 89, + "duration_ms": 0, + "estimated_cost": 0.0041862, + "prompt_cache_creation_tokens": 670, + "prompt_cached_tokens": 1099, + "prompt_tokens": 3, + "tokens": 1861 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents" + }, + "output": { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "details": { + "entries": 1, + "isDirectory": true, + "path": ".agents" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 52, + "duration_ms": 0, + "estimated_cost": 0.00201795, + "prompt_cache_creation_tokens": 183, + "prompt_cached_tokens": 1769, + "prompt_tokens": 7, + "tokens": 2011 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/skills" + }, + "output": { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "details": { + "entries": 1, + "isDirectory": true, + "path": ".agents/skills" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 54, + "duration_ms": 0, + "estimated_cost": 0.0016611, + "prompt_cache_creation_tokens": 66, + "prompt_cached_tokens": 1952, + "prompt_tokens": 6, + "tokens": 2078 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/skills/e2e-flue-skill" + }, + "output": { + "content": [ + { + "text": "SKILL.md", + "type": "text" + } + ], + "details": { + "entries": 1, + "isDirectory": true, + "path": ".agents/skills/e2e-flue-skill" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 63, + "duration_ms": 0, + "estimated_cost": 0.0018459, + "prompt_cache_creation_tokens": 74, + "prompt_cached_tokens": 2018, + "prompt_tokens": 6, + "tokens": 2161 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "output": { + "content": [ + { + "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + "type": "text" + } + ], + "details": { + "lines": 7, + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "SKILL.md", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 68, + "duration_ms": 0, + "estimated_cost": 0.0019618500000000002, + "prompt_cache_creation_tokens": 79, + "prompt_cached_tokens": 2092, + "prompt_tokens": 6, + "tokens": 2245 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "SKILL.md", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "text": "SKILL_DONE", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "stop", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 8, + "duration_ms": 0, + "estimated_cost": 0.00129555, + "prompt_cache_creation_tokens": 135, + "prompt_cached_tokens": 2171, + "prompt_tokens": 6, + "tokens": 2320 + } + } + ], + "output": { + "model": { + "id": "" + }, + "text": "SKILL_DONE", + "usage": { + "cacheRead": 11101, + "cacheWrite": 1207, + "cost": { + "cacheRead": 0.0033302999999999996, + "cacheWrite": 0.00452625, + "input": 0.00010200000000000001, + "output": 0.0050100000000000006, + "total": 0.012968549999999999 + }, + "input": 34, + "output": 334, + "totalTokens": 12676 + } + }, + "metadata": { + "flue.operation": "skill", + "flue.session": "skill", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "flue.task", + "type": "task", + "children": [ + { + "name": "flue.task", + "type": "task", + "children": [ + { + "name": "llm:gpt-4o-mini", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "Reply with exactly TASK_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "text": "TASK_DONE", + "textSignature": "{\"v\":1,\"id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\"}", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "openai-responses", + "flue.model": "gpt-4o-mini", + "flue.provider": "openai", + "flue.session": "task:task:", + "flue.stop_reason": "stop", + "flue.turn_purpose": "agent", + "model": "gpt-4o-mini", + "provider": "openai" + }, + "metrics": { + "completion_tokens": 4, + "duration_ms": 0, + "estimated_cost": 0.00012299999999999998, + "prompt_cache_creation_tokens": 0, + "prompt_cached_tokens": 0, + "prompt_tokens": 804, + "tokens": 808 + } + } + ], + "input": "Reply with exactly TASK_DONE and no other text.", + "output": "TASK_DONE", + "metadata": { + "flue.session": "task", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "output": { + "model": { + "id": "" + }, + "text": "TASK_DONE", + "usage": { + "cacheRead": 0, + "cacheWrite": 0, + "cost": { + "cacheRead": 0, + "cacheWrite": 0, + "input": 0.00012059999999999999, + "output": 0.0000024, + "total": 0.00012299999999999998 + }, + "input": 804, + "output": 4, + "totalTokens": 808 + } + }, + "metadata": { + "flue.operation": "task", + "flue.session": "task", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "flue.compact", + "type": "task", + "children": [ + { + "name": "compaction:manual", + "type": "task", + "children": [ + { + "name": "llm:gpt-4o-mini", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with Step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to Step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to Step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "text": "## Original Request\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\n\n## Early Progress", + "textSignature": "{\"v\":1,\"id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\"}", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "openai-responses", + "flue.model": "gpt-4o-mini", + "flue.provider": "openai", + "flue.session": "main", + "flue.stop_reason": "stop", + "flue.turn_purpose": "compaction_prefix", + "model": "gpt-4o-mini", + "provider": "openai" + }, + "metrics": { + "completion_tokens": 0, + "duration_ms": 0, + "estimated_cost": 0, + "prompt_cache_creation_tokens": 0, + "prompt_cached_tokens": 0, + "prompt_tokens": 0, + "tokens": 0 + } + } + ], + "input": { + "estimatedTokens": 2950, + "reason": "manual" + }, + "output": { + "messagesAfter": 2, + "messagesBefore": 8 + }, + "metadata": { + "flue.compaction_reason": "manual", + "flue.session": "main", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0, + "messages_after": 2, + "messages_before": 8 + } + } + ], + "metadata": { + "flue.operation": "compact", + "flue.session": "main", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": { + "scenario": "flue-instrumentation" + }, + "output": { + "scenario": "flue-instrumentation", + "status": "done" + }, + "metadata": { + "flue.workflow_name": "instrumentation", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ] +} diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-auto-hook.span-tree.txt b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-auto-hook.span-tree.txt new file mode 100644 index 000000000..2871f2809 --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-auto-hook.span-tree.txt @@ -0,0 +1,1484 @@ +span_tree: +└── workflow:instrumentation [task] + input: { + "scenario": "flue-instrumentation" + } + output: { + "scenario": "flue-instrumentation", + "status": "done" + } + metadata: { + "flue.workflow_name": "instrumentation", + "provider": "flue" + } + metrics: { + "duration_ms": 0 + } + ├── flue.prompt [task] + │ output: { + │ "model": { + │ "id": "" + │ }, + │ "text": "PROMPT_DONE", + │ "usage": { + │ "cacheRead": 7372, + │ "cacheWrite": 2886, + │ "cost": { + │ "cacheRead": 0.0022115999999999998, + │ "cacheWrite": 0.0108225, + │ "input": 0.000147, + │ "output": 0.008145000000000001, + │ "total": 0.0213261 + │ }, + │ "input": 49, + │ "output": 543, + │ "totalTokens": 10850 + │ } + │ } + │ metadata: { + │ "flue.operation": "prompt", + │ "flue.session": "main", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "query": "flue instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "lookup", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "main", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 196, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0113025, + │ │ "prompt_cache_creation_tokens": 2222, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 10, + │ │ "tokens": 2428 + │ │ } + │ │ └── tool:lookup [tool] + │ │ input: { + │ │ "query": "flue instrumentation" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "customTool": "lookup" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "main", + │ │ "flue.tool_name": "lookup", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "query": "flue instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "lookup", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "lookup" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + │ │ "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "Now proceeding to Step 2:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "lookupId": "flue-session-2026", + │ │ "query": "Braintrust Flue reasoning stream instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "web_search", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "main", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 158, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0039606, + │ │ "prompt_cache_creation_tokens": 236, + │ │ "prompt_cached_tokens": 2222, + │ │ "prompt_tokens": 13, + │ │ "tokens": 2629 + │ │ } + │ │ └── tool:web_search [tool] + │ │ input: { + │ │ "lookupId": "flue-session-2026", + │ │ "query": "Braintrust Flue reasoning stream instrumentation" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "customTool": "web_search" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "main", + │ │ "flue.tool_name": "web_search", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "query": "flue instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "lookup", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "lookup" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + │ │ "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "Now proceeding to Step 2:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "lookupId": "flue-session-2026", + │ │ "query": "Braintrust Flue reasoning stream instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "web_search", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "web_search" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + │ │ "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "Now proceeding to Step 3:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "url": "https://example.test/flue/reasoning-streams" + │ │ }, + │ │ "id": "", + │ │ "name": "summarize_source", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "main", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 138, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0037239000000000005, + │ │ "prompt_cache_creation_tokens": 234, + │ │ "prompt_cached_tokens": 2458, + │ │ "prompt_tokens": 13, + │ │ "tokens": 2843 + │ │ } + │ │ └── tool:summarize_source [tool] + │ │ input: { + │ │ "url": "https://example.test/flue/reasoning-streams" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "customTool": "summarize_source" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "main", + │ │ "flue.tool_name": "summarize_source", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ └── llm:claude-sonnet-4-5-20250929 [llm] + │ input: [ + │ { + │ "content": [ + │ { + │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ "type": "thinking" + │ }, + │ { + │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "query": "flue instrumentation" + │ }, + │ "id": "", + │ "name": "lookup", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "lookup" + │ }, + │ { + │ "content": [ + │ { + │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + │ "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + │ "type": "thinking" + │ }, + │ { + │ "text": "Now proceeding to Step 2:", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "lookupId": "flue-session-2026", + │ "query": "Braintrust Flue reasoning stream instrumentation" + │ }, + │ "id": "", + │ "name": "web_search", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "web_search" + │ }, + │ { + │ "content": [ + │ { + │ "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + │ "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + │ "type": "thinking" + │ }, + │ { + │ "text": "Now proceeding to Step 3:", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "url": "https://example.test/flue/reasoning-streams" + │ }, + │ "id": "", + │ "name": "summarize_source", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "summarize_source" + │ } + │ ] + │ output: { + │ "content": [ + │ { + │ "thinking": "Perfect! The summarize_source call has completed successfully. According to the instructions, I should now reply with exactly \"PROMPT_DONE\" and no other text.", + │ "thinkingSignature": "Eu8CCm4IDhgCKkAn2QOIIlYfvcs6ynsmhCslHDtBsrTA4CfmimK7zyz6+k6dZldV2JBtEBET41It0gFcGEKC0n0mAhaYVuLutpDDMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM1xfLptxSF8rKzou8GgwRLuVmfiBYOT4CZIsiMAYz8TpvchMAWodP+T9uZ+dJ47MVdNv+p86nZXmT5d5EWlCroiAOFHHzJH2o0UjJQSquAX6wu+jIC8/DXwurGIIf2ToldPuJWF5HGj8kHMnwh777XS1NUFl1irM24rvP7kTAv3Dp8YEwb8t3g1EsicY7j+C5DzgwxVsPYCVOCgdMqQjtsqpL7AX5KQ9+hR1gK1DQjshv4Gze3hw/+C+9iptd3RlDIuwO0cm8NY+sVqeWVh3TtQujQlVt1rW/HfWjclrtT0LZSGwc6RypmfMMQi6lncIk/EPgy0XbS1plKW0tLBgB", + │ "type": "thinking" + │ }, + │ { + │ "text": "PROMPT_DONE", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ metadata: { + │ "flue.api": "anthropic-messages", + │ "flue.model": "claude-sonnet-4-5-20250929", + │ "flue.provider": "anthropic", + │ "flue.session": "main", + │ "flue.stop_reason": "stop", + │ "flue.turn_purpose": "agent", + │ "model": "claude-sonnet-4-5-20250929", + │ "provider": "anthropic" + │ } + │ metrics: { + │ "completion_tokens": 51, + │ "duration_ms": 0, + │ "estimated_cost": 0.0023391, + │ "prompt_cache_creation_tokens": 194, + │ "prompt_cached_tokens": 2692, + │ "prompt_tokens": 13, + │ "tokens": 2950 + │ } + ├── flue.skill [task] + │ output: { + │ "model": { + │ "id": "" + │ }, + │ "text": "SKILL_DONE", + │ "usage": { + │ "cacheRead": 11101, + │ "cacheWrite": 1207, + │ "cost": { + │ "cacheRead": 0.0033302999999999996, + │ "cacheWrite": 0.00452625, + │ "input": 0.00010200000000000001, + │ "output": 0.0050100000000000006, + │ "total": 0.012968549999999999 + │ }, + │ "input": 34, + │ "output": 334, + │ "totalTokens": 12676 + │ } + │ } + │ metadata: { + │ "flue.operation": "skill", + │ "flue.session": "skill", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 89, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0041862, + │ │ "prompt_cache_creation_tokens": 670, + │ │ "prompt_cached_tokens": 1099, + │ │ "prompt_tokens": 3, + │ │ "tokens": 1861 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": {} + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ │ error: "{\"content\":[{\"type\":\"text\",\"text\":\"ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'\"}],\"details\":{}}" + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 52, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.00201795, + │ │ "prompt_cache_creation_tokens": 183, + │ │ "prompt_cached_tokens": 1769, + │ │ "prompt_tokens": 7, + │ │ "tokens": 2011 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "entries": 1, + │ │ "isDirectory": true, + │ │ "path": ".agents" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 54, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0016611, + │ │ "prompt_cache_creation_tokens": 66, + │ │ "prompt_cached_tokens": 1952, + │ │ "prompt_tokens": 6, + │ │ "tokens": 2078 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/skills" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "e2e-flue-skill", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "entries": 1, + │ │ "isDirectory": true, + │ │ "path": ".agents/skills" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "e2e-flue-skill", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 63, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0018459, + │ │ "prompt_cache_creation_tokens": 74, + │ │ "prompt_cached_tokens": 2018, + │ │ "prompt_tokens": 6, + │ │ "tokens": 2161 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "SKILL.md", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "entries": 1, + │ │ "isDirectory": true, + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "e2e-flue-skill", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "SKILL.md", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 68, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0019618500000000002, + │ │ "prompt_cache_creation_tokens": 79, + │ │ "prompt_cached_tokens": 2092, + │ │ "prompt_tokens": 6, + │ │ "tokens": 2245 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "lines": 7, + │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ └── llm:claude-sonnet-4-5-20250929 [llm] + │ input: [ + │ { + │ "content": [ + │ { + │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "path": ".agents/e2e-flue-skill.md" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ "type": "text" + │ } + │ ], + │ "isError": true, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "skills", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents/skills" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "e2e-flue-skill", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents/skills/e2e-flue-skill" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "SKILL.md", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ } + │ ] + │ output: { + │ "content": [ + │ { + │ "text": "SKILL_DONE", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ metadata: { + │ "flue.api": "anthropic-messages", + │ "flue.model": "claude-sonnet-4-5-20250929", + │ "flue.provider": "anthropic", + │ "flue.session": "skill", + │ "flue.stop_reason": "stop", + │ "flue.turn_purpose": "agent", + │ "model": "claude-sonnet-4-5-20250929", + │ "provider": "anthropic" + │ } + │ metrics: { + │ "completion_tokens": 8, + │ "duration_ms": 0, + │ "estimated_cost": 0.00129555, + │ "prompt_cache_creation_tokens": 135, + │ "prompt_cached_tokens": 2171, + │ "prompt_tokens": 6, + │ "tokens": 2320 + │ } + ├── flue.task [task] + │ output: { + │ "model": { + │ "id": "" + │ }, + │ "text": "TASK_DONE", + │ "usage": { + │ "cacheRead": 0, + │ "cacheWrite": 0, + │ "cost": { + │ "cacheRead": 0, + │ "cacheWrite": 0, + │ "input": 0.00012059999999999999, + │ "output": 0.0000024, + │ "total": 0.00012299999999999998 + │ }, + │ "input": 804, + │ "output": 4, + │ "totalTokens": 808 + │ } + │ } + │ metadata: { + │ "flue.operation": "task", + │ "flue.session": "task", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ └── flue.task [task] + │ input: "Reply with exactly TASK_DONE and no other text." + │ output: "TASK_DONE" + │ metadata: { + │ "flue.session": "task", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ └── llm:gpt-4o-mini [llm] + │ input: [ + │ { + │ "content": [ + │ { + │ "text": "Reply with exactly TASK_DONE and no other text.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ] + │ output: { + │ "content": [ + │ { + │ "text": "TASK_DONE", + │ "textSignature": "{\"v\":1,\"id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\"}", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ metadata: { + │ "flue.api": "openai-responses", + │ "flue.model": "gpt-4o-mini", + │ "flue.provider": "openai", + │ "flue.session": "task:task:", + │ "flue.stop_reason": "stop", + │ "flue.turn_purpose": "agent", + │ "model": "gpt-4o-mini", + │ "provider": "openai" + │ } + │ metrics: { + │ "completion_tokens": 4, + │ "duration_ms": 0, + │ "estimated_cost": 0.00012299999999999998, + │ "prompt_cache_creation_tokens": 0, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 804, + │ "tokens": 808 + │ } + └── flue.compact [task] + metadata: { + "flue.operation": "compact", + "flue.session": "main", + "provider": "flue" + } + metrics: { + "duration_ms": 0 + } + └── compaction:manual [task] + input: { + "estimatedTokens": 2950, + "reason": "manual" + } + output: { + "messagesAfter": 2, + "messagesBefore": 8 + } + metadata: { + "flue.compaction_reason": "manual", + "flue.session": "main", + "provider": "flue" + } + metrics: { + "duration_ms": 0, + "messages_after": 2, + "messages_before": 8 + } + └── llm:gpt-4o-mini [llm] + input: [ + { + "content": [ + { + "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with Step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to Step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to Step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", + "type": "text" + } + ], + "role": "user" + } + ] + output: { + "content": [ + { + "text": "## Original Request\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\n\n## Early Progress", + "textSignature": "{\"v\":1,\"id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\"}", + "type": "text" + } + ], + "role": "assistant" + } + metadata: { + "flue.api": "openai-responses", + "flue.model": "gpt-4o-mini", + "flue.provider": "openai", + "flue.session": "main", + "flue.stop_reason": "stop", + "flue.turn_purpose": "compaction_prefix", + "model": "gpt-4o-mini", + "provider": "openai" + } + metrics: { + "completion_tokens": 0, + "duration_ms": 0, + "estimated_cost": 0, + "prompt_cache_creation_tokens": 0, + "prompt_cached_tokens": 0, + "prompt_tokens": 0, + "tokens": 0 + } diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-explicit.span-tree.json b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-explicit.span-tree.json new file mode 100644 index 000000000..d01ffbe04 --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-explicit.span-tree.json @@ -0,0 +1,1610 @@ +{ + "span_tree": [ + { + "name": "workflow:instrumentation", + "type": "task", + "children": [ + { + "name": "flue.prompt", + "type": "task", + "children": [ + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:lookup", + "type": "tool", + "children": [], + "input": { + "query": "flue instrumentation" + }, + "output": { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "details": { + "customTool": "lookup" + } + }, + "metadata": { + "flue.session": "main", + "flue.tool_name": "lookup", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 196, + "duration_ms": 0, + "estimated_cost": 0.0113025, + "prompt_cache_creation_tokens": 2222, + "prompt_cached_tokens": 0, + "prompt_tokens": 10, + "tokens": 2428 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:web_search", + "type": "tool", + "children": [], + "input": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "output": { + "content": [ + { + "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "type": "text" + } + ], + "details": { + "customTool": "web_search" + } + }, + "metadata": { + "flue.session": "main", + "flue.tool_name": "web_search", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "lookup" + } + ], + "output": { + "content": [ + { + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "arguments": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "id": "", + "name": "web_search", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 158, + "duration_ms": 0, + "estimated_cost": 0.0039606, + "prompt_cache_creation_tokens": 236, + "prompt_cached_tokens": 2222, + "prompt_tokens": 13, + "tokens": 2629 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:summarize_source", + "type": "tool", + "children": [], + "input": { + "url": "https://example.test/flue/reasoning-streams" + }, + "output": { + "content": [ + { + "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + "type": "text" + } + ], + "details": { + "customTool": "summarize_source" + } + }, + "metadata": { + "flue.session": "main", + "flue.tool_name": "summarize_source", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "lookup" + }, + { + "content": [ + { + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "arguments": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "id": "", + "name": "web_search", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "web_search" + } + ], + "output": { + "content": [ + { + "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 3:", + "type": "text" + }, + { + "arguments": { + "url": "https://example.test/flue/reasoning-streams" + }, + "id": "", + "name": "summarize_source", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 138, + "duration_ms": 0, + "estimated_cost": 0.0037239000000000005, + "prompt_cache_creation_tokens": 234, + "prompt_cached_tokens": 2458, + "prompt_tokens": 13, + "tokens": 2843 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + "type": "thinking" + }, + { + "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + "type": "text" + }, + { + "arguments": { + "query": "flue instrumentation" + }, + "id": "", + "name": "lookup", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "lookup" + }, + { + "content": [ + { + "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 2:", + "type": "text" + }, + { + "arguments": { + "lookupId": "flue-session-2026", + "query": "Braintrust Flue reasoning stream instrumentation" + }, + "id": "", + "name": "web_search", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "web_search" + }, + { + "content": [ + { + "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + "type": "thinking" + }, + { + "text": "Now proceeding to Step 3:", + "type": "text" + }, + { + "arguments": { + "url": "https://example.test/flue/reasoning-streams" + }, + "id": "", + "name": "summarize_source", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "summarize_source" + } + ], + "output": { + "content": [ + { + "thinking": "Perfect! The summarize_source call has completed successfully. According to the instructions, I should now reply with exactly \"PROMPT_DONE\" and no other text.", + "thinkingSignature": "Eu8CCm4IDhgCKkAn2QOIIlYfvcs6ynsmhCslHDtBsrTA4CfmimK7zyz6+k6dZldV2JBtEBET41It0gFcGEKC0n0mAhaYVuLutpDDMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM1xfLptxSF8rKzou8GgwRLuVmfiBYOT4CZIsiMAYz8TpvchMAWodP+T9uZ+dJ47MVdNv+p86nZXmT5d5EWlCroiAOFHHzJH2o0UjJQSquAX6wu+jIC8/DXwurGIIf2ToldPuJWF5HGj8kHMnwh777XS1NUFl1irM24rvP7kTAv3Dp8YEwb8t3g1EsicY7j+C5DzgwxVsPYCVOCgdMqQjtsqpL7AX5KQ9+hR1gK1DQjshv4Gze3hw/+C+9iptd3RlDIuwO0cm8NY+sVqeWVh3TtQujQlVt1rW/HfWjclrtT0LZSGwc6RypmfMMQi6lncIk/EPgy0XbS1plKW0tLBgB", + "type": "thinking" + }, + { + "text": "PROMPT_DONE", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "main", + "flue.stop_reason": "stop", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 51, + "duration_ms": 0, + "estimated_cost": 0.0023391, + "prompt_cache_creation_tokens": 194, + "prompt_cached_tokens": 2692, + "prompt_tokens": 13, + "tokens": 2950 + } + } + ], + "output": { + "model": { + "id": "" + }, + "text": "PROMPT_DONE", + "usage": { + "cacheRead": 7372, + "cacheWrite": 2886, + "cost": { + "cacheRead": 0.0022115999999999998, + "cacheWrite": 0.0108225, + "input": 0.000147, + "output": 0.008145000000000001, + "total": 0.0213261 + }, + "input": 49, + "output": 543, + "totalTokens": 10850 + } + }, + "metadata": { + "flue.operation": "prompt", + "flue.session": "main", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "flue.skill", + "type": "task", + "children": [ + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/e2e-flue-skill.md" + }, + "output": { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "details": {} + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + }, + "error": "{\"content\":[{\"type\":\"text\",\"text\":\"ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'\"}],\"details\":{}}" + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 89, + "duration_ms": 0, + "estimated_cost": 0.0041862, + "prompt_cache_creation_tokens": 670, + "prompt_cached_tokens": 1099, + "prompt_tokens": 3, + "tokens": 1861 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents" + }, + "output": { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "details": { + "entries": 1, + "isDirectory": true, + "path": ".agents" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 52, + "duration_ms": 0, + "estimated_cost": 0.00201795, + "prompt_cache_creation_tokens": 183, + "prompt_cached_tokens": 1769, + "prompt_tokens": 7, + "tokens": 2011 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/skills" + }, + "output": { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "details": { + "entries": 1, + "isDirectory": true, + "path": ".agents/skills" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 54, + "duration_ms": 0, + "estimated_cost": 0.0016611, + "prompt_cache_creation_tokens": 66, + "prompt_cached_tokens": 1952, + "prompt_tokens": 6, + "tokens": 2078 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/skills/e2e-flue-skill" + }, + "output": { + "content": [ + { + "text": "SKILL.md", + "type": "text" + } + ], + "details": { + "entries": 1, + "isDirectory": true, + "path": ".agents/skills/e2e-flue-skill" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 63, + "duration_ms": 0, + "estimated_cost": 0.0018459, + "prompt_cache_creation_tokens": 74, + "prompt_cached_tokens": 2018, + "prompt_tokens": 6, + "tokens": 2161 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [ + { + "name": "tool:read", + "type": "tool", + "children": [], + "input": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "output": { + "content": [ + { + "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + "type": "text" + } + ], + "details": { + "lines": 7, + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + } + }, + "metadata": { + "flue.session": "skill", + "flue.tool_name": "read", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "SKILL.md", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "toolUse", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 68, + "duration_ms": 0, + "estimated_cost": 0.0019618500000000002, + "prompt_cache_creation_tokens": 79, + "prompt_cached_tokens": 2092, + "prompt_tokens": 6, + "tokens": 2245 + } + }, + { + "name": "llm:claude-sonnet-4-5-20250929", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + "type": "text" + } + ], + "role": "user" + }, + { + "content": [ + { + "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + "type": "text" + }, + { + "arguments": { + "path": ".agents/e2e-flue-skill.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + "type": "text" + } + ], + "isError": true, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "skills", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "e2e-flue-skill", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "SKILL.md", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + }, + { + "content": [ + { + "arguments": { + "path": ".agents/skills/e2e-flue-skill/SKILL.md" + }, + "id": "", + "name": "read", + "type": "toolCall" + } + ], + "role": "assistant" + }, + { + "content": [ + { + "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + "type": "text" + } + ], + "isError": false, + "role": "toolResult", + "toolCallId": "", + "toolName": "read" + } + ], + "output": { + "content": [ + { + "text": "SKILL_DONE", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "anthropic-messages", + "flue.model": "claude-sonnet-4-5-20250929", + "flue.provider": "anthropic", + "flue.session": "skill", + "flue.stop_reason": "stop", + "flue.turn_purpose": "agent", + "model": "claude-sonnet-4-5-20250929", + "provider": "anthropic" + }, + "metrics": { + "completion_tokens": 8, + "duration_ms": 0, + "estimated_cost": 0.00129555, + "prompt_cache_creation_tokens": 135, + "prompt_cached_tokens": 2171, + "prompt_tokens": 6, + "tokens": 2320 + } + } + ], + "output": { + "model": { + "id": "" + }, + "text": "SKILL_DONE", + "usage": { + "cacheRead": 11101, + "cacheWrite": 1207, + "cost": { + "cacheRead": 0.0033302999999999996, + "cacheWrite": 0.00452625, + "input": 0.00010200000000000001, + "output": 0.0050100000000000006, + "total": 0.012968549999999999 + }, + "input": 34, + "output": 334, + "totalTokens": 12676 + } + }, + "metadata": { + "flue.operation": "skill", + "flue.session": "skill", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "flue.task", + "type": "task", + "children": [ + { + "name": "flue.task", + "type": "task", + "children": [ + { + "name": "llm:gpt-4o-mini", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "Reply with exactly TASK_DONE and no other text.", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "text": "TASK_DONE", + "textSignature": "{\"v\":1,\"id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\"}", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "openai-responses", + "flue.model": "gpt-4o-mini", + "flue.provider": "openai", + "flue.session": "task:task:", + "flue.stop_reason": "stop", + "flue.turn_purpose": "agent", + "model": "gpt-4o-mini", + "provider": "openai" + }, + "metrics": { + "completion_tokens": 4, + "duration_ms": 0, + "estimated_cost": 0.00012299999999999998, + "prompt_cache_creation_tokens": 0, + "prompt_cached_tokens": 0, + "prompt_tokens": 804, + "tokens": 808 + } + } + ], + "input": "Reply with exactly TASK_DONE and no other text.", + "output": "TASK_DONE", + "metadata": { + "flue.session": "task", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "output": { + "model": { + "id": "" + }, + "text": "TASK_DONE", + "usage": { + "cacheRead": 0, + "cacheWrite": 0, + "cost": { + "cacheRead": 0, + "cacheWrite": 0, + "input": 0.00012059999999999999, + "output": 0.0000024, + "total": 0.00012299999999999998 + }, + "input": 804, + "output": 4, + "totalTokens": 808 + } + }, + "metadata": { + "flue.operation": "task", + "flue.session": "task", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + }, + { + "name": "flue.compact", + "type": "task", + "children": [ + { + "name": "compaction:manual", + "type": "task", + "children": [ + { + "name": "llm:gpt-4o-mini", + "type": "llm", + "children": [], + "input": [ + { + "content": [ + { + "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with Step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to Step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to Step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": [ + { + "text": "## Original Request\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\n\n## Early Progress", + "textSignature": "{\"v\":1,\"id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\"}", + "type": "text" + } + ], + "role": "assistant" + }, + "metadata": { + "flue.api": "openai-responses", + "flue.model": "gpt-4o-mini", + "flue.provider": "openai", + "flue.session": "main", + "flue.stop_reason": "stop", + "flue.turn_purpose": "compaction_prefix", + "model": "gpt-4o-mini", + "provider": "openai" + }, + "metrics": { + "completion_tokens": 0, + "duration_ms": 0, + "estimated_cost": 0, + "prompt_cache_creation_tokens": 0, + "prompt_cached_tokens": 0, + "prompt_tokens": 0, + "tokens": 0 + } + } + ], + "input": { + "estimatedTokens": 2950, + "reason": "manual" + }, + "output": { + "messagesAfter": 2, + "messagesBefore": 8 + }, + "metadata": { + "flue.compaction_reason": "manual", + "flue.session": "main", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0, + "messages_after": 2, + "messages_before": 8 + } + } + ], + "metadata": { + "flue.operation": "compact", + "flue.session": "main", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ], + "input": { + "scenario": "flue-instrumentation" + }, + "output": { + "scenario": "flue-instrumentation", + "status": "done" + }, + "metadata": { + "flue.workflow_name": "instrumentation", + "provider": "flue" + }, + "metrics": { + "duration_ms": 0 + } + } + ] +} diff --git a/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-explicit.span-tree.txt b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-explicit.span-tree.txt new file mode 100644 index 000000000..2871f2809 --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/__snapshots__/flue-v0-8-0-explicit.span-tree.txt @@ -0,0 +1,1484 @@ +span_tree: +└── workflow:instrumentation [task] + input: { + "scenario": "flue-instrumentation" + } + output: { + "scenario": "flue-instrumentation", + "status": "done" + } + metadata: { + "flue.workflow_name": "instrumentation", + "provider": "flue" + } + metrics: { + "duration_ms": 0 + } + ├── flue.prompt [task] + │ output: { + │ "model": { + │ "id": "" + │ }, + │ "text": "PROMPT_DONE", + │ "usage": { + │ "cacheRead": 7372, + │ "cacheWrite": 2886, + │ "cost": { + │ "cacheRead": 0.0022115999999999998, + │ "cacheWrite": 0.0108225, + │ "input": 0.000147, + │ "output": 0.008145000000000001, + │ "total": 0.0213261 + │ }, + │ "input": 49, + │ "output": 543, + │ "totalTokens": 10850 + │ } + │ } + │ metadata: { + │ "flue.operation": "prompt", + │ "flue.session": "main", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "query": "flue instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "lookup", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "main", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 196, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0113025, + │ │ "prompt_cache_creation_tokens": 2222, + │ │ "prompt_cached_tokens": 0, + │ │ "prompt_tokens": 10, + │ │ "tokens": 2428 + │ │ } + │ │ └── tool:lookup [tool] + │ │ input: { + │ │ "query": "flue instrumentation" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "customTool": "lookup" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "main", + │ │ "flue.tool_name": "lookup", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "query": "flue instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "lookup", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "lookup" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + │ │ "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "Now proceeding to Step 2:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "lookupId": "flue-session-2026", + │ │ "query": "Braintrust Flue reasoning stream instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "web_search", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "main", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 158, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0039606, + │ │ "prompt_cache_creation_tokens": 236, + │ │ "prompt_cached_tokens": 2222, + │ │ "prompt_tokens": 13, + │ │ "tokens": 2629 + │ │ } + │ │ └── tool:web_search [tool] + │ │ input: { + │ │ "lookupId": "flue-session-2026", + │ │ "query": "Braintrust Flue reasoning stream instrumentation" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "customTool": "web_search" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "main", + │ │ "flue.tool_name": "web_search", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "query": "flue instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "lookup", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "lookup" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + │ │ "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "Now proceeding to Step 2:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "lookupId": "flue-session-2026", + │ │ "query": "Braintrust Flue reasoning stream instrumentation" + │ │ }, + │ │ "id": "", + │ │ "name": "web_search", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "web_search" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + │ │ "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + │ │ "type": "thinking" + │ │ }, + │ │ { + │ │ "text": "Now proceeding to Step 3:", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "url": "https://example.test/flue/reasoning-streams" + │ │ }, + │ │ "id": "", + │ │ "name": "summarize_source", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "main", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 138, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0037239000000000005, + │ │ "prompt_cache_creation_tokens": 234, + │ │ "prompt_cached_tokens": 2458, + │ │ "prompt_tokens": 13, + │ │ "tokens": 2843 + │ │ } + │ │ └── tool:summarize_source [tool] + │ │ input: { + │ │ "url": "https://example.test/flue/reasoning-streams" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "customTool": "summarize_source" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "main", + │ │ "flue.tool_name": "summarize_source", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ └── llm:claude-sonnet-4-5-20250929 [llm] + │ input: [ + │ { + │ "content": [ + │ { + │ "text": "Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "thinking": "The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.", + │ "thinkingSignature": "EoQFCm4IDhgCKkD+AoKMhpXNPUJ5eANwM28uUCJPCE+AXh0ACw7aXniX+YN04zdJl3hlHMbtAuKhhczLiEeOJtu4KtVpea5u5NFdMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMIOTWCNEtsiI9vF4SGgwPXC861uZx8lpOziEiMLsCukGIluD0U44degzYnHFc+BwXNIEB+yatSHlZE+a5smr9crZcft3OLmsIdXuaFSrDAyQxWd9oqfJdnvza9eWIaOCeNkVCjrTc/wotBwh5Xp8m9k/WKt7P4zzUJBuLQ1f6ZnsdWkL8OiL/2E7Up55z2+UuVWsg1Y90/x27YRFdQjv3RnztYp4bZ5oIHAlTJoCzWiBYEh/Z8c2O+wy6MHo1cp0T57OroB/4HAqRZxrjTOXpKYLmYKXAY5tU8DTd3A0/FfEhg3oPSbOhX+112szFCpm3BRNJYooUUhwSu1hO4H/6r7d/Yp9XIM4tBfzuDx83CC/YetdOFgnYkdliw0xaUGaj4o37rWIRctWHAMdlUc4NDA0Ljc1uirHDXkN8EJwWSoIjPSBTA/p/wgLrvRV5Yy9Z0dMoWOpgYF6t1H/tNAyY8ml1CA7IWyd3jnfTZ1/G3Y0xFDwJDFlb4/QKc67w36SSCa+X9mMoTxD/DYN249lsII+XX3lQ7F1zJ07THOtCyRirCaRhmE/kGwl5tiB1QHrWa9bNHxQxf9i92435JGKN053Fe14AR70MtBSzIU2/zbgvhB1vF5lZt2i46hNxfo4lXR495gEwdwC6+8HJnlEJAJkdeHfZKj+RiwXoiYKPKsSbHi83X8Hh32IifuglNxdlxVQYAQ==", + │ "type": "thinking" + │ }, + │ { + │ "text": "I'll complete this instrumented research flow step by step. Starting with Step 1:", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "query": "flue instrumentation" + │ }, + │ "id": "", + │ "name": "lookup", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "{\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "lookup" + │ }, + │ { + │ "content": [ + │ { + │ "thinking": "Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".", + │ "thinkingSignature": "EpEDCm4IDhgCKkAMahve1kB1j4njp1ZSzO8eCK4bb5Ex7MB6tjdoOXfuUDRfkBqvIGdwVly8GiA8GGYC7Y/RVfREXF6A6OXHTwFyMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMLw+fsa4yo7a7ZSoIGgyaTdvH020n2dQj9bUiMB4OokY29w+uZb4rqDnKDbLXUqUj6U0f1QCGQF2ZBYDDfDJyM5Jv1xY3rQiUUjkhBirQAS4XivjvMnWI5zHBmpI/u/pq4aGdrdb3vUsJ/ne6R1d80JA/INGF8vLkQcZ5xxEK0jU4yRE+ldc2uzavmtoxIKAFD6bqKks1Qv6u+TIZtuW7tUB/7jFxDw93KmJNruMIa8c1J6pPUyBy3xE7QwgmU0kDfIfdnljxLoEBiMwtnxjCPj9lT7HHz4FkrhbnQTV4MvAQohCLjaSbOTd6LdLxwtJPm9mc26ID4eYN1gCCzyAxGXhqLHlzc23PafvQjsZliWnLhaiNMnG0YEo78XkuJQsYAQ==", + │ "type": "thinking" + │ }, + │ { + │ "text": "Now proceeding to Step 2:", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "lookupId": "flue-session-2026", + │ "query": "Braintrust Flue reasoning stream instrumentation" + │ }, + │ "id": "", + │ "name": "web_search", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "{\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "web_search" + │ }, + │ { + │ "content": [ + │ { + │ "thinking": "Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.", + │ "thinkingSignature": "EqQDCm4IDhgCKkAXv7EDAhWMcrBz11bUd5qxlzyy03CAGQfRgLHDE0uKzLATh1o2sedd8GxLwwQqV0CmLRfNxsdK/ZDp3Lks9iysMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIMXDMniOy5Dy0KI8x7GgzgHs7BYJMs6/N0ur8iMPe0SwnHhP39OjEu7P8ASwK9ffwa3VP67QOlPzOstRRdEZNd0mq+BVjpmBXB+QcAzCrjAeAh/UO/d7SfFmXjqwA3//thoL/TTlGa6W+fdOCFRikn65JWT4ZdVFetfqD+9/QCP/nXEwMsLnTBAxC4EGryrgs2YT+OWwmEJ7rHKFeDs5djhwSb2J2ZJO1kRvD9s2vCCDkImygYBSIVgx1Y0CZJHhzn2Vf39v0Fbth2wDZa+OqxivV9NmDZEjmgcM+tTRx1CCnaww8LZEJQ68v/dUJy7hhD4MrNcQ62evJYPfT3+4EKKWJ/7HI7KXz91//+YAkph63XstbJMFJ3AldAFiq3ecauXt5r42N5gmCmwZX+sI48ENLGGAE=", + │ "type": "thinking" + │ }, + │ { + │ "text": "Now proceeding to Step 3:", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "url": "https://example.test/flue/reasoning-streams" + │ }, + │ "id": "", + │ "name": "summarize_source", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "{\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "summarize_source" + │ } + │ ] + │ output: { + │ "content": [ + │ { + │ "thinking": "Perfect! The summarize_source call has completed successfully. According to the instructions, I should now reply with exactly \"PROMPT_DONE\" and no other text.", + │ "thinkingSignature": "Eu8CCm4IDhgCKkAn2QOIIlYfvcs6ynsmhCslHDtBsrTA4CfmimK7zyz6+k6dZldV2JBtEBET41It0gFcGEKC0n0mAhaYVuLutpDDMhpjbGF1ZGUtc29ubmV0LTQtNS0yMDI1MDkyOTgAQgh0aGlua2luZxIM1xfLptxSF8rKzou8GgwRLuVmfiBYOT4CZIsiMAYz8TpvchMAWodP+T9uZ+dJ47MVdNv+p86nZXmT5d5EWlCroiAOFHHzJH2o0UjJQSquAX6wu+jIC8/DXwurGIIf2ToldPuJWF5HGj8kHMnwh777XS1NUFl1irM24rvP7kTAv3Dp8YEwb8t3g1EsicY7j+C5DzgwxVsPYCVOCgdMqQjtsqpL7AX5KQ9+hR1gK1DQjshv4Gze3hw/+C+9iptd3RlDIuwO0cm8NY+sVqeWVh3TtQujQlVt1rW/HfWjclrtT0LZSGwc6RypmfMMQi6lncIk/EPgy0XbS1plKW0tLBgB", + │ "type": "thinking" + │ }, + │ { + │ "text": "PROMPT_DONE", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ metadata: { + │ "flue.api": "anthropic-messages", + │ "flue.model": "claude-sonnet-4-5-20250929", + │ "flue.provider": "anthropic", + │ "flue.session": "main", + │ "flue.stop_reason": "stop", + │ "flue.turn_purpose": "agent", + │ "model": "claude-sonnet-4-5-20250929", + │ "provider": "anthropic" + │ } + │ metrics: { + │ "completion_tokens": 51, + │ "duration_ms": 0, + │ "estimated_cost": 0.0023391, + │ "prompt_cache_creation_tokens": 194, + │ "prompt_cached_tokens": 2692, + │ "prompt_tokens": 13, + │ "tokens": 2950 + │ } + ├── flue.skill [task] + │ output: { + │ "model": { + │ "id": "" + │ }, + │ "text": "SKILL_DONE", + │ "usage": { + │ "cacheRead": 11101, + │ "cacheWrite": 1207, + │ "cost": { + │ "cacheRead": 0.0033302999999999996, + │ "cacheWrite": 0.00452625, + │ "input": 0.00010200000000000001, + │ "output": 0.0050100000000000006, + │ "total": 0.012968549999999999 + │ }, + │ "input": 34, + │ "output": 334, + │ "totalTokens": 12676 + │ } + │ } + │ metadata: { + │ "flue.operation": "skill", + │ "flue.session": "skill", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 89, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0041862, + │ │ "prompt_cache_creation_tokens": 670, + │ │ "prompt_cached_tokens": 1099, + │ │ "prompt_tokens": 3, + │ │ "tokens": 1861 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": {} + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ │ error: "{\"content\":[{\"type\":\"text\",\"text\":\"ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'\"}],\"details\":{}}" + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 52, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.00201795, + │ │ "prompt_cache_creation_tokens": 183, + │ │ "prompt_cached_tokens": 1769, + │ │ "prompt_tokens": 7, + │ │ "tokens": 2011 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "entries": 1, + │ │ "isDirectory": true, + │ │ "path": ".agents" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 54, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0016611, + │ │ "prompt_cache_creation_tokens": 66, + │ │ "prompt_cached_tokens": 1952, + │ │ "prompt_tokens": 6, + │ │ "tokens": 2078 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/skills" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "e2e-flue-skill", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "entries": 1, + │ │ "isDirectory": true, + │ │ "path": ".agents/skills" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "e2e-flue-skill", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 63, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0018459, + │ │ "prompt_cache_creation_tokens": 74, + │ │ "prompt_cached_tokens": 2018, + │ │ "prompt_tokens": 6, + │ │ "tokens": 2161 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "SKILL.md", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "entries": 1, + │ │ "isDirectory": true, + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ ├── llm:claude-sonnet-4-5-20250929 [llm] + │ │ input: [ + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "role": "user" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ │ "type": "text" + │ │ }, + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/e2e-flue-skill.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": true, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "skills", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "e2e-flue-skill", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills/e2e-flue-skill" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ }, + │ │ { + │ │ "content": [ + │ │ { + │ │ "text": "SKILL.md", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "isError": false, + │ │ "role": "toolResult", + │ │ "toolCallId": "", + │ │ "toolName": "read" + │ │ } + │ │ ] + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "arguments": { + │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ │ }, + │ │ "id": "", + │ │ "name": "read", + │ │ "type": "toolCall" + │ │ } + │ │ ], + │ │ "role": "assistant" + │ │ } + │ │ metadata: { + │ │ "flue.api": "anthropic-messages", + │ │ "flue.model": "claude-sonnet-4-5-20250929", + │ │ "flue.provider": "anthropic", + │ │ "flue.session": "skill", + │ │ "flue.stop_reason": "toolUse", + │ │ "flue.turn_purpose": "agent", + │ │ "model": "claude-sonnet-4-5-20250929", + │ │ "provider": "anthropic" + │ │ } + │ │ metrics: { + │ │ "completion_tokens": 68, + │ │ "duration_ms": 0, + │ │ "estimated_cost": 0.0019618500000000002, + │ │ "prompt_cache_creation_tokens": 79, + │ │ "prompt_cached_tokens": 2092, + │ │ "prompt_tokens": 6, + │ │ "tokens": 2245 + │ │ } + │ │ └── tool:read [tool] + │ │ input: { + │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ │ } + │ │ output: { + │ │ "content": [ + │ │ { + │ │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + │ │ "type": "text" + │ │ } + │ │ ], + │ │ "details": { + │ │ "lines": 7, + │ │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ │ } + │ │ } + │ │ metadata: { + │ │ "flue.session": "skill", + │ │ "flue.tool_name": "read", + │ │ "provider": "flue" + │ │ } + │ │ metrics: { + │ │ "duration_ms": 0 + │ │ } + │ └── llm:claude-sonnet-4-5-20250929 [llm] + │ input: [ + │ { + │ "content": [ + │ { + │ "text": "Run the skill named \"e2e-flue-skill\".\n\nArguments:\n{\n \"marker\": \"SKILL_DONE\"\n}", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ }, + │ { + │ "content": [ + │ { + │ "text": "I'll run the e2e-flue-skill. Let me first read the skill file to understand its instructions.", + │ "type": "text" + │ }, + │ { + │ "arguments": { + │ "path": ".agents/e2e-flue-skill.md" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "ENOENT: no such file or directory, open '/e2e/scenarios/flue-instrumentation/.agents/e2e-flue-skill.md'", + │ "type": "text" + │ } + │ ], + │ "isError": true, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "skills", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents/skills" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "e2e-flue-skill", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents/skills/e2e-flue-skill" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "SKILL.md", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ }, + │ { + │ "content": [ + │ { + │ "arguments": { + │ "path": ".agents/skills/e2e-flue-skill/SKILL.md" + │ }, + │ "id": "", + │ "name": "read", + │ "type": "toolCall" + │ } + │ ], + │ "role": "assistant" + │ }, + │ { + │ "content": [ + │ { + │ "text": "---\nname: e2e-flue-skill\ndescription: Deterministic skill used by the Braintrust Flue instrumentation e2e test.\n---\n\nReturn the marker from the provided args exactly once. Output no other text.\n", + │ "type": "text" + │ } + │ ], + │ "isError": false, + │ "role": "toolResult", + │ "toolCallId": "", + │ "toolName": "read" + │ } + │ ] + │ output: { + │ "content": [ + │ { + │ "text": "SKILL_DONE", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ metadata: { + │ "flue.api": "anthropic-messages", + │ "flue.model": "claude-sonnet-4-5-20250929", + │ "flue.provider": "anthropic", + │ "flue.session": "skill", + │ "flue.stop_reason": "stop", + │ "flue.turn_purpose": "agent", + │ "model": "claude-sonnet-4-5-20250929", + │ "provider": "anthropic" + │ } + │ metrics: { + │ "completion_tokens": 8, + │ "duration_ms": 0, + │ "estimated_cost": 0.00129555, + │ "prompt_cache_creation_tokens": 135, + │ "prompt_cached_tokens": 2171, + │ "prompt_tokens": 6, + │ "tokens": 2320 + │ } + ├── flue.task [task] + │ output: { + │ "model": { + │ "id": "" + │ }, + │ "text": "TASK_DONE", + │ "usage": { + │ "cacheRead": 0, + │ "cacheWrite": 0, + │ "cost": { + │ "cacheRead": 0, + │ "cacheWrite": 0, + │ "input": 0.00012059999999999999, + │ "output": 0.0000024, + │ "total": 0.00012299999999999998 + │ }, + │ "input": 804, + │ "output": 4, + │ "totalTokens": 808 + │ } + │ } + │ metadata: { + │ "flue.operation": "task", + │ "flue.session": "task", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ └── flue.task [task] + │ input: "Reply with exactly TASK_DONE and no other text." + │ output: "TASK_DONE" + │ metadata: { + │ "flue.session": "task", + │ "provider": "flue" + │ } + │ metrics: { + │ "duration_ms": 0 + │ } + │ └── llm:gpt-4o-mini [llm] + │ input: [ + │ { + │ "content": [ + │ { + │ "text": "Reply with exactly TASK_DONE and no other text.", + │ "type": "text" + │ } + │ ], + │ "role": "user" + │ } + │ ] + │ output: { + │ "content": [ + │ { + │ "text": "TASK_DONE", + │ "textSignature": "{\"v\":1,\"id\":\"msg_09b32b2821e9a4d8016a184600019081929d34bb7d4c6a246f\"}", + │ "type": "text" + │ } + │ ], + │ "role": "assistant" + │ } + │ metadata: { + │ "flue.api": "openai-responses", + │ "flue.model": "gpt-4o-mini", + │ "flue.provider": "openai", + │ "flue.session": "task:task:", + │ "flue.stop_reason": "stop", + │ "flue.turn_purpose": "agent", + │ "model": "gpt-4o-mini", + │ "provider": "openai" + │ } + │ metrics: { + │ "completion_tokens": 4, + │ "duration_ms": 0, + │ "estimated_cost": 0.00012299999999999998, + │ "prompt_cache_creation_tokens": 0, + │ "prompt_cached_tokens": 0, + │ "prompt_tokens": 804, + │ "tokens": 808 + │ } + └── flue.compact [task] + metadata: { + "flue.operation": "compact", + "flue.session": "main", + "provider": "flue" + } + metrics: { + "duration_ms": 0 + } + └── compaction:manual [task] + input: { + "estimatedTokens": 2950, + "reason": "manual" + } + output: { + "messagesAfter": 2, + "messagesBefore": 8 + } + metadata: { + "flue.compaction_reason": "manual", + "flue.session": "main", + "provider": "flue" + } + metrics: { + "duration_ms": 0, + "messages_after": 2, + "messages_before": 8 + } + └── llm:gpt-4o-mini [llm] + input: [ + { + "content": [ + { + "text": "\n[User]: Complete this instrumented research flow. Call exactly one tool per turn and wait for each tool result before choosing the next tool. Step 1: call lookup with query \"flue instrumentation\". Step 2: use the lookup result id as lookupId and call web_search with query \"Braintrust Flue reasoning stream instrumentation\". Step 3: use the first web_search result url and call summarize_source. After summarize_source returns, reply with exactly PROMPT_DONE and no other text.\n\n[Assistant thinking]: The user wants me to complete a research flow with exactly three steps:\n1. Call lookup with query \"flue instrumentation\"\n2. Call web_search with the lookupId from step 1 and query \"Braintrust Flue reasoning stream instrumentation\"\n3. Call summarize_source with the first URL from step 2\n4. Reply with exactly \"PROMPT_DONE\"\n\nThe user emphasizes I should call exactly one tool per turn and wait for each result. Let me start with step 1.\n\n[Assistant]: I'll complete this instrumented research flow step by step. Starting with Step 1:\n\n[Assistant tool calls]: lookup(query=\"flue instrumentation\")\n\n[Tool result]: {\"id\":\"flue-session-2026\",\"query\":\"flue instrumentation\",\"topic\":\"session instrumentation\"}\n\n[Assistant thinking]: Good, I got the lookup result with id \"flue-session-2026\". Now I need to proceed to step 2: call web_search with this lookupId and the query \"Braintrust Flue reasoning stream instrumentation\".\n\n[Assistant]: Now proceeding to Step 2:\n\n[Assistant tool calls]: web_search(lookupId=\"flue-session-2026\", query=\"Braintrust Flue reasoning stream instrumentation\")\n\n[Tool result]: {\"lookupId\":\"flue-session-2026\",\"query\":\"Braintrust Flue reasoning stream instrumentation\",\"results\":[{\"title\":\"Flue reasoning stream instrumentation\",\"url\":\"https://example.test/flue/reasoning-streams\"}]}\n\n[Assistant thinking]: Perfect! I got the web_search results with one result. The first (and only) result has the URL \"https://example.test/flue/reasoning-streams\". Now I need to proceed to step 3: call summarize_source with this URL.\n\n[Assistant]: Now proceeding to Step 3:\n\n[Assistant tool calls]: summarize_source(url=\"https://example.test/flue/reasoning-streams\")\n\n[Tool result]: {\"summary\":\"Flue emits reasoning, tool execution, and LLM turn events separately.\",\"url\":\"https://example.test/flue/reasoning-streams\"}\n\n\nThis is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.", + "type": "text" + } + ], + "role": "user" + } + ] + output: { + "content": [ + { + "text": "## Original Request\nThe user requested to complete an instrumented research flow consisting of three specific steps, involving calling various tools in a sequential manner.\n\n## Early Progress", + "textSignature": "{\"v\":1,\"id\":\"msg_01ecf68325f9e202016a184601309081a0878ef4054e950d32\"}", + "type": "text" + } + ], + "role": "assistant" + } + metadata: { + "flue.api": "openai-responses", + "flue.model": "gpt-4o-mini", + "flue.provider": "openai", + "flue.session": "main", + "flue.stop_reason": "stop", + "flue.turn_purpose": "compaction_prefix", + "model": "gpt-4o-mini", + "provider": "openai" + } + metrics: { + "completion_tokens": 0, + "duration_ms": 0, + "estimated_cost": 0, + "prompt_cache_creation_tokens": 0, + "prompt_cached_tokens": 0, + "prompt_tokens": 0, + "tokens": 0 + } diff --git a/e2e/scenarios/flue-instrumentation/assertions.ts b/e2e/scenarios/flue-instrumentation/assertions.ts index 45df42dd5..395f43e5c 100644 --- a/e2e/scenarios/flue-instrumentation/assertions.ts +++ b/e2e/scenarios/flue-instrumentation/assertions.ts @@ -17,13 +17,13 @@ import { findLatestChildSpan, findLatestSpan, } from "../../helpers/trace-selectors"; -import { ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; +import { SCENARIO_NAME } from "./constants.mjs"; type RunFlueScenario = (harness: { runNodeScenarioDir: (options: { entry: string; env?: Record; - nodeArgs: string[]; + nodeArgs?: string[]; runContext?: ScenarioRunContext; scenarioDir: string; timeoutMs: number; @@ -40,19 +40,17 @@ type RunFlueScenario = (harness: { const SNAPSHOT_METADATA_KEYS = [ "provider", "model", - "operation", "scenario", + "flue.api", + "flue.compaction_reason", + "flue.model", "flue.operation", - "flue.version", + "flue.provider", "flue.session", - "flue.model", - "flue.role", - "flue.skill_name", - "flue.thinking", - "flue.thinking_level", - "flue.tools_count", + "flue.stop_reason", "flue.tool_name", - "flue.compaction_reason", + "flue.turn_purpose", + "flue.workflow_name", ] as const; function snapshotFields(event: CapturedLogEvent): SpanTreeFields { @@ -76,13 +74,18 @@ function snapshotFields(event: CapturedLogEvent): SpanTreeFields { }; } -function findFlueOperation( +function findFlueOperation(events: CapturedLogEvent[], flueSpanName: string) { + const workflow = findLatestSpanByPrefix(events, "workflow:"); + return findLatestChildSpan(events, flueSpanName, workflow?.span.id); +} + +function findLatestSpanByPrefix( events: CapturedLogEvent[], - operationName: string, - flueSpanName: string, -) { - const operation = findLatestSpan(events, operationName); - return findLatestChildSpan(events, flueSpanName, operation?.span.id); + prefix: string, +): CapturedLogEvent | undefined { + return [...events] + .reverse() + .find((event) => event.span.name?.startsWith(prefix)); } function findMatchingDescendants( @@ -146,149 +149,44 @@ function firstSpanIndex( function findFlueDescendants( events: CapturedLogEvent[], flueSpan: CapturedLogEvent | undefined, - operationSpan: CapturedLogEvent | undefined, predicate: (event: CapturedLogEvent) => boolean, ): CapturedLogEvent[] { - const bySpanId = new Map(); - for (const event of [ - ...findMatchingDescendants(events, flueSpan, predicate), - ...findMatchingDescendants(events, operationSpan, predicate), - ]) { - if (event.span.id && !bySpanId.has(event.span.id)) { - bySpanId.set(event.span.id, event); - } - } - return [...bySpanId.values()].sort( - (left, right) => - firstSpanIndex(events, left) - firstSpanIndex(events, right), - ); + return findMatchingDescendants(events, flueSpan, predicate); } function isFlueChildSpan(event: CapturedLogEvent): boolean { return ( - event.span.name === "flue.turn" || - event.span.name === "flue.task" || - event.span.name === "flue.compaction" || - event.span.name?.startsWith("tool: ") === true + event.span.name?.startsWith("llm:") === true || + event.span.name?.startsWith("tool:") === true || + event.span.name?.startsWith("task:") === true || + event.span.name?.startsWith("compaction:") === true || + event.span.name === "flue.task" ); } -function isProviderSpan(event: CapturedLogEvent): boolean { - return ( - event.span.name === "anthropic.messages.create" || - event.span.name === "openai.responses.create" || - event.span.name === "openai.responses.compact" - ); -} - -function isOperationChildSpan(event: CapturedLogEvent): boolean { - return isFlueChildSpan(event) || isProviderSpan(event); -} - -function expectToolsAndTurnsShareParent( - parent: CapturedLogEvent | undefined, - turns: CapturedLogEvent[], - tools: CapturedLogEvent[], -): void { - expect(parent).toBeDefined(); - const parentId = parent?.span.id; - expect(parentId).toBeDefined(); - if (!parentId) { - return; - } - const turnIds = new Set( - turns.flatMap((event) => (event.span.id ? [event.span.id] : [])), - ); - - expect(turns.length).toBeGreaterThan(0); - expect(tools.length).toBeGreaterThan(0); - expect(turns.every((event) => event.span.parentIds.includes(parentId))).toBe( - true, - ); - expect(tools.every((event) => event.span.parentIds.includes(parentId))).toBe( - true, - ); - expect( - tools.some((event) => - event.span.parentIds.some((parentId) => turnIds.has(parentId)), - ), - ).toBe(false); -} - function buildSpanTree(events: CapturedLogEvent[]): SpanTreeEntry[] { - const promptOperation = findLatestSpan(events, "flue-prompt-operation"); - const skillOperation = findLatestSpan(events, "flue-skill-operation"); - const taskOperation = findLatestSpan(events, "flue-task-operation"); - const compactOperation = findLatestSpan(events, "flue-compact-operation"); - const promptSpan = findFlueOperation( - events, - "flue-prompt-operation", - "flue.session.prompt", - ); - const skillSpan = findFlueOperation( - events, - "flue-skill-operation", - "flue.session.skill", - ); - const taskSpan = findFlueOperation( - events, - "flue-task-operation", - "flue.session.task", - ); - const compactSpan = findFlueOperation( - events, - "flue-compact-operation", - "flue.session.compact", - ); - - const promptChildren = findFlueDescendants( - events, - promptSpan, - promptOperation, - isOperationChildSpan, - ); - const skillChildren = findFlueDescendants( - events, - skillSpan, - skillOperation, - isOperationChildSpan, - ); - const taskChildren = findFlueDescendants( - events, - taskSpan, - taskOperation, - isOperationChildSpan, - ); - const compactChildren = findFlueDescendants( - events, - compactSpan, - compactOperation, - isOperationChildSpan, - ); + const workflow = findLatestSpanByPrefix(events, "workflow:"); + const promptSpan = findFlueOperation(events, "flue.prompt"); + const skillSpan = findFlueOperation(events, "flue.skill"); + const taskSpan = findFlueOperation(events, "flue.task"); + const compactSpan = findFlueOperation(events, "flue.compact"); return [ - findLatestSpan(events, ROOT_NAME), - promptOperation, + workflow, promptSpan, - ...promptChildren, - skillOperation, + ...findFlueDescendants(events, promptSpan, isFlueChildSpan), skillSpan, - ...skillChildren, - taskOperation, + ...findFlueDescendants(events, skillSpan, isFlueChildSpan), taskSpan, - ...taskChildren, - compactOperation, + ...findFlueDescendants(events, taskSpan, isFlueChildSpan), compactSpan, - ...compactChildren, + ...findFlueDescendants(events, compactSpan, isFlueChildSpan), ].flatMap((event) => event ? [{ event, fields: snapshotFields(event) }] : [], ); } export function defineFlueInstrumentationAssertions(options: { - expectedPromptProviderSpanName?: string; - expectFlueTurnSpans?: boolean; - expectThinking?: boolean; name: string; runScenario: RunFlueScenario; snapshotName: string; @@ -302,7 +200,7 @@ export function defineFlueInstrumentationAssertions(options: { const timeoutMs = effectiveScenarioTimeoutMs(options.timeoutMs); const testConfig = { timeout: timeoutMs }; - describe(options.name, () => { + describe.sequential(options.name, () => { let events: CapturedLogEvent[] = []; beforeAll(async () => { @@ -313,27 +211,25 @@ export function defineFlueInstrumentationAssertions(options: { }, timeoutMs); test("captures the root trace", testConfig, () => { - const root = findLatestSpan(events, ROOT_NAME); + const root = findLatestSpanByPrefix(events, "workflow:"); expect(root).toBeDefined(); - expect(root?.row.metadata).toMatchObject({ scenario: SCENARIO_NAME }); + expect(root?.input).toMatchObject({ scenario: SCENARIO_NAME }); + expect(root?.row.metadata).toMatchObject({ + "flue.workflow_name": "instrumentation", + provider: "flue", + }); }); - test("captures wrapped Flue operation spans", testConfig, () => { - for (const [operationName, flueSpanName] of [ - ["flue-prompt-operation", "flue.session.prompt"], - ["flue-skill-operation", "flue.session.skill"], - ["flue-task-operation", "flue.session.task"], - ["flue-compact-operation", "flue.session.compact"], + test("captures observe-based Flue operation spans", testConfig, () => { + for (const flueSpanName of [ + "flue.prompt", + "flue.skill", + "flue.task", + "flue.compact", ] as const) { - const operation = findLatestSpan(events, operationName); - const span = findLatestChildSpan( - events, - flueSpanName, - operation?.span.id, - ); + const span = findFlueOperation(events, flueSpanName); - expect(operation).toBeDefined(); expect(span).toBeDefined(); expect(span?.span.type).toBe("task"); expect(span?.row.metadata).toMatchObject({ @@ -343,131 +239,52 @@ export function defineFlueInstrumentationAssertions(options: { }); test( - "captures Flue child turn, tool, task, and compaction spans", + "captures Flue LLM, tool, task, and compaction spans", testConfig, () => { - const promptSpan = findFlueOperation( - events, - "flue-prompt-operation", - "flue.session.prompt", - ); - const promptOperation = findLatestSpan(events, "flue-prompt-operation"); + const promptSpan = findFlueOperation(events, "flue.prompt"); const promptChildren = findFlueDescendants( events, promptSpan, - promptOperation, - isOperationChildSpan, + isFlueChildSpan, ); - const promptTurns = promptChildren.filter( - (event) => event.span.name === "flue.turn", + const promptTurns = promptChildren.filter((event) => + event.span.name?.startsWith("llm:"), ); const promptTools = promptChildren.filter((event) => - event.span.name?.startsWith("tool: "), + event.span.name?.startsWith("tool:"), ); const lookupToolSpan = promptTools.find( - (event) => event.span.name === "tool: lookup", - ); - const reasoningTurn = promptTurns.find((event) => - JSON.stringify(event.output).includes('"reasoning"'), + (event) => event.span.name === "tool:lookup", ); - const skillSpan = findFlueOperation( - events, - "flue-skill-operation", - "flue.session.skill", - ); - const skillOperation = findLatestSpan(events, "flue-skill-operation"); - const skillChildren = findFlueDescendants( - events, - skillSpan, - skillOperation, - isOperationChildSpan, - ); - const skillTurns = skillChildren.filter( - (event) => event.span.name === "flue.turn", - ); - const skillTools = skillChildren.filter((event) => - event.span.name?.startsWith("tool: "), - ); - const taskSpan = findFlueOperation( - events, - "flue-task-operation", - "flue.session.task", - ); - const taskOperation = findLatestSpan(events, "flue-task-operation"); + const taskSpan = findFlueOperation(events, "flue.task"); const childTask = findFlueDescendants( events, taskSpan, - taskOperation, - (event) => event.span.name === "flue.task", + (event) => + event.span.name === "flue.task" || + event.span.name?.startsWith("task:") === true, )[0]; - const compactSpan = findFlueOperation( - events, - "flue-compact-operation", - "flue.session.compact", - ); - const compactOperation = findLatestSpan( - events, - "flue-compact-operation", - ); + const compactSpan = findFlueOperation(events, "flue.compact"); const compaction = findFlueDescendants( events, compactSpan, - compactOperation, - (event) => event.span.name === "flue.compaction", + (event) => event.span.name?.startsWith("compaction:") === true, )[0]; - const expectFlueTurnSpans = options.expectFlueTurnSpans ?? true; + expect(promptTurns.length).toBeGreaterThan(0); expect(promptTools.map((event) => event.span.name)).toEqual( expect.arrayContaining([ - "tool: lookup", - "tool: web_search", - "tool: summarize_source", + "tool:lookup", + "tool:web_search", + "tool:summarize_source", ]), ); - if (expectFlueTurnSpans) { - expect(promptTurns.length).toBeGreaterThanOrEqual(3); - expectToolsAndTurnsShareParent(promptSpan, promptTurns, promptTools); - expectToolsAndTurnsShareParent(skillSpan, skillTurns, skillTools); - } else { - expect(promptTurns).toHaveLength(0); - expect(skillTurns).toHaveLength(0); - expect(promptSpan).toBeDefined(); - expect(skillSpan).toBeDefined(); - const promptSpanId = promptSpan?.span.id; - const skillSpanId = skillSpan?.span.id; - if (promptSpanId) { - expect( - promptTools.every((event) => - event.span.parentIds.includes(promptSpanId), - ), - ).toBe(true); - } - if (skillSpanId) { - expect( - skillTools.every((event) => - event.span.parentIds.includes(skillSpanId), - ), - ).toBe(true); - } - } - if (expectFlueTurnSpans && options.expectThinking !== false) { - expect(reasoningTurn?.span.type).toBe("llm"); - expect(reasoningTurn?.output).toBeDefined(); - const reasoningOutput = JSON.stringify(reasoningTurn?.output); - expect(reasoningOutput).not.toContain(""); - expect(reasoningOutput).not.toContain("content unavailable"); - expect(reasoningOutput).not.toContain("[Reasoning redacted]"); - expect(reasoningTurn?.metadata).toMatchObject({ - "flue.thinking": true, - }); - } - if (expectFlueTurnSpans) { - expect(promptTurns[0]?.metrics).toMatchObject({ - completion_tokens: expect.any(Number), - prompt_tokens: expect.any(Number), - tokens: expect.any(Number), - }); - } + expect(promptTurns[0]?.metrics).toMatchObject({ + completion_tokens: expect.any(Number), + prompt_tokens: expect.any(Number), + tokens: expect.any(Number), + }); expect(lookupToolSpan?.span.type).toBe("tool"); expect(lookupToolSpan?.input).toMatchObject({ query: "flue instrumentation", @@ -475,7 +292,6 @@ export function defineFlueInstrumentationAssertions(options: { expect(JSON.stringify(lookupToolSpan?.output)).toContain( "flue-session-2026", ); - expect(skillSpan?.output).toBe("SKILL_DONE"); expect(childTask?.span.type).toBe("task"); expect(childTask?.input).toBe( "Reply with exactly TASK_DONE and no other text.", @@ -488,33 +304,7 @@ export function defineFlueInstrumentationAssertions(options: { ); test("does not instrument session.shell", testConfig, () => { - expect(findAllSpans(events, "flue.session.shell")).toHaveLength(0); - }); - - test("nests provider spans inside Flue operations", testConfig, () => { - const promptSpan = findFlueOperation( - events, - "flue-prompt-operation", - "flue.session.prompt", - ); - const promptProviders = findMatchingDescendants( - events, - promptSpan, - isProviderSpan, - ); - - if (options.expectedPromptProviderSpanName) { - const provider = promptProviders.find( - (event) => event.span.name === options.expectedPromptProviderSpanName, - ); - expect(provider).toBeDefined(); - expect(provider?.input).toBeDefined(); - expect(JSON.stringify(provider?.input)).toContain( - "Complete this instrumented research flow", - ); - } else { - expect(promptProviders).toHaveLength(0); - } + expect(findAllSpans(events, "flue.shell")).toHaveLength(0); }); test("matches the span tree snapshot", testConfig, async () => { diff --git a/e2e/scenarios/flue-instrumentation/package.json b/e2e/scenarios/flue-instrumentation/package.json index bd5839aab..d488f15c9 100644 --- a/e2e/scenarios/flue-instrumentation/package.json +++ b/e2e/scenarios/flue-instrumentation/package.json @@ -3,6 +3,7 @@ "private": true, "type": "module", "dependencies": { - "@flue/runtime": "0.7.0" + "@flue/cli": "0.8.0", + "@flue/runtime": "0.8.0" } } diff --git a/e2e/scenarios/flue-instrumentation/pnpm-lock.yaml b/e2e/scenarios/flue-instrumentation/pnpm-lock.yaml index 24d16999c..ce55e0d37 100644 --- a/e2e/scenarios/flue-instrumentation/pnpm-lock.yaml +++ b/e2e/scenarios/flue-instrumentation/pnpm-lock.yaml @@ -8,9 +8,12 @@ importers: .: dependencies: + '@flue/cli': + specifier: 0.8.0 + version: 0.8.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@types/node@25.9.1)(esbuild@0.27.3)(typebox@1.1.38)(workerd@1.20260526.1)(wrangler@4.95.0)(yaml@2.9.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3) '@flue/runtime': - specifier: 0.7.0 - version: 0.7.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(ws@8.20.1)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3) + specifier: 0.8.0 + version: 0.8.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3) packages: @@ -131,25 +134,58 @@ packages: '@borewit/text-codec@0.2.2': resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} - '@cloudflare/codemode@0.3.7': - resolution: {integrity: sha512-Tc2AcF39ZExXMcCkTYtYGRHgIbWLePdWcRErEAS+RrpNgQht5dG0A9TkQDUQ1kyE43AC+gl4leVwhoWY2V9sWw==} + '@cloudflare/kv-asset-handler@0.5.0': + resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} + engines: {node: '>=22.0.0'} + + '@cloudflare/unenv-preset@2.16.1': + resolution: {integrity: sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==} peerDependencies: - '@modelcontextprotocol/sdk': ^1.25.0 - '@tanstack/ai': '>=0.8.0 <1.0.0' - ai: ^6.0.0 - zod: ^4.0.0 + unenv: 2.0.0-rc.24 + workerd: '>1.20260305.0 <2.0.0-0' peerDependenciesMeta: - '@modelcontextprotocol/sdk': - optional: true - '@tanstack/ai': - optional: true - ai: - optional: true - zod: + workerd: optional: true - '@cloudflare/shell@0.3.8': - resolution: {integrity: sha512-tuseZ2bYEIiiOioGOgD9SqhchUQfHPOaRcifw8fj0YwTZNvcmO/wSvbtWDxxC/CUlnEJ1Y+tvNHub97TyTyoEQ==} + '@cloudflare/vite-plugin@1.39.0': + resolution: {integrity: sha512-AHC+KSR+3dtGu7Ab7I0Ode4Whx12TxMEmiZt7w+Fc3/2wYNByIzbb6cndWZ78tnveFdO1xhNLv1YaNngxGtOPg==} + peerDependencies: + vite: ^6.1.0 || ^7.0.0 || ^8.0.0 + wrangler: ^4.95.0 + + '@cloudflare/workerd-darwin-64@1.20260526.1': + resolution: {integrity: sha512-/pR3GH3gfv0PUp7DjI8v0aAIDOqFwibq4bg5xT7TZgcVdBV/cJQWckdXCMqiRtHiawLwogUX00EIOINkYJ1Zqg==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20260526.1': + resolution: {integrity: sha512-rcyu0iANYfaiezKh3Mcao1O4IIgVfQldxduiL5TZT1sP0NIeRY4YReSTrzPxNnXxSYaIqaqRHMcHbUM/ic4knA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20260526.1': + resolution: {integrity: sha512-5EZAEnlLwa9oGJRo8Nd3iY5Wcd9ROGNNG90xNIGp8MEjj8v2jTn42NC47fCZKFdnLj3+S+vWEhu1x0GVJnALjA==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20260526.1': + resolution: {integrity: sha512-X/YBQXeXFeCN7QTStoWrATEBc9WKl7PIqkw/dQkjyJ72gh3rkLe0+Xkzp3wO7gtxTDQMa7NPGy1W4+sdMf8q1g==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20260526.1': + resolution: {integrity: sha512-R+tqpFFdcfZIljx8fIW9rj9fRTtDgfoA2yonsfAGa6e8snrmr+38mdFHtkRC0D3UyZpn/hOtmXiUBfdX2gMR7Q==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} '@earendil-works/pi-agent-core@0.75.4': resolution: {integrity: sha512-cGYbysb4EqUf0B28OeqFq2ppm1XF3bYBOP71q9dv38yf/UJfzMjiXBeNelrcio+QWIoVrW+xzYm7sMzYIUc9Og==} @@ -160,8 +196,183 @@ packages: engines: {node: '>=22.19.0'} hasBin: true - '@flue/runtime@0.7.0': - resolution: {integrity: sha512-irkY9cqXkerzONBUtkrVBA869llLrzmzu97phWBm/z/LivgWBkt7YDfg8SrpNuTGbP9ScGjJmLtIXswe0Cz4Gw==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@flue/cli@0.8.0': + resolution: {integrity: sha512-iWTVoSCZ0/D5T5O4E+dha9IT7yx1/qqjsEGLtedd/wnlp2nK45qTrjutBS2pgenGNzdQ6wlPzMPkP8MA9z49yw==} + engines: {node: '>=22.18.0'} + hasBin: true + peerDependencies: + wrangler: ^4.94.0 + peerDependenciesMeta: + wrangler: + optional: true + + '@flue/runtime@0.8.0': + resolution: {integrity: sha512-GCXJOZtb6s+HuMBzB4I41uQzxX7pELfdorD3gnWnkYoNFjHW8D/ncjXMTsczyl2tkP1IPK0C1Ffw0zwGqkmO7g==} engines: {node: '>=22.18.0'} '@google/genai@1.52.0': @@ -179,12 +390,171 @@ packages: peerDependencies: hono: ^4 + '@hono/node-server@2.0.4': + resolution: {integrity: sha512-Ut3y0dMMPWy6bZ2kVfx25EOVbZlm15dhF4mOsezMlhpNHy+4MkU1qN9Y6lnruYi4wPmFzimGX2X7LF/FwHli4A==} + engines: {node: '>=20'} + peerDependencies: + hono: ^4 + '@hono/standard-validator@0.2.2': resolution: {integrity: sha512-mJ7W84Bt/rSvoIl63Ynew+UZOHAzzRAoAXb3JaWuxAkM/Lzg+ZHTCUiz77KOtn2e623WNN8LkD57Dk0szqUrIw==} peerDependencies: '@standard-schema/spec': ^1.0.0 hono: '>=3.9.0' + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@jitl/quickjs-ffi-types@0.32.0': resolution: {integrity: sha512-v9T+GQpmk43VDJ7d72sf0Nexhk+ArvtUihW27dy7lqAl0zBObFKtSBBIm5RBjwIhE8VwsPPm9PNuvPvNqLWUEg==} @@ -200,6 +570,16 @@ packages: '@jitl/quickjs-wasmfile-release-sync@0.32.0': resolution: {integrity: sha512-BKNDI/TPBfGlLNGYpLrhcDGXmIk4xHm4MRAisOBnOzpXVn9HZWsfmMAc9WMBrAHjvvds6HOikKeaOBKdPdpVrg==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@mistralai/mistralai@2.2.1': resolution: {integrity: sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ==} @@ -220,9 +600,27 @@ packages: resolution: {integrity: sha512-mQ2s0pYYiav+tzCDR05Zptem8Ey2v8s11lri5RKGhTtL4COVCvVCk5vtyRYNT+9L8qSfyOqqefF9UtnW8mC5jA==} engines: {node: '>= 20.19.0'} + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nodable/entities@2.1.0': resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==} + '@oxc-project/types@0.132.0': + resolution: {integrity: sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==} + + '@poppinss/colors@4.1.6': + resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} + + '@poppinss/dumper@0.6.5': + resolution: {integrity: sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==} + + '@poppinss/exception@1.2.3': + resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} + '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -253,6 +651,108 @@ packages: '@protobufjs/utf8@1.1.1': resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@rolldown/binding-android-arm64@1.0.2': + resolution: {integrity: sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.2': + resolution: {integrity: sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.2': + resolution: {integrity: sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.2': + resolution: {integrity: sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.2': + resolution: {integrity: sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.2': + resolution: {integrity: sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.2': + resolution: {integrity: sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.2': + resolution: {integrity: sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.2': + resolution: {integrity: sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.2': + resolution: {integrity: sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.2': + resolution: {integrity: sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.2': + resolution: {integrity: sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.2': + resolution: {integrity: sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.2': + resolution: {integrity: sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.2': + resolution: {integrity: sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + '@smithy/core@3.24.3': resolution: {integrity: sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg==} engines: {node: '>=18.0.0'} @@ -289,6 +789,9 @@ packages: resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} + '@speed-highlight/core@1.2.15': + resolution: {integrity: sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==} + '@standard-community/standard-json@0.3.5': resolution: {integrity: sha512-4+ZPorwDRt47i+O7RjyuaxHRK/37QY/LmgxlGrRrSTLYoFatEOzvqIc85GTlM18SFZ5E91C+v0o/M37wZPpUHA==} peerDependencies: @@ -360,6 +863,9 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -374,19 +880,14 @@ packages: peerDependencies: valibot: ^1.4.0 - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} + '@vercel/detect-agent@1.2.3': + resolution: {integrity: sha512-VYNCgUc0nOmC4WJmWw9GkrKdfr8Zl4/rxhC5SvgacBgxiW9W/9NRttUoHHXV8xdII3MaRgkZZVX8Ikzc/Jmjag==} + engines: {node: '>=14'} accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} - acorn@8.16.0: - resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} - engines: {node: '>=0.4.0'} - hasBin: true - agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} @@ -402,12 +903,8 @@ packages: ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - async-lock@1.4.1: - resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} @@ -422,6 +919,9 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} @@ -439,9 +939,6 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -450,10 +947,6 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.9: - resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} - engines: {node: '>= 0.4'} - call-bound@1.0.4: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} @@ -461,9 +954,6 @@ packages: chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - clean-git-ref@2.0.1: - resolution: {integrity: sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==} - commander@6.2.1: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} @@ -488,15 +978,14 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} - crc-32@1.2.2: - resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} - engines: {node: '>=0.8'} - hasBin: true - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -522,10 +1011,6 @@ packages: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -534,9 +1019,6 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - diff3@0.0.3: - resolution: {integrity: sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==} - diff@8.0.4: resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} @@ -558,6 +1040,9 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + error-stack-parser-es@1.0.5: + resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -570,6 +1055,11 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -577,14 +1067,6 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - eventsource-parser@3.0.8: resolution: {integrity: sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==} engines: {node: '>=18.0.0'} @@ -627,6 +1109,15 @@ packages: resolution: {integrity: sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==} hasBin: true + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -639,9 +1130,9 @@ packages: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} @@ -658,6 +1149,11 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -692,17 +1188,10 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - hasown@2.0.3: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} @@ -745,10 +1234,6 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - ignore@7.0.5: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} @@ -771,31 +1256,19 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isomorphic-git@1.38.1: - resolution: {integrity: sha512-Vd2u5qDLa04fA/h5nUMU5UuffPXqg+3D3bJIV3n7Sno2qS3XMinUXRvNHrGPVy2kkC1ad5SPCC3WcpXjn0L9oQ==} - engines: {node: '>=14.17'} - hasBin: true - jose@6.2.3: resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -809,8 +1282,8 @@ packages: json-schema-typed@8.0.2: resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} - just-bash@2.14.5: - resolution: {integrity: sha512-MCBGnRlDeZ/MM7mcw+ZuSGFMBsggajrmKz6e/hrOAN7syvVZkjiY+Vh2wyCwN/CdcnAX5SxbiQB51n5nrQuX+g==} + just-bash@3.0.1: + resolution: {integrity: sha512-YVyzCN08fKarUnwqy7rKOAcX+2MLYLnYInuowmUXn3mqhrtd4ieZNBuzdQG+qYV9DqnIWuv9Whiph0WRIWsBtw==} hasBin: true jwa@2.0.1: @@ -819,9 +1292,87 @@ packages: jws@4.0.1: resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + layerr@3.0.0: resolution: {integrity: sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} @@ -849,6 +1400,11 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} + miniflare@4.20260526.0: + resolution: {integrity: sha512-JYQ7jPZZWoaaj9jWHb8Ucp6Cu2SbDVqIsAJhumqdzzLkkfq0pYkDeino/sZfW1ixJWPjv/C44zjm9gVJC2izCA==} + engines: {node: '>=22.0.0'} + hasBin: true + minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} @@ -856,9 +1412,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minimisted@2.0.1: - resolution: {integrity: sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==} - mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -869,6 +1422,11 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} @@ -936,8 +1494,9 @@ packages: resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} engines: {node: '>=8'} - pako@1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + package-up@5.0.0: + resolution: {integrity: sha512-MQEgDUvXCa3sGvqHg3pzHO8e9gqTCMPVrWUko3vPQGntwegmFo52mZb2abIVTjFnUcW0BcPz0D93jV5Cas1DWA==} + engines: {node: '>=18'} papaparse@5.5.3: resolution: {integrity: sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==} @@ -957,20 +1516,29 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} - pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} pkce-challenge@5.0.1: resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} engines: {node: '>=16.20.0'} - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} @@ -978,10 +1546,6 @@ packages: deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. hasBin: true - process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - protobufjs@7.6.0: resolution: {integrity: sha512-LtESOsMPTZgyYtwxhvdgdjGL0HmXEaRA/hVD6sol4zA60hVXXXP/SGmxnqDbgGE8gy7pYex7cym+5vYPcmaXBQ==} engines: {node: '>=12.0.0'} @@ -1026,10 +1590,6 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - readable-stream@4.7.0: - resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -1038,6 +1598,31 @@ packages: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} + rolldown@1.0.2: + resolution: {integrity: sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rosie-skills-darwin-arm64@0.6.4: + resolution: {integrity: sha512-rn1s5hqFKcxeiDEWWoFa1hdGPshR8TkwHLzy/cBavb9XJNAaUxbe3oQ78W9sQkRHAgRyzJYyk9tw68Qrdnizgg==} + cpu: [arm64] + os: [darwin] + + rosie-skills-freebsd-x64@0.6.4: + resolution: {integrity: sha512-SxCRduPBMtfjkQ+q56Yw9OLA3PyaqoALzt7kER7IDKuUVfM2O/1w8sa5xhTDiCvWkZJixnH5d5Ya6KT+/Mwcng==} + cpu: [x64] + os: [freebsd] + + rosie-skills-linux-x64@0.6.4: + resolution: {integrity: sha512-D9Y9mfu7goB0s0X59uU3hcFeUTef3VbpCIDwFMzyvJrAq3XhRACWBDMHQsHlyWdHxTXPX/ILyW65RXyrJlgqng==} + cpu: [x64] + os: [linux] + + rosie-skills@0.6.4: + resolution: {integrity: sha512-ojfhSiQRdZ2QyWbmKAHOSAUbaLYrTc5zIH7mS1jKoP8KCFSQddwVhMyFqldckTeybTfW3zNcsZzyOTzGTN1SBA==} + engines: {node: '>=18'} + hasBin: true + router@2.2.0: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} @@ -1065,17 +1650,12 @@ packages: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - sha.js@2.4.12: - resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} - engines: {node: '>= 0.10'} - hasBin: true + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} @@ -1111,6 +1691,10 @@ packages: resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} engines: {node: '>= 18'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} @@ -1135,6 +1719,10 @@ packages: resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} engines: {node: '>=18'} + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + tar-fs@2.1.4: resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} @@ -1142,9 +1730,9 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - to-buffer@1.2.2: - resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} - engines: {node: '>= 0.4'} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} @@ -1174,10 +1762,6 @@ packages: typebox@1.1.38: resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==} - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - uint8array-extras@1.5.0: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} @@ -1189,6 +1773,13 @@ packages: undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici@7.24.8: + resolution: {integrity: sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ==} + engines: {node: '>=20.18.1'} + + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -1208,19 +1799,73 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vite@8.0.14: + resolution: {integrity: sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} - engines: {node: '>= 0.4'} - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + workerd@1.20260526.1: + resolution: {integrity: sha512-IHzymht98p10JH1zzwdCpbViAqw97HrwKl7+KfZeASFMsYSrIsAULWdPn0LRC5FTUzBpamLNyKCCKxbgXHgRHQ==} + engines: {node: '>=16'} + hasBin: true + + wrangler@4.95.0: + resolution: {integrity: sha512-vgXzFVSCdUbeCadgVXvu8fK5tzNm8T9W+7lriyGWZMx0B1+CAdr4d8JTlZszHfgjypRAHmAxb49etZGIRD9pgg==} + engines: {node: '>=22.0.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20260526.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -1245,6 +1890,12 @@ packages: engines: {node: '>= 14.6'} hasBin: true + youch-core@0.3.3: + resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} + + youch@4.1.0-beta.10: + resolution: {integrity: sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==} + zod-to-json-schema@3.25.2: resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} peerDependencies: @@ -1490,23 +2141,45 @@ snapshots: '@borewit/text-codec@0.2.2': {} - '@cloudflare/codemode@0.3.7(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': + '@cloudflare/kv-asset-handler@0.5.0': {} + + '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260526.1)': dependencies: - '@types/json-schema': 7.0.15 - acorn: 8.16.0 + unenv: 2.0.0-rc.24 optionalDependencies: - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) - zod: 4.4.3 + workerd: 1.20260526.1 - '@cloudflare/shell@0.3.8(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)': + '@cloudflare/vite-plugin@1.39.0(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.3)(yaml@2.9.0))(workerd@1.20260526.1)(wrangler@4.95.0)': dependencies: - '@cloudflare/codemode': 0.3.7(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) - isomorphic-git: 1.38.1 + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260526.1) + miniflare: 4.20260526.0 + unenv: 2.0.0-rc.24 + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.3)(yaml@2.9.0) + wrangler: 4.95.0 + ws: 8.20.1 transitivePeerDependencies: - - '@modelcontextprotocol/sdk' - - '@tanstack/ai' - - ai - - zod + - bufferutil + - utf-8-validate + - workerd + + '@cloudflare/workerd-darwin-64@1.20260526.1': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20260526.1': + optional: true + + '@cloudflare/workerd-linux-64@1.20260526.1': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20260526.1': + optional: true + + '@cloudflare/workerd-windows-64@1.20260526.1': + optional: true + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 '@earendil-works/pi-agent-core@0.75.4(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.20.1)(zod@4.4.3)': dependencies: @@ -1541,40 +2214,170 @@ snapshots: - ws - zod - '@flue/runtime@0.7.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(ws@8.20.1)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3)': + '@emnapi/core@1.10.0': dependencies: - '@cloudflare/codemode': 0.3.7(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) - '@cloudflare/shell': 0.3.8(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) - '@earendil-works/pi-agent-core': 0.75.4(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.20.1)(zod@4.4.3) - '@earendil-works/pi-ai': 0.75.4(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.20.1)(zod@4.4.3) - '@hono/node-server': 1.19.14(hono@4.12.21) - '@hono/standard-validator': 0.2.2(@standard-schema/spec@1.1.0)(hono@4.12.21) - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) - '@standard-community/standard-json': 0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3) - '@standard-community/standard-openapi': 0.2.9(@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3))(@standard-schema/spec@1.1.0)(openapi-types@12.1.3)(typebox@1.1.38)(valibot@1.4.0)(zod@4.4.3) - '@valibot/to-json-schema': 1.7.0(valibot@1.4.0) - hono: 4.12.21 - hono-openapi: 1.3.0(@hono/standard-validator@0.2.2(@standard-schema/spec@1.1.0)(hono@4.12.21))(@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3))(@standard-community/standard-openapi@0.2.9(@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3))(@standard-schema/spec@1.1.0)(openapi-types@12.1.3)(typebox@1.1.38)(valibot@1.4.0)(zod@4.4.3))(@types/json-schema@7.0.15)(hono@4.12.21)(openapi-types@12.1.3) - just-bash: 2.14.5 - openapi-types: 12.1.3 - quansync: 0.2.11 - ulidx: 2.4.1 - valibot: 1.4.0 - transitivePeerDependencies: - - '@cfworker/json-schema' - - '@standard-schema/spec' - - '@tanstack/ai' - - '@types/json-schema' - - ai - - arktype - - bufferutil - - effect - - supports-color - - sury - - typebox + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + + '@flue/cli@0.8.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@types/node@25.9.1)(esbuild@0.27.3)(typebox@1.1.38)(workerd@1.20260526.1)(wrangler@4.95.0)(yaml@2.9.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3)': + dependencies: + '@cloudflare/vite-plugin': 1.39.0(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.3)(yaml@2.9.0))(workerd@1.20260526.1)(wrangler@4.95.0) + '@flue/runtime': 0.8.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3) + '@vercel/detect-agent': 1.2.3 + package-up: 5.0.0 + valibot: 1.4.0 + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.3)(yaml@2.9.0) + optionalDependencies: + wrangler: 4.95.0 + transitivePeerDependencies: + - '@cfworker/json-schema' + - '@standard-schema/spec' + - '@types/json-schema' + - '@types/node' + - '@vitejs/devtools' + - arktype + - bufferutil + - effect + - esbuild + - jiti + - less + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - sury + - terser + - tsx + - typebox + - typescript + - utf-8-validate + - workerd + - yaml + - zod + - zod-openapi + - zod-to-json-schema + + '@flue/runtime@0.8.0(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3)': + dependencies: + '@earendil-works/pi-agent-core': 0.75.4(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.20.1)(zod@4.4.3) + '@earendil-works/pi-ai': 0.75.4(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.20.1)(zod@4.4.3) + '@hono/node-server': 2.0.4(hono@4.12.21) + '@hono/standard-validator': 0.2.2(@standard-schema/spec@1.1.0)(hono@4.12.21) + '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) + '@standard-community/standard-json': 0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3) + '@standard-community/standard-openapi': 0.2.9(@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3))(@standard-schema/spec@1.1.0)(openapi-types@12.1.3)(typebox@1.1.38)(valibot@1.4.0)(zod@4.4.3) + '@valibot/to-json-schema': 1.7.0(valibot@1.4.0) + hono: 4.12.21 + hono-openapi: 1.3.0(@hono/standard-validator@0.2.2(@standard-schema/spec@1.1.0)(hono@4.12.21))(@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3))(@standard-community/standard-openapi@0.2.9(@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3))(@standard-schema/spec@1.1.0)(openapi-types@12.1.3)(typebox@1.1.38)(valibot@1.4.0)(zod@4.4.3))(@types/json-schema@7.0.15)(hono@4.12.21)(openapi-types@12.1.3) + js-yaml: 4.1.1 + just-bash: 3.0.1 + openapi-types: 12.1.3 + quansync: 0.2.11 + ulidx: 2.4.1 + valibot: 1.4.0 + ws: 8.20.1 + transitivePeerDependencies: + - '@cfworker/json-schema' + - '@standard-schema/spec' + - '@types/json-schema' + - arktype + - bufferutil + - effect + - supports-color + - sury + - typebox - typescript - utf-8-validate - - ws - zod - zod-openapi - zod-to-json-schema @@ -1596,11 +2399,111 @@ snapshots: dependencies: hono: 4.12.21 + '@hono/node-server@2.0.4(hono@4.12.21)': + dependencies: + hono: 4.12.21 + '@hono/standard-validator@0.2.2(@standard-schema/spec@1.1.0)(hono@4.12.21)': dependencies: '@standard-schema/spec': 1.1.0 hono: 4.12.21 + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.10.0 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + '@jitl/quickjs-ffi-types@0.32.0': {} '@jitl/quickjs-wasmfile-debug-asyncify@0.32.0': @@ -1619,6 +2522,15 @@ snapshots: dependencies: '@jitl/quickjs-ffi-types': 0.32.0 + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@mistralai/mistralai@2.2.1': dependencies: ws: 8.20.1 @@ -1658,8 +2570,29 @@ snapshots: prebuild-install: 7.1.3 optional: true + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + '@nodable/entities@2.1.0': {} + '@oxc-project/types@0.132.0': {} + + '@poppinss/colors@4.1.6': + dependencies: + kleur: 4.1.5 + + '@poppinss/dumper@0.6.5': + dependencies: + '@poppinss/colors': 4.1.6 + '@sindresorhus/is': 7.2.0 + supports-color: 10.2.2 + + '@poppinss/exception@1.2.3': {} + '@protobufjs/aspromise@1.1.2': {} '@protobufjs/base64@1.1.2': {} @@ -1682,6 +2615,59 @@ snapshots: '@protobufjs/utf8@1.1.1': {} + '@rolldown/binding-android-arm64@1.0.2': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.2': + optional: true + + '@rolldown/binding-darwin-x64@1.0.2': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.2': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.2': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.2': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.2': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.2': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.2': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.2': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.2': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.2': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.2': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.2': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.2': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@sindresorhus/is@7.2.0': {} + '@smithy/core@3.24.3': dependencies: '@aws-crypto/crc32': 5.2.0 @@ -1730,6 +2716,8 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 + '@speed-highlight/core@1.2.15': {} + '@standard-community/standard-json@0.3.5(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@valibot/to-json-schema@1.7.0(valibot@1.4.0))(quansync@0.2.11)(typebox@1.1.38)(valibot@1.4.0)(zod-to-json-schema@3.25.2(zod@4.4.3))(zod@4.4.3)': dependencies: '@standard-schema/spec': 1.1.0 @@ -1763,6 +2751,11 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + '@types/json-schema@7.0.15': {} '@types/node@25.9.1': @@ -1775,17 +2768,13 @@ snapshots: dependencies: valibot: 1.4.0 - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 + '@vercel/detect-agent@1.2.3': {} accepts@2.0.0: dependencies: mime-types: 3.0.2 negotiator: 1.0.0 - acorn@8.16.0: {} - agent-base@7.1.4: {} ajv-formats@3.0.1(ajv@8.20.0): @@ -1799,11 +2788,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - async-lock@1.4.1: {} - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 + argparse@2.0.1: {} balanced-match@4.0.4: {} @@ -1818,6 +2803,8 @@ snapshots: readable-stream: 3.6.2 optional: true + blake3-wasm@2.1.5: {} + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -1846,11 +2833,6 @@ snapshots: ieee754: 1.2.1 optional: true - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - bytes@3.1.2: {} call-bind-apply-helpers@1.0.2: @@ -1858,13 +2840,6 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.9: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - call-bound@1.0.4: dependencies: call-bind-apply-helpers: 1.0.2 @@ -1873,8 +2848,6 @@ snapshots: chownr@1.1.4: optional: true - clean-git-ref@2.0.1: {} - commander@6.2.1: {} content-disposition@1.1.0: {} @@ -1887,13 +2860,13 @@ snapshots: cookie@0.7.2: {} + cookie@1.1.1: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 vary: 1.1.2 - crc-32@1.2.2: {} - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -1909,22 +2882,14 @@ snapshots: decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 + optional: true deep-extend@0.6.0: optional: true - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - depd@2.0.0: {} - detect-libc@2.1.2: - optional: true - - diff3@0.0.3: {} + detect-libc@2.1.2: {} diff@8.0.4: {} @@ -1947,6 +2912,8 @@ snapshots: once: 1.4.0 optional: true + error-stack-parser-es@1.0.5: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -1955,14 +2922,39 @@ snapshots: dependencies: es-errors: 1.3.0 + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + escape-html@1.0.3: {} etag@1.8.1: {} - event-target-shim@5.0.1: {} - - events@3.3.0: {} - eventsource-parser@3.0.8: {} eventsource@3.0.7: @@ -2036,6 +3028,10 @@ snapshots: strnum: 2.3.0 xml-naming: 0.1.0 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + fetch-blob@3.2.0: dependencies: node-domexception: 1.0.0 @@ -2061,9 +3057,7 @@ snapshots: transitivePeerDependencies: - supports-color - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 + find-up-simple@1.0.1: {} formdata-polyfill@4.0.10: dependencies: @@ -2076,6 +3070,9 @@ snapshots: fs-constants@1.0.0: optional: true + fsevents@2.3.3: + optional: true + function-bind@1.1.2: {} gaxios@7.1.4: @@ -2130,16 +3127,8 @@ snapshots: gopd@1.2.0: {} - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - has-symbols@1.1.0: {} - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - hasown@2.0.3: dependencies: function-bind: 1.1.2 @@ -2184,8 +3173,6 @@ snapshots: ieee754@1.2.1: {} - ignore@5.3.2: {} - ignore@7.0.5: {} inherits@2.0.4: {} @@ -2199,34 +3186,16 @@ snapshots: ipaddr.js@1.9.1: {} - is-callable@1.2.7: {} - is-promise@4.0.0: {} - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.20 - - isarray@2.0.5: {} - isexe@2.0.0: {} - isomorphic-git@1.38.1: - dependencies: - async-lock: 1.4.1 - clean-git-ref: 2.0.1 - crc-32: 1.2.2 - diff3: 0.0.3 - ignore: 5.3.2 - minimisted: 2.0.1 - pako: 1.0.11 - pify: 4.0.1 - readable-stream: 4.7.0 - sha.js: 2.4.12 - simple-get: 4.0.1 - jose@6.2.3: {} + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + json-bigint@1.0.0: dependencies: bignumber.js: 9.3.1 @@ -2240,7 +3209,7 @@ snapshots: json-schema-typed@8.0.2: {} - just-bash@2.14.5: + just-bash@3.0.1: dependencies: diff: 8.0.4 fast-xml-parser: 5.8.0 @@ -2274,8 +3243,59 @@ snapshots: jwa: 2.0.1 safe-buffer: 5.2.1 + kleur@4.1.5: {} + layerr@3.0.0: {} + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + long@5.3.2: {} math-intrinsics@1.1.0: {} @@ -2290,17 +3310,27 @@ snapshots: dependencies: mime-db: 1.54.0 - mimic-response@3.1.0: {} + mimic-response@3.1.0: + optional: true + + miniflare@4.20260526.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + sharp: 0.34.5 + undici: 7.24.8 + workerd: 1.20260526.1 + ws: 8.20.1 + youch: 4.1.0-beta.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate minimatch@10.2.5: dependencies: brace-expansion: 5.0.6 - minimist@1.2.8: {} - - minimisted@2.0.1: - dependencies: - minimist: 1.2.8 + minimist@1.2.8: + optional: true mkdirp-classic@0.5.3: optional: true @@ -2309,6 +3339,8 @@ snapshots: ms@2.1.3: {} + nanoid@3.3.12: {} + napi-build-utils@2.0.0: optional: true @@ -2363,7 +3395,9 @@ snapshots: '@types/retry': 0.12.0 retry: 0.13.1 - pako@1.0.11: {} + package-up@5.0.0: + dependencies: + find-up-simple: 1.0.1 papaparse@5.5.3: {} @@ -2375,13 +3409,23 @@ snapshots: path-key@3.1.1: {} + path-to-regexp@6.3.0: {} + path-to-regexp@8.4.2: {} - pify@4.0.1: {} + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.4: {} pkce-challenge@5.0.1: {} - possible-typed-array-names@1.1.0: {} + postcss@8.5.15: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 prebuild-install@7.1.3: dependencies: @@ -2399,8 +3443,6 @@ snapshots: tunnel-agent: 0.6.0 optional: true - process@0.11.10: {} - protobufjs@7.6.0: dependencies: '@protobufjs/aspromise': 1.1.2 @@ -2471,18 +3513,46 @@ snapshots: util-deprecate: 1.0.2 optional: true - readable-stream@4.7.0: - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - require-from-string@2.0.2: {} retry@0.13.1: {} + rolldown@1.0.2: + dependencies: + '@oxc-project/types': 0.132.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.2 + '@rolldown/binding-darwin-arm64': 1.0.2 + '@rolldown/binding-darwin-x64': 1.0.2 + '@rolldown/binding-freebsd-x64': 1.0.2 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.2 + '@rolldown/binding-linux-arm64-gnu': 1.0.2 + '@rolldown/binding-linux-arm64-musl': 1.0.2 + '@rolldown/binding-linux-ppc64-gnu': 1.0.2 + '@rolldown/binding-linux-s390x-gnu': 1.0.2 + '@rolldown/binding-linux-x64-gnu': 1.0.2 + '@rolldown/binding-linux-x64-musl': 1.0.2 + '@rolldown/binding-openharmony-arm64': 1.0.2 + '@rolldown/binding-wasm32-wasi': 1.0.2 + '@rolldown/binding-win32-arm64-msvc': 1.0.2 + '@rolldown/binding-win32-x64-msvc': 1.0.2 + + rosie-skills-darwin-arm64@0.6.4: + optional: true + + rosie-skills-freebsd-x64@0.6.4: + optional: true + + rosie-skills-linux-x64@0.6.4: + optional: true + + rosie-skills@0.6.4: + optionalDependencies: + rosie-skills-darwin-arm64: 0.6.4 + rosie-skills-freebsd-x64: 0.6.4 + rosie-skills-linux-x64: 0.6.4 + router@2.2.0: dependencies: debug: 4.4.3 @@ -2501,8 +3571,7 @@ snapshots: dependencies: commander: 6.2.1 - semver@7.8.0: - optional: true + semver@7.8.0: {} send@1.2.1: dependencies: @@ -2529,22 +3598,38 @@ snapshots: transitivePeerDependencies: - supports-color - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - setprototypeof@1.2.0: {} - sha.js@2.4.12: + sharp@0.34.5: dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.0 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 shebang-command@2.0.0: dependencies: @@ -2580,16 +3665,20 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - simple-concat@1.0.1: {} + simple-concat@1.0.1: + optional: true simple-get@4.0.1: dependencies: decompress-response: 6.0.0 once: 1.4.0 simple-concat: 1.0.1 + optional: true smol-toml@1.6.1: {} + source-map-js@1.2.1: {} + sprintf-js@1.1.3: {} sql.js@1.14.1: {} @@ -2599,6 +3688,7 @@ snapshots: string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 + optional: true strip-json-comments@2.0.1: optional: true @@ -2609,6 +3699,8 @@ snapshots: dependencies: '@tokenizer/token': 0.3.0 + supports-color@10.2.2: {} + tar-fs@2.1.4: dependencies: chownr: 1.1.4 @@ -2626,11 +3718,10 @@ snapshots: readable-stream: 3.6.2 optional: true - to-buffer@1.2.2: + tinyglobby@0.2.16: dependencies: - isarray: 2.0.5 - safe-buffer: 5.2.1 - typed-array-buffer: 1.0.3 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 toidentifier@1.0.1: {} @@ -2661,12 +3752,6 @@ snapshots: typebox@1.1.38: {} - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - uint8array-extras@1.5.0: {} ulidx@2.4.1: @@ -2675,6 +3760,12 @@ snapshots: undici-types@7.24.6: {} + undici@7.24.8: {} + + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + unpipe@1.0.0: {} util-deprecate@1.0.2: @@ -2684,22 +3775,50 @@ snapshots: vary@1.1.2: {} - web-streams-polyfill@3.3.3: {} - - which-typed-array@1.1.20: + vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.3)(yaml@2.9.0): dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.9 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.2 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 25.9.1 + esbuild: 0.27.3 + fsevents: 2.3.3 + yaml: 2.9.0 + + web-streams-polyfill@3.3.3: {} which@2.0.2: dependencies: isexe: 2.0.0 + workerd@1.20260526.1: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20260526.1 + '@cloudflare/workerd-darwin-arm64': 1.20260526.1 + '@cloudflare/workerd-linux-64': 1.20260526.1 + '@cloudflare/workerd-linux-arm64': 1.20260526.1 + '@cloudflare/workerd-windows-64': 1.20260526.1 + + wrangler@4.95.0: + dependencies: + '@cloudflare/kv-asset-handler': 0.5.0 + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260526.1) + blake3-wasm: 2.1.5 + esbuild: 0.27.3 + miniflare: 4.20260526.0 + path-to-regexp: 6.3.0 + rosie-skills: 0.6.4 + unenv: 2.0.0-rc.24 + workerd: 1.20260526.1 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + wrappy@1.0.2: {} ws@8.20.1: {} @@ -2708,6 +3827,19 @@ snapshots: yaml@2.9.0: {} + youch-core@0.3.3: + dependencies: + '@poppinss/exception': 1.2.3 + error-stack-parser-es: 1.0.5 + + youch@4.1.0-beta.10: + dependencies: + '@poppinss/colors': 4.1.6 + '@poppinss/dumper': 0.6.5 + '@speed-highlight/core': 1.2.15 + cookie: 1.1.1 + youch-core: 0.3.3 + zod-to-json-schema@3.25.2(zod@4.4.3): dependencies: zod: 4.4.3 diff --git a/e2e/scenarios/flue-instrumentation/scenario.cli.mjs b/e2e/scenarios/flue-instrumentation/scenario.cli.mjs new file mode 100644 index 000000000..bbbb961fd --- /dev/null +++ b/e2e/scenarios/flue-instrumentation/scenario.cli.mjs @@ -0,0 +1,4 @@ +const { runCliFlueInstrumentation, runMain } = + await import("./scenario.impl.mjs"); + +runMain(runCliFlueInstrumentation); diff --git a/e2e/scenarios/flue-instrumentation/scenario.impl.mjs b/e2e/scenarios/flue-instrumentation/scenario.impl.mjs index 7d38abebf..50388a547 100644 --- a/e2e/scenarios/flue-instrumentation/scenario.impl.mjs +++ b/e2e/scenarios/flue-instrumentation/scenario.impl.mjs @@ -1,239 +1,235 @@ -import { Type } from "@flue/runtime"; -import { configureProvider } from "@flue/runtime/app"; -import { - createFlueContext, - InMemorySessionStore, - resolveModel, -} from "@flue/runtime/internal"; -import { local } from "@flue/runtime/node"; -import { wrapFlueContext } from "braintrust"; -import { - runMain, - runOperation, - runTracedScenario, -} from "../../helpers/provider-runtime.mjs"; -import { - FLUE_MODEL, - FLUE_REASONING_MODEL, - ROOT_NAME, - SCENARIO_NAME, -} from "./constants.mjs"; - -const openAIBaseUrl = - process.env.OPENAI_BASE_URL ?? process.env.BRAINTRUST_E2E_MODEL_BASE_URL; -if (openAIBaseUrl) { - configureProvider("openai", { baseUrl: openAIBaseUrl }); -} +import { spawn } from "node:child_process"; +import { createServer } from "node:net"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { SCENARIO_NAME } from "./constants.mjs"; + +const flueCliPath = path.join( + path.dirname( + path.dirname(fileURLToPath(import.meta.resolve("@flue/cli/config"))), + ), + "bin", + "flue.mjs", +); +const braintrustHookNodeOption = "--import=braintrust/hook.mjs"; + +export async function runNodeFlueInstrumentationScenario(options) { + const env = scenarioEnv(options); + const outputDir = path.join(process.cwd(), ".flue-build", options.outputName); + await runFlueCli( + [ + "build", + "--target", + "node", + "--root", + process.cwd(), + "--output", + outputDir, + ], + env, + ); -const anthropicBaseUrl = process.env.ANTHROPIC_BASE_URL; -if (anthropicBaseUrl) { - configureProvider("anthropic", { - apiKey: process.env.ANTHROPIC_API_KEY ?? "test-key", - baseUrl: anthropicBaseUrl, + const port = await getFreePort(); + const child = spawn(process.execPath, [path.join(outputDir, "server.mjs")], { + cwd: process.cwd(), + env: { + ...env, + PORT: String(port), + }, + stdio: ["ignore", "pipe", "pipe"], }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (chunk) => { + stdout += chunk.toString(); + }); + child.stderr.on("data", (chunk) => { + stderr += chunk.toString(); + }); + + try { + await waitForFlueServer(child, () => ({ stderr, stdout })); + const workflowResponse = await fetch( + `http://127.0.0.1:${port}/workflows/instrumentation?wait=result`, + { + body: JSON.stringify({ scenario: SCENARIO_NAME }), + headers: { "content-type": "application/json" }, + method: "POST", + }, + ); + if (!workflowResponse.ok) { + throw new Error( + `workflow request failed with ${workflowResponse.status}\n${await workflowResponse.text()}`, + ); + } + await workflowResponse.arrayBuffer(); + + const flushResponse = await fetch( + `http://127.0.0.1:${port}/__braintrust_flush`, + { method: "POST" }, + ); + if (!flushResponse.ok) { + throw new Error( + `flush request failed with ${flushResponse.status}\n${await flushResponse.text()}`, + ); + } + } catch (error) { + throw new Error( + `${error instanceof Error ? error.message : String(error)}\nSTDOUT:\n${stdout}\nSTDERR:\n${stderr}`, + ); + } finally { + await stopChild(child); + } } -function flueModel() { - return process.env.FLUE_E2E_MODEL ?? FLUE_MODEL; +export async function runCliFlueInstrumentationScenario() { + await runFlueCli( + [ + "run", + "instrumentation", + "--target", + "node", + "--payload", + JSON.stringify({ scenario: SCENARIO_NAME }), + "--root", + process.cwd(), + ], + scenarioEnv({ autoHook: true, explicitObserve: false }), + ); + await new Promise((resolve) => setTimeout(resolve, 1_000)); } -function flueReasoningModel() { - return process.env.FLUE_E2E_REASONING_MODEL ?? FLUE_REASONING_MODEL; +export function runExplicitFlueInstrumentation() { + return runNodeFlueInstrumentationScenario({ + autoHook: false, + explicitObserve: true, + outputName: "explicit", + }); } -function fluePromptModel() { - return process.env.FLUE_E2E_PROMPT_MODEL ?? flueReasoningModel(); +export function runAutoFlueInstrumentation() { + return runNodeFlueInstrumentationScenario({ + autoHook: true, + explicitObserve: false, + outputName: "auto-hook", + }); } -function fluePromptThinkingLevel() { - return ( - process.env.FLUE_E2E_PROMPT_THINKING_LEVEL ?? flueReasoningThinkingLevel() - ); +export function runCliFlueInstrumentation() { + return runCliFlueInstrumentationScenario(); } -function flueReasoningThinkingLevel() { - return process.env.FLUE_E2E_REASONING_THINKING_LEVEL ?? "medium"; +function scenarioEnv({ autoHook, explicitObserve }) { + const env = { + ...process.env, + FLUE_E2E_EXPLICIT_OBSERVE: explicitObserve ? "1" : "0", + }; + if (!autoHook) { + return env; + } + return { + ...env, + NODE_OPTIONS: [env.NODE_OPTIONS, braintrustHookNodeOption] + .filter(Boolean) + .join(" "), + }; } -function makeContext() { - const sandbox = local({ cwd: process.cwd() }); - return createFlueContext({ - agentConfig: { - compaction: { - keepRecentTokens: 1, - reserveTokens: 64, - }, - model: resolveModel(flueModel()), - resolveModel, - roles: { - skillRunner: { - description: "Runs the Flue e2e skill without delegating.", - instructions: [ - "Never call the task tool.", - "Do not delegate e2e-flue-skill to another session.", - "If you need the skill body, read .agents/skills/e2e-flue-skill/SKILL.md yourself with the read tool.", - "Return the marker from the Arguments object exactly, with no other text.", - ].join(" "), - name: "skillRunner", - }, - }, - skills: {}, - systemPrompt: [ - "You are a deterministic Flue instrumentation test agent.", - "Follow user instructions exactly.", - "When asked for a marker, output only that marker and no extra text.", - "When running a local skill file, read it yourself and do not delegate it to a task.", - ].join(" "), - thinkingLevel: "off", - }, - createDefaultEnv: async () => - sandbox.createSessionEnv({ - cwd: process.cwd(), - id: "flue-e2e-default", - }), - defaultStore: new InMemorySessionStore(), - env: process.env, - id: "flue-e2e-instance", - payload: { - scenario: SCENARIO_NAME, - }, - runId: `flue-e2e-${process.env.BRAINTRUST_E2E_RUN_ID ?? "local"}`, +async function runFlueCli(args, env) { + await new Promise((resolve, reject) => { + const child = spawn(process.execPath, [flueCliPath, ...args], { + cwd: process.cwd(), + env, + stdio: ["ignore", "pipe", "pipe"], + }); + + let stdout = ""; + let stderr = ""; + + child.stdout.on("data", (chunk) => { + stdout += chunk.toString(); + }); + child.stderr.on("data", (chunk) => { + stderr += chunk.toString(); + }); + child.on("error", reject); + child.on("close", (code) => { + if (code === 0) { + resolve(); + return; + } + + reject( + new Error( + `flue ${args.join(" ")} failed with exit code ${code ?? 0}\nSTDOUT:\n${stdout}\nSTDERR:\n${stderr}`, + ), + ); + }); }); } -const lookupTool = { - description: - "Return a deterministic lookup result with an id needed by web_search.", - execute: async (args) => - JSON.stringify({ - id: "flue-session-2026", - query: args.query, - topic: "session instrumentation", - }), - name: "lookup", - parameters: Type.Object({ - query: Type.String(), - }), -}; - -const webSearchTool = { - description: - "Search a deterministic local web index. Requires the id returned by lookup.", - execute: async (args) => - JSON.stringify({ - lookupId: args.lookupId, - query: args.query, - results: [ - { - title: "Flue reasoning stream instrumentation", - url: "https://example.test/flue/reasoning-streams", - }, - ], - }), - name: "web_search", - parameters: Type.Object({ - lookupId: Type.String(), - query: Type.String(), - }), -}; - -const summarizeSourceTool = { - description: - "Summarize the selected deterministic source after web_search returns a URL.", - execute: async (args) => - JSON.stringify({ - summary: - "Flue emits reasoning, tool execution, and LLM turn events separately.", - url: args.url, - }), - name: "summarize_source", - parameters: Type.Object({ - url: Type.String(), - }), -}; - -export async function runFlueInstrumentationScenario({ wrapContext }) { - const rawContext = makeContext(); - const ctx = wrapContext ? wrapFlueContext(rawContext) : rawContext; - - await runTracedScenario({ - callback: async () => { - const harness = await ctx.init({ - compaction: { - keepRecentTokens: 1, - reserveTokens: 64, - }, - cwd: process.cwd(), - model: flueModel(), - sandbox: local({ cwd: process.cwd() }), - }); - const session = await harness.session("main"); - const skillSession = await harness.session("skill"); - const taskSession = await harness.session("task"); - - await runOperation("flue-prompt-operation", "prompt", async () => { - await session.prompt( - [ - "Complete this instrumented research flow.", - "Call exactly one tool per turn and wait for each tool result before choosing the next tool.", - 'Step 1: call lookup with query "flue instrumentation".', - 'Step 2: use the lookup result id as lookupId and call web_search with query "Braintrust Flue reasoning stream instrumentation".', - "Step 3: use the first web_search result url and call summarize_source.", - "After summarize_source returns, reply with exactly PROMPT_DONE and no other text.", - ].join(" "), - { - cacheRetention: "none", - maxTokens: 2048, - model: fluePromptModel(), - thinkingLevel: fluePromptThinkingLevel(), - tools: [lookupTool, webSearchTool, summarizeSourceTool], - }, - ); - }); - - await runOperation("flue-skill-operation", "skill", async () => { - await skillSession.skill("e2e-flue-skill", { - args: { marker: "SKILL_DONE" }, - cacheRetention: "none", - maxTokens: 128, - model: flueReasoningModel(), - role: "skillRunner", - thinkingLevel: "off", - }); - }); - - await runOperation("flue-task-operation", "task", async () => { - await taskSession.task( - "Reply with exactly TASK_DONE and no other text.", - { - cacheRetention: "none", - maxTokens: 32, - model: FLUE_MODEL, - thinkingLevel: "off", - }, - ); - }); - - await runOperation("flue-compact-operation", "compact", async () => { - await session.compact(); - }); - }, - flushCount: 2, - flushDelayMs: 100, - metadata: { - scenario: SCENARIO_NAME, - }, - projectNameBase: "e2e-flue-instrumentation", - rootName: ROOT_NAME, +async function getFreePort() { + const server = createServer(); + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(0, "127.0.0.1", resolve); }); + const address = server.address(); + await new Promise((resolve, reject) => { + server.close((error) => (error ? reject(error) : resolve())); + }); + if (!address || typeof address === "string") { + throw new Error("failed to allocate a local port for the Flue server"); + } + return address.port; } -export function runWrappedFlueInstrumentation() { - return runFlueInstrumentationScenario({ wrapContext: true }); +async function waitForFlueServer(child, output) { + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + reject(new Error("timed out waiting for Flue server startup")); + }, 30_000); + const onData = () => { + if (output().stdout.includes("Server listening")) { + cleanup(); + resolve(); + } + }; + const onExit = (code) => { + cleanup(); + reject(new Error(`Flue server exited before startup with code ${code}`)); + }; + const cleanup = () => { + clearTimeout(timeout); + child.stdout.off("data", onData); + child.stderr.off("data", onData); + child.off("exit", onExit); + }; + child.stdout.on("data", onData); + child.stderr.on("data", onData); + child.once("exit", onExit); + onData(); + }); } -export function runAutoFlueInstrumentation() { - return runFlueInstrumentationScenario({ wrapContext: false }); +async function stopChild(child) { + if (child.exitCode !== null || child.signalCode !== null) { + return; + } + await new Promise((resolve) => { + child.once("exit", resolve); + child.kill("SIGTERM"); + setTimeout(() => { + if (child.exitCode === null && child.signalCode === null) { + child.kill("SIGKILL"); + } + }, 5_000).unref(); + }); } -export { runMain }; +export function runMain(main) { + void main().catch((error) => { + console.error(error); + process.exitCode = 1; + }); +} diff --git a/e2e/scenarios/flue-instrumentation/scenario.mjs b/e2e/scenarios/flue-instrumentation/scenario.mjs index 015d18e6d..a9bd9d94e 100644 --- a/e2e/scenarios/flue-instrumentation/scenario.mjs +++ b/e2e/scenarios/flue-instrumentation/scenario.mjs @@ -1,3 +1,8 @@ -import { runAutoFlueInstrumentation, runMain } from "./scenario.impl.mjs"; +import "braintrust"; + +await new Promise((resolve) => setImmediate(resolve)); + +const { runAutoFlueInstrumentation, runMain } = + await import("./scenario.impl.mjs"); runMain(runAutoFlueInstrumentation); diff --git a/e2e/scenarios/flue-instrumentation/scenario.test.ts b/e2e/scenarios/flue-instrumentation/scenario.test.ts index e9b219bee..baa6e2b07 100644 --- a/e2e/scenarios/flue-instrumentation/scenario.test.ts +++ b/e2e/scenarios/flue-instrumentation/scenario.test.ts @@ -1,8 +1,9 @@ -import { describe } from "vitest"; +import { describe, test } from "vitest"; import { prepareScenarioDir, readInstalledPackageVersion, resolveScenarioDir, + withScenarioHarness, } from "../../helpers/scenario-harness"; import { defineFlueInstrumentationAssertions } from "./assertions"; @@ -15,37 +16,28 @@ const flueVersion = await readInstalledPackageVersion( "@flue/runtime", ); const TIMEOUT_MS = 120_000; -const wrappedVariantKey = "flue-v0-7-0-wrapped"; -const autoHookVariantKey = "flue-v0-7-0-auto-hook"; -const openAIAutoHookVariantKey = "flue-v0-7-0-openai-auto-hook"; +const variantKey = "flue-v0-8-0"; -const openAIPromptEnv = { - FLUE_E2E_PROMPT_MODEL: "openai/gpt-4o-mini", - FLUE_E2E_PROMPT_THINKING_LEVEL: "off", -}; - -describe(`flue ${flueVersion}`, () => { +describe.sequential(`flue ${flueVersion}`, () => { defineFlueInstrumentationAssertions({ - name: "wrapped instrumentation", + name: "explicit instrumentation", runScenario: async ({ runScenarioDir }) => { await runScenarioDir({ entry: "scenario.ts", runContext: { originalScenarioDir, - variantKey: wrappedVariantKey, + variantKey, }, scenarioDir, timeoutMs: TIMEOUT_MS, }); }, - snapshotName: "flue-v0-7-0-wrapped", + snapshotName: `${variantKey}-explicit`, testFileUrl: import.meta.url, timeoutMs: TIMEOUT_MS, }); defineFlueInstrumentationAssertions({ - expectedPromptProviderSpanName: "anthropic.messages.create", - expectFlueTurnSpans: false, name: "auto-hook instrumentation", runScenario: async ({ runNodeScenarioDir }) => { await runNodeScenarioDir({ @@ -53,37 +45,28 @@ describe(`flue ${flueVersion}`, () => { nodeArgs: ["--import", "braintrust/hook.mjs"], runContext: { originalScenarioDir, - variantKey: autoHookVariantKey, + variantKey, }, scenarioDir, timeoutMs: TIMEOUT_MS, }); }, - snapshotName: "flue-v0-7-0-auto-hook", + snapshotName: `${variantKey}-auto-hook`, testFileUrl: import.meta.url, timeoutMs: TIMEOUT_MS, }); - defineFlueInstrumentationAssertions({ - expectedPromptProviderSpanName: "openai.responses.create", - expectFlueTurnSpans: false, - expectThinking: false, - name: "auto-hook instrumentation with OpenAI prompt model", - runScenario: async ({ runNodeScenarioDir }) => { + test("runs through flue cli", { timeout: TIMEOUT_MS }, async () => { + await withScenarioHarness(async ({ runNodeScenarioDir }) => { await runNodeScenarioDir({ - entry: "scenario.mjs", - env: openAIPromptEnv, - nodeArgs: ["--import", "braintrust/hook.mjs"], + entry: "scenario.cli.mjs", runContext: { originalScenarioDir, - variantKey: openAIAutoHookVariantKey, + variantKey, }, scenarioDir, timeoutMs: TIMEOUT_MS, }); - }, - snapshotName: "flue-v0-7-0-openai-auto-hook", - testFileUrl: import.meta.url, - timeoutMs: TIMEOUT_MS, + }); }); }); diff --git a/e2e/scenarios/flue-instrumentation/scenario.ts b/e2e/scenarios/flue-instrumentation/scenario.ts index c5c71cef2..b96ed4882 100644 --- a/e2e/scenarios/flue-instrumentation/scenario.ts +++ b/e2e/scenarios/flue-instrumentation/scenario.ts @@ -1,3 +1,3 @@ -import { runMain, runWrappedFlueInstrumentation } from "./scenario.impl.mjs"; +import { runExplicitFlueInstrumentation, runMain } from "./scenario.impl.mjs"; -runMain(runWrappedFlueInstrumentation); +runMain(runExplicitFlueInstrumentation); diff --git a/js/src/auto-instrumentations/configs/all.ts b/js/src/auto-instrumentations/configs/all.ts index 4ec5830c4..fb245e41f 100644 --- a/js/src/auto-instrumentations/configs/all.ts +++ b/js/src/auto-instrumentations/configs/all.ts @@ -46,7 +46,6 @@ const defaultInstrumentationConfigGroups: readonly InstrumentationConfigGroup[] configs: claudeAgentSDKConfigs, }, { integrations: ["cursor", "cursorSDK"], configs: cursorSDKConfigs }, - { integrations: ["flue"], configs: flueConfigs }, { integrations: ["openAIAgents"], configs: openAIAgentsCoreConfigs, @@ -77,6 +76,10 @@ const defaultInstrumentationConfigGroups: readonly InstrumentationConfigGroup[] integrations: ["gitHubCopilot"], configs: gitHubCopilotConfigs, }, + { + integrations: ["flue"], + configs: flueConfigs, + }, // Note: `@mastra/core` is not listed here because its instrumentation // doesn't go through the AST `code-transformer` matcher — Mastra's // content-hashed chunks make `filePath`-based matching too brittle. diff --git a/js/src/auto-instrumentations/configs/flue.ts b/js/src/auto-instrumentations/configs/flue.ts index cba01deef..db2792c06 100644 --- a/js/src/auto-instrumentations/configs/flue.ts +++ b/js/src/auto-instrumentations/configs/flue.ts @@ -1,7 +1,7 @@ import type { InstrumentationConfig } from "@apm-js-collab/code-transformer"; import { flueChannels } from "../../instrumentation/plugins/flue-channels"; -const flueVersionRange = ">=0.7.0 <0.8.0"; +const flueVersionRange = ">=0.8.0"; export const flueConfigs: InstrumentationConfig[] = [ { @@ -16,17 +16,4 @@ export const flueConfigs: InstrumentationConfig[] = [ kind: "Sync", }, }, - { - channelName: flueChannels.openSession.channelName, - module: { - name: "@flue/runtime", - versionRange: flueVersionRange, - filePath: "dist/internal.mjs", - }, - functionQuery: { - className: "Harness", - methodName: "openSession", - kind: "Async", - }, - }, ]; diff --git a/js/src/exports.ts b/js/src/exports.ts index cf001b3e3..5712559b2 100644 --- a/js/src/exports.ts +++ b/js/src/exports.ts @@ -183,7 +183,6 @@ export type { MastraObservabilityExporter } from "./wrappers/mastra"; export { wrapClaudeAgentSDK } from "./wrappers/claude-agent-sdk/claude-agent-sdk"; export { wrapOpenAICodexSDK } from "./wrappers/openai-codex"; export { wrapCursorSDK } from "./wrappers/cursor-sdk"; -export { wrapFlueContext, wrapFlueSession } from "./wrappers/flue"; export { wrapGoogleGenAI } from "./wrappers/google-genai"; export { wrapGoogleADK } from "./wrappers/google-adk"; export { wrapGenkit } from "./wrappers/genkit"; @@ -299,4 +298,5 @@ export { // Auto-instrumentation configuration export { configureInstrumentation } from "./instrumentation"; +export { braintrustFlueObserver } from "./instrumentation"; export type { InstrumentationConfig } from "./instrumentation"; diff --git a/js/src/instrumentation/index.ts b/js/src/instrumentation/index.ts index ccce32b2c..d76798ef9 100644 --- a/js/src/instrumentation/index.ts +++ b/js/src/instrumentation/index.ts @@ -19,6 +19,7 @@ export { BraintrustPlugin } from "./braintrust-plugin"; export type { BraintrustPluginConfig } from "./braintrust-plugin"; export { OpenAIAgentsTraceProcessor } from "./plugins/openai-agents-trace-processor"; export type { OpenAIAgentsTraceProcessorOptions } from "./plugins/openai-agents-trace-processor"; +export { braintrustFlueObserver } from "./plugins/flue-plugin"; // Re-export core types for external instrumentation packages export type { diff --git a/js/src/instrumentation/plugins/flue-channels.ts b/js/src/instrumentation/plugins/flue-channels.ts index f90efc907..161903528 100644 --- a/js/src/instrumentation/plugins/flue-channels.ts +++ b/js/src/instrumentation/plugins/flue-channels.ts @@ -1,93 +1,9 @@ import { channel, defineChannels } from "../core/channel-definitions"; -import type { - FlueCallHandle, - FlueCallOptions, - FlueContext, - FlueEvent, - FlueHarness, - FlueOperationKind, - FluePromptResponse, - FlueSession, - FlueSkillOptions, - FlueTaskOptions, -} from "../../vendor-sdk-types/flue"; +import type { FlueObservableContext } from "../../vendor-sdk-types/flue"; export const flueChannels = defineChannels("@flue/runtime", { - createContext: channel<[unknown], FlueContext>({ + createContext: channel<[unknown], FlueObservableContext>({ channelName: "createFlueContext", kind: "sync-stream", }), - - openSession: channel< - [string | undefined, string | undefined, unknown], - FlueSession, - { - harness?: FlueHarness; - } - >({ - channelName: "Harness.openSession", - kind: "async", - }), - - contextEvent: channel< - [FlueEvent], - void, - { - captureTurnSpans?: boolean; - context?: FlueContext; - } - >({ - channelName: "context.event", - kind: "sync-stream", - }), - - prompt: channel< - [string, FlueCallOptions | undefined], - FluePromptResponse, - { - operation: FlueOperationKind; - session?: FlueSession; - } - >({ - channelName: "session.prompt", - kind: "async", - }), - - skill: channel< - [string, FlueSkillOptions | undefined], - FluePromptResponse, - { - operation: FlueOperationKind; - session?: FlueSession; - } - >({ - channelName: "session.skill", - kind: "async", - }), - - task: channel< - [string, FlueTaskOptions | undefined], - FluePromptResponse, - { - operation: FlueOperationKind; - session?: FlueSession; - } - >({ - channelName: "session.task", - kind: "async", - }), - - compact: channel< - [], - void, - { - operation: FlueOperationKind; - session?: FlueSession; - } - >({ - channelName: "session.compact", - kind: "async", - }), }); - -export type FlueThenableResult = FlueCallHandle | PromiseLike; diff --git a/js/src/instrumentation/plugins/flue-plugin.test.ts b/js/src/instrumentation/plugins/flue-plugin.test.ts index 23f6aaeba..9194e7b58 100644 --- a/js/src/instrumentation/plugins/flue-plugin.test.ts +++ b/js/src/instrumentation/plugins/flue-plugin.test.ts @@ -1,38 +1,28 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -const { - mockContextManager, - mockCurrentParentSpan, - mockCurrentSpanStore, - mockStartSpan, -} = vi.hoisted(() => ({ - mockContextManager: { - wrapSpanForStore: vi.fn((span: unknown) => span), - [Symbol.for("braintrust.currentSpanStore")]: undefined as unknown, - }, +const { mockCurrentParentSpan, mockStartSpan } = vi.hoisted(() => ({ mockCurrentParentSpan: { current: undefined as any }, - mockCurrentSpanStore: { - enterWith: vi.fn(), - getStore: vi.fn(), - run: vi.fn(), - }, mockStartSpan: vi.fn(), })); -mockContextManager[Symbol.for("braintrust.currentSpanStore")] = - mockCurrentSpanStore; +const { mockChannelHandlers, mockNewTracingChannel, mockTracingChannel } = + vi.hoisted(() => { + const handlers = new Set(); + const tracingChannel = { + subscribe: vi.fn((handler: any) => { + handlers.add(handler); + }), + unsubscribe: vi.fn((handler: any) => handlers.delete(handler)), + }; -vi.mock("../../isomorph", () => ({ - default: { - newTracingChannel: vi.fn(), - }, -})); + return { + mockChannelHandlers: handlers, + mockNewTracingChannel: vi.fn(() => tracingChannel), + mockTracingChannel: tracingChannel, + }; + }); vi.mock("../../logger", () => ({ - BRAINTRUST_CURRENT_SPAN_STORE: Symbol.for("braintrust.currentSpanStore"), - _internalGetGlobalState: () => ({ - contextManager: mockContextManager, - }), startSpan: (...args: unknown[]) => mockStartSpan(...args), withCurrent: (span: unknown, callback: () => unknown) => { const previous = mockCurrentParentSpan.current; @@ -45,17 +35,20 @@ vi.mock("../../logger", () => ({ }, })); -import iso from "../../isomorph"; -import { FluePlugin } from "./flue-plugin"; +vi.mock("../../isomorph", () => ({ + default: { + newTracingChannel: mockNewTracingChannel, + }, +})); + +import { FluePlugin, braintrustFlueObserver } from "./flue-plugin"; -const mockNewTracingChannel = iso.newTracingChannel as ReturnType; +type Subscriber = typeof braintrustFlueObserver; -describe("FluePlugin", () => { - let boundStoreTransformsByName: Map unknown>; - let handlersByName: Map; +describe("Flue observe instrumentation", () => { let spans: Array<{ + args: any; end: ReturnType; - export: ReturnType; log: ReturnType; name?: string; rootSpanId: string; @@ -64,27 +57,11 @@ describe("FluePlugin", () => { }>; beforeEach(() => { - boundStoreTransformsByName = new Map(); - handlersByName = new Map(); spans = []; mockCurrentParentSpan.current = undefined; - mockContextManager.wrapSpanForStore.mockClear(); - mockNewTracingChannel.mockImplementation((name: string) => ({ - start: { - bindStore: vi.fn((_store, transform) => { - boundStoreTransformsByName.set(name, transform); - }), - publish: vi.fn(), - unbindStore: vi.fn(), - }, - subscribe: vi.fn((handlers) => handlersByName.set(name, handlers)), - tracePromise: vi.fn((fn) => fn()), - traceSync: vi.fn((fn) => fn()), - unsubscribe: vi.fn(), - })); - mockStartSpan.mockImplementation((args: any) => { - const spanId = `span-${spans.length}`; + mockStartSpan.mockImplementation((args: any = {}) => { const parentSpan = mockCurrentParentSpan.current; + const spanId = `span-${spans.length}`; const rootSpanId = args.parentSpanIds?.rootSpanId ?? parentSpan?.rootSpanId ?? spanId; const spanParents = args.parentSpanIds?.spanId @@ -93,8 +70,8 @@ describe("FluePlugin", () => { ? [parentSpan.spanId] : []; const span = { + args, end: vi.fn(), - export: vi.fn(async () => `${args.name}-export-${spans.length}`), log: vi.fn(), name: args.name, rootSpanId, @@ -107,353 +84,216 @@ describe("FluePlugin", () => { }); afterEach(() => { + delete (globalThis as Record)[ + Symbol.for("braintrust.flue.auto-state") + ]; + delete (globalThis as Record)[ + Symbol.for("braintrust.flue.observe-bridge") + ]; + mockChannelHandlers.clear(); vi.clearAllMocks(); }); - it("subscribes to Flue channels", () => { - const plugin = new FluePlugin(); - - plugin.enable(); - - expect( - handlersByName.has("orchestrion:@flue/runtime:createFlueContext"), - ).toBe(true); - expect( - handlersByName.has("orchestrion:@flue/runtime:Harness.openSession"), - ).toBe(true); - expect(handlersByName.has("orchestrion:@flue/runtime:context.event")).toBe( - true, - ); - expect(handlersByName.has("orchestrion:@flue/runtime:session.prompt")).toBe( - true, - ); - expect(handlersByName.has("orchestrion:@flue/runtime:session.skill")).toBe( - true, - ); - expect(handlersByName.has("orchestrion:@flue/runtime:session.task")).toBe( - true, - ); - expect( - handlersByName.has("orchestrion:@flue/runtime:session.compact"), - ).toBe(true); - }); - - it("binds operation spans into the traced execution context", () => { - const plugin = new FluePlugin(); - plugin.enable(); - - const promptEvent = { - arguments: ["Use a tool", { model: "pi/test" }], - operation: "prompt", - session: { name: "main" }, - }; - const bindTransform = boundStoreTransformsByName.get( - "orchestrion:@flue/runtime:session.prompt", - ); - - const storeValue = bindTransform?.(promptEvent); - handlersByName - .get("orchestrion:@flue/runtime:session.prompt") - .start(promptEvent); - - const operationSpans = spans.filter( - (span) => span.name === "flue.session.prompt", - ); - expect(operationSpans).toHaveLength(1); - expect(mockContextManager.wrapSpanForStore).toHaveBeenCalledWith( - operationSpans[0], - ); - expect(storeValue).toBe(operationSpans[0]); - }); - - it("patches contexts and sessions returned by auto-instrumented entrypoints", async () => { - const plugin = new FluePlugin(); - plugin.enable(); - - const session = makeSession(); - const harness = { session: vi.fn(async () => session) }; - const ctx = { - init: vi.fn(async () => harness), - subscribeEvent: vi.fn(() => vi.fn()), - }; - handlersByName - .get("orchestrion:@flue/runtime:createFlueContext") - .end({ arguments: [{}], result: ctx }); - - await ctx.init({ model: "pi/test" }); - const wrappedSession = await harness.session(); - await wrappedSession.prompt("hello"); - - expect(ctx.subscribeEvent).toHaveBeenCalledTimes(1); - await expect(wrappedSession.prompt("hello again")).resolves.toEqual({ - text: "ok", + it("exports a subscriber that can be passed directly to Flue observe", () => { + const subscribers: Subscriber[] = []; + const unsubscribe = vi.fn(); + const observe = vi.fn((subscriber: Subscriber) => { + subscribers.push(subscriber); + return unsubscribe; }); - }); - it("does not create Flue turn spans when context events disable them", () => { - const plugin = new FluePlugin(); - plugin.enable(); + const unregister = observe(braintrustFlueObserver); - const contextHandlers = handlersByName.get( - "orchestrion:@flue/runtime:context.event", - ); - const promptHandlers = handlersByName.get( - "orchestrion:@flue/runtime:session.prompt", - ); - const promptEvent = { - arguments: ["Use a tool", { model: "pi/test" }], - operation: "prompt", - session: { name: "main" }, - }; + expect(observe).toHaveBeenCalledTimes(1); + expect(observe).toHaveBeenCalledWith(braintrustFlueObserver); + expect(subscribers).toHaveLength(1); - promptHandlers.start(promptEvent); - contextHandlers.start({ - arguments: [ - { - operationId: "op_1", - operationKind: "prompt", - session: "main", - type: "operation_start", - }, - ], - captureTurnSpans: false, - }); - contextHandlers.start({ - arguments: [{ operationId: "op_1", text: "Looking", type: "text_delta" }], - captureTurnSpans: false, - }); - contextHandlers.start({ - arguments: [ - { - args: { query: "braintrust" }, - operationId: "op_1", - toolCallId: "tool_1", - toolName: "lookup", - type: "tool_start", - }, - ], - captureTurnSpans: false, - }); - contextHandlers.start({ - arguments: [ - { - durationMs: 10, - isError: false, - model: "pi/test", - operationId: "op_1", - stopReason: "stop", - type: "turn", - usage: usage(), - }, - ], - captureTurnSpans: false, + subscribers[0]?.({ + runId: "run-1", + type: "run_start", + workflowName: "research", }); + expect(findSpan("workflow:research")).toBeDefined(); - expect(spans.filter((span) => span.name === "flue.turn")).toHaveLength(0); - expect(spans.find((span) => span.name === "tool: lookup")).toBeDefined(); + unregister(); + expect(unsubscribe).toHaveBeenCalledTimes(1); }); - it("correlates operation, turn, tool, task, and compaction spans", () => { - const plugin = new FluePlugin(); - plugin.enable(); - - const contextHandlers = handlersByName.get( - "orchestrion:@flue/runtime:context.event", - ); - const promptHandlers = handlersByName.get( - "orchestrion:@flue/runtime:session.prompt", + it("maps Flue 0.8 observe events into semantic Braintrust spans", () => { + const emit = observeEvents(); + const usage = flueUsage(); + const startedAt = "2026-05-27T05:12:31.000Z"; + + emit( + { + instanceId: "instance-1", + owner: { kind: "workflow", workflowName: "research" }, + payload: { topic: "flue" }, + runId: "run-1", + startedAt, + timestamp: startedAt, + type: "run_start", + workflowName: "research", + }, + { id: "ctx-1", runId: "run-1" }, ); - const promptEvent = { - arguments: [ - "Use a tool and delegate work", - { model: "pi/test", tools: [{ name: "lookup", parameters: {} }] }, - ], - operation: "prompt", - session: { name: "main" }, - }; - - promptHandlers.start(promptEvent); - contextHandlers.start({ - arguments: [ - { - eventIndex: 1, - operationId: "op_1", - operationKind: "prompt", - session: "main", - type: "operation_start", - }, - ], + emit({ + operationId: "op-1", + operationKind: "prompt", + runId: "run-1", + session: "main", + timestamp: "2026-05-27T05:12:32.000Z", + type: "operation_start", }); - contextHandlers.start({ - arguments: [{ operationId: "op_1", text: "Looking", type: "text_delta" }], - }); - contextHandlers.start({ - arguments: [{ operationId: "op_1", type: "thinking_start" }], - }); - contextHandlers.start({ - arguments: [ - { delta: "Think it ", operationId: "op_1", type: "thinking_delta" }, - ], - }); - contextHandlers.start({ - arguments: [ - { - content: "Think it through.", - operationId: "op_1", - type: "thinking_end", - }, - ], - }); - contextHandlers.start({ - arguments: [ - { - args: { query: "braintrust" }, - operationId: "op_1", - toolCallId: "tool_1", - toolName: "lookup", - type: "tool_start", - }, - ], + emit({ + api: "responses", + input: { + messages: [{ content: "Find Flue changes", role: "user" }], + systemPrompt: "Be precise", + tools: [{ name: "lookup", parameters: {} }], + }, + model: "claude-test", + operationId: "op-1", + provider: "anthropic", + purpose: "agent", + reasoning: "medium", + runId: "run-1", + timestamp: "2026-05-27T05:12:33.000Z", + turnId: "turn-1", + type: "turn_request", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 3, - isError: false, - operationId: "op_1", - result: "lookup ok", - toolCallId: "tool_1", - toolName: "lookup", - type: "tool_call", - }, - ], + emit({ + args: { query: "flue instrumentation" }, + operationId: "op-1", + runId: "run-1", + timestamp: "2026-05-27T05:12:34.000Z", + toolCallId: "tool-1", + toolName: "lookup", + turnId: "turn-1", + type: "tool_start", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 10, - isError: false, - model: "pi/test", - operationId: "op_1", - stopReason: "stop", - type: "turn", - usage: usage(), - }, - ], + emit({ + durationMs: 4, + isError: false, + operationId: "op-1", + result: { ok: true }, + runId: "run-1", + timestamp: "2026-05-27T05:12:35.000Z", + toolCallId: "tool-1", + toolName: "lookup", + turnId: "turn-1", + type: "tool_call", }); - contextHandlers.start({ - arguments: [ - { - operationId: "op_1", - parentSession: "main", - prompt: "child prompt", - taskId: "task_1", - type: "task_start", - }, - ], + emit({ + api: "responses", + durationMs: 12, + isError: false, + model: "claude-test", + operationId: "op-1", + output: { content: [{ text: "done", type: "text" }], role: "assistant" }, + provider: "anthropic", + purpose: "agent", + runId: "run-1", + stopReason: "stop", + timestamp: "2026-05-27T05:12:36.000Z", + turnId: "turn-1", + type: "turn", + usage, }); - contextHandlers.start({ - arguments: [ - { - taskId: "task_1", - text: "child done", - type: "text_delta", - }, - ], + emit({ + agent: "worker", + operationId: "op-1", + prompt: "Summarize the source", + runId: "run-1", + taskId: "task-1", + timestamp: "2026-05-27T05:12:37.000Z", + type: "task_start", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 8, - isError: false, - model: "pi/test", - stopReason: "stop", - taskId: "task_1", - type: "turn", - usage: usage(), - }, - ], + emit({ + durationMs: 8, + isError: false, + result: "task done", + runId: "run-1", + taskId: "task-1", + timestamp: "2026-05-27T05:12:38.000Z", + type: "task", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 20, - isError: false, - result: "task ok", - taskId: "task_1", - type: "task", - }, - ], + emit({ + estimatedTokens: 200, + operationId: "op-1", + reason: "manual", + runId: "run-1", + session: "main", + timestamp: "2026-05-27T05:12:39.000Z", + type: "compaction_start", }); - contextHandlers.start({ - arguments: [ - { - estimatedTokens: 100, - operationId: "op_1", - reason: "manual", - type: "compaction_start", - }, - ], + emit({ + durationMs: 6, + messagesAfter: 2, + messagesBefore: 8, + operationId: "op-1", + runId: "run-1", + session: "main", + timestamp: "2026-05-27T05:12:40.000Z", + type: "compaction", + usage, }); - contextHandlers.start({ - arguments: [ - { - durationMs: 4, - messagesAfter: 2, - messagesBefore: 8, - operationId: "op_1", - type: "compaction", - usage: usage(), - }, - ], + emit({ + durationMs: 50, + isError: false, + operationId: "op-1", + operationKind: "prompt", + result: "operation done", + runId: "run-1", + timestamp: "2026-05-27T05:12:41.000Z", + type: "operation", + usage, }); - contextHandlers.start({ - arguments: [ - { - durationMs: 50, - isError: false, - operationId: "op_1", - operationKind: "prompt", - type: "operation", - usage: usage(), - }, - ], + emit({ + durationMs: 60, + isError: false, + result: { final: true }, + runId: "run-1", + timestamp: "2026-05-27T05:12:42.000Z", + type: "run_end", }); - (promptEvent as any).result = { - model: { id: "pi/test" }, - text: "done", - usage: usage(), - }; - promptHandlers.asyncEnd(promptEvent); - const operationSpan = spans.find( - (span) => span.name === "flue.session.prompt", - ); - const turnSpan = spans.find((span) => span.name === "flue.turn"); - const toolSpan = spans.find((span) => span.name === "tool: lookup"); - const taskSpan = spans.find((span) => span.name === "flue.task"); - const childTurnSpan = spans.filter((span) => span.name === "flue.turn")[1]; - const compactionSpan = spans.find( - (span) => span.name === "flue.compaction", - ); - - expect(operationSpan?.log).toHaveBeenCalledWith( - expect.objectContaining({ - input: "Use a tool and delegate work", - metadata: expect.objectContaining({ - "flue.operation": "prompt", - "flue.tools_count": 1, + const workflowSpan = findSpan("workflow:research"); + const operationSpan = findSpan("flue.prompt"); + const turnSpan = findSpan("llm:claude-test"); + const toolSpan = findSpan("tool:lookup"); + const taskSpan = findSpan("task:worker"); + const compactionSpan = findSpan("compaction:manual"); + + expect(workflowSpan?.args).toMatchObject({ + event: { + input: { topic: "flue" }, + metadata: { + "flue.context_id": "ctx-1", + "flue.workflow_name": "research", provider: "flue", - }), - }), - ); + }, + }, + startTime: Date.parse(startedAt) / 1000, + }); + expect(operationSpan?.spanParents).toEqual([workflowSpan?.spanId]); expect(turnSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(toolSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(toolSpan?.spanParents).toEqual(turnSpan?.spanParents); - expect(toolSpan?.spanParents).not.toContain(turnSpan?.spanId); + expect(toolSpan?.spanParents).toEqual([turnSpan?.spanId]); expect(taskSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(childTurnSpan?.spanParents).toEqual([taskSpan?.spanId]); expect(compactionSpan?.spanParents).toEqual([operationSpan?.spanId]); + expect(turnSpan?.args.event).toMatchObject({ + input: [{ content: "Find Flue changes", role: "user" }], + metadata: { + "flue.api": "responses", + "flue.model": "claude-test", + "flue.provider": "anthropic", + "flue.system_prompt": "Be precise", + "flue.turn_purpose": "agent", + provider: "anthropic", + reasoning: "medium", + tools: [{ name: "lookup", parameters: {} }], + }, + }); expect(turnSpan?.log).toHaveBeenCalledWith( expect.objectContaining({ metrics: expect.objectContaining({ @@ -464,281 +304,206 @@ describe("FluePlugin", () => { prompt_tokens: 3, tokens: 10, }), - output: [ - expect.objectContaining({ - message: expect.objectContaining({ - content: "Looking", - reasoning: "Think it through.", - role: "assistant", - tool_calls: [ - { - function: { - arguments: JSON.stringify({ query: "braintrust" }), - name: "lookup", - }, - id: "tool_1", - type: "function", - }, - ], - }), - }), - ], + output: { + content: [{ text: "done", type: "text" }], + role: "assistant", + }, }), ); - expect(operationSpan?.end).toHaveBeenCalledTimes(1); - }); - - it("parents synthetic tool spans as siblings of active turn spans", () => { - const plugin = new FluePlugin(); - plugin.enable(); - - const contextHandlers = handlersByName.get( - "orchestrion:@flue/runtime:context.event", + expect(operationSpan?.log).toHaveBeenCalledWith( + expect.objectContaining({ + metadata: expect.objectContaining({ + "flue.usage": usage, + }), + metrics: { duration_ms: 50 }, + output: "operation done", + }), ); - const promptHandlers = handlersByName.get( - "orchestrion:@flue/runtime:session.prompt", + expect(operationSpan?.log).not.toHaveBeenCalledWith( + expect.objectContaining({ + metrics: expect.objectContaining({ prompt_tokens: 3 }), + }), ); - const promptEvent = { - arguments: ["Use a tool", { model: "pi/test" }], - operation: "prompt", - session: { name: "main" }, - }; - - promptHandlers.start(promptEvent); - contextHandlers.start({ - arguments: [ - { - operationId: "op_1", - operationKind: "prompt", - session: "main", - type: "operation_start", - }, - ], + expect(workflowSpan?.end).toHaveBeenCalledWith({ + endTime: Date.parse("2026-05-27T05:12:42.000Z") / 1000, }); - contextHandlers.start({ - arguments: [ - { operationId: "op_1", text: "Using a tool", type: "text_delta" }, - ], + }); + + it("creates a root operation span for direct or dispatched agent events", () => { + const emit = observeEvents(); + + emit({ + dispatchId: "dispatch-1", + instanceId: "instance-1", + operationId: "op-1", + operationKind: "prompt", + session: "main", + type: "operation_start", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 2, - isError: false, - operationId: "op_1", - result: "lookup ok", - toolCallId: "tool_1", - toolName: "lookup", - type: "tool_call", - }, - ], + + const operationSpan = findSpan("flue.prompt"); + expect(operationSpan?.spanParents).toEqual([]); + expect(operationSpan?.args.event.metadata).toMatchObject({ + "flue.dispatch_id": "dispatch-1", + "flue.instance_id": "instance-1", + "flue.operation": "prompt", + "flue.session": "main", + provider: "flue", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 10, - isError: false, - model: "pi/test", - operationId: "op_1", - stopReason: "toolUse", - type: "turn", - usage: usage(), - }, - ], + }); + + it("contains observer failures so Flue calls are not affected", () => { + const emit = observeEvents(); + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + mockStartSpan.mockImplementationOnce(() => { + throw new Error("start failed"); }); - const operationSpan = spans.find( - (span) => span.name === "flue.session.prompt", + expect(() => + emit({ + runId: "run-1", + type: "run_start", + workflowName: "broken", + }), + ).not.toThrow(); + expect(errorSpy).toHaveBeenCalledWith( + "Error in Flue observe instrumentation:", + expect.any(Error), ); - const turnSpan = spans.find((span) => span.name === "flue.turn"); - const toolSpan = spans.find((span) => span.name === "tool: lookup"); - - expect(turnSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(toolSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(toolSpan?.spanParents).toEqual(turnSpan?.spanParents); - expect(toolSpan?.spanParents).not.toContain(turnSpan?.spanId); }); - it("records tool calls when tool_start is the first turn event", () => { + it("subscribes transformed Flue contexts for auto instrumentation", () => { const plugin = new FluePlugin(); - plugin.enable(); + const contextSubscribers: Array<(event: unknown) => unknown> = []; + const unsubscribeContext = vi.fn(); + const context = { + id: "ctx-1", + runId: "run-1", + subscribeEvent: vi.fn((subscriber: (event: unknown) => unknown) => { + contextSubscribers.push(subscriber); + return unsubscribeContext; + }), + }; - const contextHandlers = handlersByName.get( - "orchestrion:@flue/runtime:context.event", - ); - const promptHandlers = handlersByName.get( - "orchestrion:@flue/runtime:session.prompt", + plugin.enable(); + expect(mockNewTracingChannel).toHaveBeenCalledWith( + "orchestrion:@flue/runtime:createFlueContext", ); - const promptEvent = { - arguments: ["Use a tool", { model: "pi/test" }], - operation: "prompt", - session: { name: "main" }, - }; + expect(mockTracingChannel.subscribe).toHaveBeenCalledTimes(1); - promptHandlers.start(promptEvent); - contextHandlers.start({ - arguments: [ - { - operationId: "op_1", - operationKind: "prompt", - session: "main", - type: "operation_start", - }, - ], - }); - contextHandlers.start({ - arguments: [ - { - args: { query: "braintrust" }, - operationId: "op_1", - toolCallId: "tool_1", - toolName: "lookup", - type: "tool_start", - }, - ], + emitCreateContextEnd(context); + + expect(context.subscribeEvent).toHaveBeenCalledTimes(1); + contextSubscribers[0]?.({ + runId: "run-1", + type: "run_start", + workflowName: "auto-research", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 2, - isError: false, - operationId: "op_1", - result: "lookup ok", - toolCallId: "tool_1", - toolName: "lookup", - type: "tool_call", - }, - ], + + expect( + findSpan("workflow:auto-research")?.args.event.metadata, + ).toMatchObject({ + "flue.context_id": "ctx-1", + "flue.context_run_id": "run-1", }); - contextHandlers.start({ - arguments: [ - { - durationMs: 10, - isError: false, - model: "pi/test", - operationId: "op_1", - stopReason: "toolUse", - type: "turn", - usage: usage(), - }, - ], + contextSubscribers[0]?.({ + durationMs: 1, + isError: false, + result: "done", + runId: "run-1", + type: "run_end", }); + expect(unsubscribeContext).toHaveBeenCalledTimes(1); - const operationSpan = spans.find( - (span) => span.name === "flue.session.prompt", - ); - const turnSpan = spans.find((span) => span.name === "flue.turn"); - const toolSpan = spans.find((span) => span.name === "tool: lookup"); + plugin.disable(); - expect(turnSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(toolSpan?.spanParents).toEqual([operationSpan?.spanId]); - expect(toolSpan?.spanParents).not.toContain(turnSpan?.spanId); - expect(turnSpan?.log).toHaveBeenCalledWith( - expect.objectContaining({ - output: [ - expect.objectContaining({ - message: expect.objectContaining({ - content: "", - role: "assistant", - tool_calls: [ - { - function: { - arguments: JSON.stringify({ query: "braintrust" }), - name: "lookup", - }, - id: "tool_1", - type: "function", - }, - ], - }), - }), - ], + expect(mockTracingChannel.unsubscribe).toHaveBeenCalledTimes(1); + expect(unsubscribeContext).toHaveBeenCalledTimes(1); + }); + + it("keeps auto instrumentation idempotent across plugin instances", () => { + const first = new FluePlugin(); + const second = new FluePlugin(); + const contextSubscribers: Array<(event: unknown) => unknown> = []; + const unsubscribeContext = vi.fn(); + const context = { + subscribeEvent: vi.fn((subscriber: (event: unknown) => unknown) => { + contextSubscribers.push(subscriber); + return unsubscribeContext; }), - ); + }; + + first.enable(); + second.enable(); + emitCreateContextEnd(context); + emitCreateContextEnd(context); + + expect(mockTracingChannel.subscribe).toHaveBeenCalledTimes(1); + expect(context.subscribeEvent).toHaveBeenCalledTimes(1); + + first.disable(); + expect(mockTracingChannel.unsubscribe).not.toHaveBeenCalled(); + expect(unsubscribeContext).not.toHaveBeenCalled(); + + second.disable(); + expect(mockTracingChannel.unsubscribe).toHaveBeenCalledTimes(1); + + contextSubscribers[0]?.({ + runId: "run-after-disable", + type: "run_start", + workflowName: "after-disable", + }); + expect(unsubscribeContext).toHaveBeenCalledTimes(1); + expect(findSpan("workflow:after-disable")).toBeUndefined(); }); - it("ends compaction spans from operation completion when no final compaction event arrives", () => { + it("unsubscribes direct Flue contexts on terminal operation events", () => { const plugin = new FluePlugin(); - plugin.enable(); - - const contextHandlers = handlersByName.get( - "orchestrion:@flue/runtime:context.event", - ); - const promptHandlers = handlersByName.get( - "orchestrion:@flue/runtime:session.prompt", - ); - const promptEvent = { - arguments: ["Trigger a compaction"], - operation: "prompt", - session: { name: "main" }, + const contextSubscribers: Array<(event: unknown) => unknown> = []; + const unsubscribeContext = vi.fn(); + const context = { + id: "direct-agent-1", + subscribeEvent: vi.fn((subscriber: (event: unknown) => unknown) => { + contextSubscribers.push(subscriber); + return unsubscribeContext; + }), }; - promptHandlers.start(promptEvent); - contextHandlers.start({ - arguments: [ - { - operationId: "op_1", - operationKind: "prompt", - session: "main", - type: "operation_start", - }, - ], - }); - contextHandlers.start({ - arguments: [ - { - estimatedTokens: 100, - operationId: "op_1", - reason: "manual", - session: "main", - type: "compaction_start", - }, - ], + plugin.enable(); + emitCreateContextEnd(context); + contextSubscribers[0]?.({ + durationMs: 2, + instanceId: "direct-agent-1", + isError: false, + operationId: "op-1", + operationKind: "prompt", + result: "done", + type: "operation", }); - (promptEvent as any).result = { text: "done" }; - promptHandlers.asyncEnd(promptEvent); - const operationSpan = spans.find( - (span) => span.name === "flue.session.prompt", - ); - const compactionSpan = spans.find( - (span) => span.name === "flue.compaction", - ); + expect(unsubscribeContext).toHaveBeenCalledTimes(1); + expect(findSpan("flue.prompt")).toBeDefined(); - expect(compactionSpan?.end).toHaveBeenCalledTimes(1); - expect(operationSpan?.end).toHaveBeenCalledTimes(1); - expect(compactionSpan?.log).toHaveBeenCalledWith( - expect.objectContaining({ - input: { - estimatedTokens: 100, - reason: "manual", - }, - metrics: expect.objectContaining({ - duration_ms: expect.any(Number), - }), - output: { completed: true }, - }), - ); + plugin.disable(); }); -}); -function makeSession() { - const promise = Promise.resolve({ text: "ok" }); - const handle = { - abort: vi.fn(), - signal: new AbortController().signal, - then: promise.then.bind(promise), - }; - return { - compact: vi.fn(async () => undefined), - name: "main", - prompt: vi.fn(() => handle), - skill: vi.fn(() => handle), - task: vi.fn(() => handle), - }; -} + function observeEvents() { + return (event: unknown, ctx?: unknown) => + braintrustFlueObserver(event, ctx); + } + + function emitCreateContextEnd(result: unknown) { + for (const handlers of mockChannelHandlers) { + handlers.end?.({ result }); + } + } + + function findSpan(name: string) { + return spans.find((span) => span.name === name); + } +}); -function usage() { +function flueUsage() { return { cacheRead: 1, cacheWrite: 2, diff --git a/js/src/instrumentation/plugins/flue-plugin.ts b/js/src/instrumentation/plugins/flue-plugin.ts index 7c4e55ce7..8778621a7 100644 --- a/js/src/instrumentation/plugins/flue-plugin.ts +++ b/js/src/instrumentation/plugins/flue-plugin.ts @@ -1,88 +1,65 @@ import { BasePlugin } from "../core"; import type { ChannelMessage } from "../core/channel-definitions"; import type { IsoChannelHandlers } from "../../isomorph"; -import { - _internalGetGlobalState, - BRAINTRUST_CURRENT_SPAN_STORE, - startSpan, - withCurrent, -} from "../../logger"; -import type { CurrentSpanStore, Span } from "../../logger"; -import { getCurrentUnixTimestamp, isObject } from "../../util"; +import { startSpan, withCurrent } from "../../logger"; +import type { Span, StartSpanArgs } from "../../logger"; import { SpanTypeAttribute } from "../../../util/index"; -import { - patchFlueContextInPlace, - patchFlueSessionInPlace, - subscribeFlueContextEvents, - wrapFlueHarness, -} from "../../wrappers/flue"; import { flueChannels } from "./flue-channels"; import type { FlueBaseEvent, - FlueCallOptions, FlueCompactionEvent, FlueCompactionStartEvent, + FlueContext, FlueEvent, + FlueObservableContext, FlueOperationEvent, FlueOperationKind, FlueOperationStartEvent, - FluePromptResponse, - FlueSession, - FlueSkillOptions, + FlueRunEndEvent, + FlueRunStartEvent, + FlueRuntimeOperationKind, FlueTaskEvent, - FlueTaskOptions, FlueTaskStartEvent, - FlueThinkingDeltaEvent, - FlueThinkingEndEvent, FlueToolCallEvent, FlueToolStartEvent, FlueTurnEvent, + FlueTurnRequestEvent, FlueUsage, } from "../../vendor-sdk-types/flue"; -type OperationState = { - metadata: Record; - operation: FlueOperationKind; - operationId?: string; - sessionName?: string; - span: Span; - startTime: number; +type FlueObserver = (event: unknown, ctx?: unknown) => void; + +type FlueAutoState = { + channel?: ReturnType; + contexts: WeakSet; + handlers?: IsoChannelHandlers< + ChannelMessage + >; + refCount: number; }; type SpanState = { - input?: unknown; metadata: Record; - operationState?: OperationState; span: Span; - startTime: number; }; -type TurnState = SpanState & { - finalThinking?: string; - hasThinking: boolean; - text: string[]; - thinking: string[]; - toolCalls: Array<{ - args?: unknown; - toolCallId?: string; - toolName?: string; - }>; +const FLUE_AUTO_STATE = Symbol.for("braintrust.flue.auto-state"); +const FLUE_OBSERVE_BRIDGE = Symbol.for("braintrust.flue.observe-bridge"); + +/** + * Braintrust's Flue observe subscriber. + * + * Pass this directly to @flue/runtime/app.observe: + * + * const unsubscribe = observe(braintrustFlueObserver); + */ +export const braintrustFlueObserver: FlueObserver = (event, ctx) => { + getObserveBridge().handle(event, ctx); }; export class FluePlugin extends BasePlugin { - private activeOperationsById = new Map(); - private activeOperationsByScope = new Map(); - private compactionsByScope = new Map(); - private pendingOperationsByKey = new Map(); - private tasksById = new Map(); - private toolsById = new Map(); - private turnsByScope = new Map(); - protected onEnable(): void { - this.subscribeToContextCreation(); - this.subscribeToSessionCreation(); - this.subscribeToContextEvents(); - this.subscribeToSessionOperations(); + this.unsubscribers.push(enableFlueAutoInstrumentation()); } protected onDisable(): void { @@ -90,582 +67,473 @@ export class FluePlugin extends BasePlugin { unsubscribe(); } this.unsubscribers = []; - this.activeOperationsById.clear(); - this.activeOperationsByScope.clear(); - this.compactionsByScope.clear(); - this.pendingOperationsByKey.clear(); - this.tasksById.clear(); - this.toolsById.clear(); - this.turnsByScope.clear(); } +} - private subscribeToContextCreation(): void { +function enableFlueAutoInstrumentation(): () => void { + const state = getAutoState(); + state.refCount += 1; + + if (!state.handlers) { const channel = flueChannels.createContext.tracingChannel(); const handlers: IsoChannelHandlers< ChannelMessage > = { end: (event) => { - const ctx = event.result; - if (!ctx) { - return; - } - subscribeFlueContextEvents(ctx, { captureTurnSpans: false }); - patchFlueContextInPlace(ctx); + subscribeToFlueContext(event.result, state); }, - error: () => {}, }; channel.subscribe(handlers); - this.unsubscribers.push(() => { - channel.unsubscribe(handlers); - }); + state.channel = channel; + state.handlers = handlers; } - private subscribeToSessionCreation(): void { - const channel = flueChannels.openSession.tracingChannel(); - const handlers: IsoChannelHandlers< - ChannelMessage - > = { - asyncEnd: (event) => { - if (event.result) { - patchFlueSessionInPlace( - event.result as FlueSession & Record, - ); - } - if (event.harness) { - wrapFlueHarness(event.harness); - } - }, - error: () => {}, - }; + let released = false; + return () => { + if (released) { + return; + } + released = true; + releaseAutoState(state); + }; +} - channel.subscribe(handlers); - this.unsubscribers.push(() => { - channel.unsubscribe(handlers); - }); +function getAutoState(): FlueAutoState { + const existing = Reflect.get(globalThis, FLUE_AUTO_STATE); + if (isAutoState(existing)) { + return existing; } + const state: FlueAutoState = { + contexts: new WeakSet(), + refCount: 0, + }; + Reflect.set(globalThis, FLUE_AUTO_STATE, state); + return state; +} - private subscribeToSessionOperations(): void { - this.subscribeToSessionOperation(flueChannels.prompt); - this.subscribeToSessionOperation(flueChannels.skill); - this.subscribeToSessionOperation(flueChannels.task); - this.subscribeToCompact(); +function getObserveBridge(): FlueObserveBridge { + const existing = Reflect.get(globalThis, FLUE_OBSERVE_BRIDGE); + if (isFlueObserveBridge(existing)) { + return existing; } + const bridge = new FlueObserveBridge(); + Reflect.set(globalThis, FLUE_OBSERVE_BRIDGE, bridge); + return bridge; +} - private subscribeToSessionOperation( - channel: - | typeof flueChannels.prompt - | typeof flueChannels.skill - | typeof flueChannels.task, - ): void { - const tracingChannel = channel.tracingChannel(); - const states = new WeakMap(); - const ensureState = ( - event: ChannelMessage, - ): OperationState => { - const existing = states.get(event); - if (existing) { - return existing; - } - const state = this.startOperationState({ - args: event.arguments, - moduleVersion: - typeof event.moduleVersion === "string" - ? event.moduleVersion - : undefined, - operation: event.operation, - session: event.session, - }); - states.set(event, state); - return state; - }; - const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart( - tracingChannel, - ensureState, - ); - const handlers: IsoChannelHandlers> = { - start: (event) => { - ensureState(event); - }, - asyncEnd: (event) => { - this.endOperationState(states.get(event), event.result); - states.delete(event); - }, - error: (event) => { - const state = states.get(event); - if (state && event.error) { - safeLog(state.span, { error: errorToString(event.error) }); - this.finishOperationState(state); - } - states.delete(event); - }, - }; - - tracingChannel.subscribe(handlers); - this.unsubscribers.push(() => { - unbindCurrentSpanStore?.(); - tracingChannel.unsubscribe(handlers); - }); - } +function isFlueObserveBridge(value: unknown): value is FlueObserveBridge { + return ( + isObjectLike(value) && + typeof Reflect.get(value, "handle") === "function" && + typeof Reflect.get(value, "reset") === "function" + ); +} - private subscribeToCompact(): void { - const tracingChannel = flueChannels.compact.tracingChannel(); - const states = new WeakMap(); - const ensureState = ( - event: ChannelMessage, - ): OperationState => { - const existing = states.get(event); - if (existing) { - return existing; - } - const state = this.startOperationState({ - args: [], - moduleVersion: - typeof event.moduleVersion === "string" - ? event.moduleVersion - : undefined, - operation: event.operation, - session: event.session, - }); - states.set(event, state); - return state; - }; - const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart( - tracingChannel, - ensureState, - ); - const handlers: IsoChannelHandlers< - ChannelMessage - > = { - start: (event) => { - ensureState(event); - }, - asyncEnd: (event) => { - this.endOperationState(states.get(event), undefined); - states.delete(event); - }, - error: (event) => { - const state = states.get(event); - if (state && event.error) { - safeLog(state.span, { error: errorToString(event.error) }); - this.finishOperationState(state); - } - states.delete(event); - }, - }; +function isAutoState(value: unknown): value is FlueAutoState { + return ( + isObjectLike(value) && + Reflect.get(value, "contexts") instanceof WeakSet && + typeof Reflect.get(value, "refCount") === "number" + ); +} - tracingChannel.subscribe(handlers); - this.unsubscribers.push(() => { - unbindCurrentSpanStore?.(); - tracingChannel.unsubscribe(handlers); - }); +function releaseAutoState(state: FlueAutoState): void { + state.refCount -= 1; + if (state.refCount > 0) { + return; } - private subscribeToContextEvents(): void { - const channel = flueChannels.contextEvent.tracingChannel(); - const handlers: IsoChannelHandlers< - ChannelMessage - > = { - start: (event) => { - const flueEvent = event.arguments[0]; - if (!flueEvent) { - return; - } - - try { - this.handleFlueEvent(flueEvent, { - captureTurnSpans: event.captureTurnSpans !== false, - }); - } catch (error) { - logInstrumentationError("Flue event", error); - } - }, - error: () => {}, - }; + try { + if (state.channel && state.handlers) { + state.channel.unsubscribe(state.handlers); + } + } finally { + Reflect.deleteProperty(globalThis, FLUE_AUTO_STATE); + } +} - channel.subscribe(handlers); - this.unsubscribers.push(() => { - channel.unsubscribe(handlers); - }); +function subscribeToFlueContext(value: unknown, state: FlueAutoState): void { + if (!isObservableFlueContext(value) || state.contexts.has(value)) { + return; } - private bindCurrentSpanStoreToOperationStart( - tracingChannel: { - start?: { - bindStore( - store: CurrentSpanStore, - transform: (event: TEvent) => T, - ): void; - unbindStore(store: CurrentSpanStore): boolean; - }; - }, - ensureState: (event: TEvent) => OperationState, - ): (() => void) | undefined { - const state = _internalGetGlobalState(); - const startChannel = tracingChannel.start; - const contextManager = state?.contextManager; - const currentSpanStore = contextManager - ? ( - contextManager as { - [BRAINTRUST_CURRENT_SPAN_STORE]?: CurrentSpanStore; - } - )[BRAINTRUST_CURRENT_SPAN_STORE] - : undefined; - - if (!currentSpanStore || !startChannel) { - return undefined; + const ctx = flueContextFromUnknown(value); + let released = false; + let unsubscribe: (() => void) | undefined; + const release = () => { + if (released) { + return; } + released = true; + try { + unsubscribe?.(); + } catch (error) { + logInstrumentationError("Flue context unsubscribe", error); + } + }; - startChannel.bindStore(currentSpanStore, (event: TEvent) => { - const operationState = ensureState(event); - return contextManager!.wrapSpanForStore(operationState.span); - }); + try { + unsubscribe = value.subscribeEvent((event) => { + if (state.refCount <= 0) { + release(); + return; + } - return () => { - startChannel.unbindStore(currentSpanStore); - }; + braintrustFlueObserver(event, ctx); + if (isAutoContextTerminalEvent(event, ctx)) { + release(); + } + }); + state.contexts.add(value); + } catch (error) { + logInstrumentationError("Flue context subscription", error); } +} - private startOperationState(args: { - args: ArrayLike; - moduleVersion?: string; - operation: FlueOperationKind; - session?: FlueSession; - }): OperationState { - const sessionName = getSessionName(args.session); - const metadata = { - ...extractOperationInputMetadata(args.operation, args.args), - ...extractSessionMetadata(args.session), - "flue.operation": args.operation, - provider: "flue", - ...(args.moduleVersion ? { "flue.version": args.moduleVersion } : {}), - }; - const span = startSpan({ - name: `flue.session.${args.operation}`, - spanAttributes: { type: SpanTypeAttribute.TASK }, - }); - const state: OperationState = { - metadata, - operation: args.operation, - sessionName, - span, - startTime: getCurrentUnixTimestamp(), - }; +function isAutoContextTerminalEvent( + event: unknown, + ctx: FlueContext | undefined, +): boolean { + if (!isObjectLike(event)) { + return false; + } + const type = Reflect.get(event, "type"); + if (type === "run_end") { + return true; + } + if (type !== "operation") { + return false; + } + return !ctx?.runId && typeof Reflect.get(event, "runId") !== "string"; +} - safeLog(span, { - input: extractOperationInput(args.operation, args.args), - metadata, - }); +function isObservableFlueContext( + value: unknown, +): value is FlueObservableContext { + return ( + isObjectLike(value) && + typeof Reflect.get(value, "subscribeEvent") === "function" + ); +} - this.pendingOperationQueue(operationKey(sessionName, args.operation)).push( - state, - ); - addOperationToScope( - this.activeOperationsByScope, - sessionName ?? "unknown", - state, - ); +function isFlueEvent(event: object): event is FlueEvent { + const type = Reflect.get(event, "type"); + return ( + type === "run_start" || + type === "run_end" || + type === "operation_start" || + type === "operation" || + type === "turn_request" || + type === "turn" || + type === "tool_start" || + type === "tool_call" || + type === "task_start" || + type === "task" || + type === "compaction_start" || + type === "compaction" + ); +} - return state; +function flueContextFromUnknown(ctx: unknown): FlueContext | undefined { + if (!isObjectLike(ctx)) { + return undefined; } + const id = Reflect.get(ctx, "id"); + const runId = Reflect.get(ctx, "runId"); + return { + ...(typeof id === "string" ? { id } : {}), + ...(typeof runId === "string" ? { runId } : {}), + }; +} - private endOperationState( - state: OperationState | undefined, - result: FluePromptResponse | undefined, - ): void { - if (!state) { +function isObjectLike(value: unknown): value is object { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +class FlueObserveBridge { + private compactionsByKey = new Map(); + private operationsById = new Map(); + private runsById = new Map(); + private seenEvents = new WeakSet(); + private tasksById = new Map(); + private toolsByKey = new Map(); + private turnsByKey = new Map(); + + handle(event: unknown, ctx: unknown): void { + if (!isObjectLike(event) || !isFlueEvent(event)) { return; } + if (this.seenEvents.has(event)) { + return; + } + this.seenEvents.add(event); - const metadata = { - ...state.metadata, - ...extractPromptResponseMetadata(result), - }; - const metrics = { - ...buildDurationMetrics(state.startTime), - ...metricsFromUsage(result?.usage), - }; - - safeLog(state.span, { - metadata, - metrics, - output: extractOperationOutput(result), - }); - this.finishCompactionsForOperation(state); - this.finishOperationState(state); + try { + this.handleEvent(event, flueContextFromUnknown(ctx)); + } catch (error) { + logInstrumentationError("Flue observe", error); + } } - private finishOperationState(state: OperationState): void { - removePendingOperation(this.pendingOperationsByKey, state); - if (state.operationId) { - this.activeOperationsById.delete(state.operationId); - } - removeScopedOperation(this.activeOperationsByScope, state); - state.span.end(); + reset(): void { + this.compactionsByKey.clear(); + this.operationsById.clear(); + this.runsById.clear(); + this.seenEvents = new WeakSet(); + this.tasksById.clear(); + this.toolsByKey.clear(); + this.turnsByKey.clear(); } - private handleFlueEvent( - event: FlueEvent, - options: { captureTurnSpans: boolean }, - ): void { + private handleEvent(event: FlueEvent, ctx: FlueContext | undefined): void { switch (event.type) { - case "operation_start": - this.handleOperationStart(event as FlueOperationStartEvent); - return; - case "operation": - this.handleOperation(event as FlueOperationEvent); + case "run_start": + this.handleRunStart(event, ctx); return; - case "text_delta": - if (!options.captureTurnSpans) { - return; - } - this.ensureTurnState(event).text.push( - typeof event.text === "string" ? event.text : "", - ); + case "run_end": + this.handleRunEnd(event); return; - case "thinking_start": - if (!options.captureTurnSpans) { - return; - } - this.handleThinkingStart(event); + case "operation_start": + this.handleOperationStart(event); return; - case "thinking_delta": - if (!options.captureTurnSpans) { - return; - } - this.handleThinkingDelta(event as FlueThinkingDeltaEvent); + case "operation": + this.handleOperation(event); return; - case "thinking_end": - if (!options.captureTurnSpans) { - return; - } - this.handleThinkingEnd(event as FlueThinkingEndEvent); + case "turn_request": + this.handleTurnRequest(event); return; case "turn": - if (!options.captureTurnSpans) { - return; - } - this.handleTurn(event as FlueTurnEvent); + this.handleTurn(event); return; case "tool_start": - this.handleToolStart(event as FlueToolStartEvent, options); + this.handleToolStart(event); return; case "tool_call": - this.handleToolCall(event as FlueToolCallEvent); + this.handleToolCall(event); return; case "task_start": - this.handleTaskStart(event as FlueTaskStartEvent); + this.handleTaskStart(event); return; case "task": - this.handleTask(event as FlueTaskEvent); + this.handleTask(event); return; case "compaction_start": - this.handleCompactionStart(event as FlueCompactionStartEvent); + this.handleCompactionStart(event); return; case "compaction": - this.handleCompaction(event as FlueCompactionEvent); + this.handleCompaction(event); return; default: return; } } - private handleOperationStart(event: FlueOperationStartEvent): void { - if (!isInstrumentedOperation(event.operationKind)) { + private handleRunStart( + event: FlueRunStartEvent, + ctx: FlueContext | undefined, + ): void { + if (!event.runId) { return; } - const state = this.takePendingOperationForEvent(event); + const workflowName = + event.workflowName ?? + event.owner?.workflowName ?? + (typeof ctx?.id === "string" ? ctx.id : "unknown"); + const metadata = { + ...extractEventMetadata(event, ctx), + ...(workflowName ? { "flue.workflow_name": workflowName } : {}), + provider: "flue", + }; + const span = startSpan({ + name: `workflow:${workflowName}`, + spanAttributes: { type: SpanTypeAttribute.TASK }, + startTime: eventTime(event.startedAt ?? event.timestamp), + event: { + input: event.payload, + metadata, + }, + }); + + this.runsById.set(event.runId, { metadata, span }); + } + + private handleRunEnd(event: FlueRunEndEvent): void { + const state = this.runsById.get(event.runId); if (!state) { return; } - state.operationId = event.operationId; - this.activeOperationsById.set(event.operationId, state); - addScopedOperation(this.activeOperationsByScope, event, state); - state.metadata = { - ...state.metadata, + safeLog(state.span, { + ...(event.isError ? { error: errorToString(event.error) } : {}), + metadata: { + ...state.metadata, + ...extractEventMetadata(event), + ...(event.isError !== undefined + ? { "flue.is_error": event.isError } + : {}), + }, + metrics: durationMetrics(event.durationMs), + output: event.result, + }); + safeEnd(state.span, eventTime(event.timestamp)); + this.runsById.delete(event.runId); + } + + private handleOperationStart(event: FlueOperationStartEvent): void { + if (!event.operationId || !isInstrumentedOperation(event.operationKind)) { + return; + } + + const metadata = { ...extractEventMetadata(event), - "flue.operation_id": event.operationId, + "flue.operation": event.operationKind, + provider: "flue", }; - safeLog(state.span, { metadata: state.metadata }); + const parent = this.parentSpanForEvent(event); + const span = startFlueSpan(parent, { + name: `flue.${event.operationKind}`, + spanAttributes: { type: SpanTypeAttribute.TASK }, + startTime: eventTime(event.timestamp), + event: { metadata }, + }); + + this.operationsById.set(event.operationId, { metadata, span }); } private handleOperation(event: FlueOperationEvent): void { - const state = event.operationId - ? this.activeOperationsById.get(event.operationId) - : undefined; - if (!state) { + if (!isInstrumentedOperation(event.operationKind)) { return; } + const state = + this.operationsById.get(event.operationId) ?? + this.startSyntheticOperation(event); const metadata = { ...state.metadata, ...extractEventMetadata(event), - ...(typeof event.durationMs === "number" - ? { "flue.duration_ms": event.durationMs } - : {}), ...(event.isError !== undefined ? { "flue.is_error": event.isError } : {}), + ...(event.usage ? { "flue.usage": event.usage } : {}), }; - const metrics = metricsFromUsage(event.usage); safeLog(state.span, { - ...(event.error ? { error: errorToString(event.error) } : {}), + ...(event.isError ? { error: errorToString(event.error) } : {}), metadata, - ...(Object.keys(metrics).length ? { metrics } : {}), + metrics: durationMetrics(event.durationMs), + output: event.result, }); + this.finishCompactionsForOperation(event); + safeEnd(state.span, eventTime(event.timestamp)); + this.operationsById.delete(event.operationId); } - private ensureTurnState(event: FlueBaseEvent): TurnState { - const scope = scopeKey(event); - const existing = this.turnsByScope.get(scope); - if (existing) { - return existing; + private handleTurnRequest(event: FlueTurnRequestEvent): void { + const key = turnKey(event); + if (!key) { + return; } - const parent = this.parentSpanForEvent(event); const metadata = { ...extractEventMetadata(event), - provider: "flue", + ...(event.api ? { "flue.api": event.api } : {}), + ...(event.model ? { model: event.model, "flue.model": event.model } : {}), + ...(event.provider ? { provider: event.provider } : { provider: "flue" }), + ...(event.provider ? { "flue.provider": event.provider } : {}), + ...(event.purpose ? { "flue.turn_purpose": event.purpose } : {}), + ...(event.reasoning ? { reasoning: event.reasoning } : {}), + ...(event.input?.systemPrompt + ? { "flue.system_prompt": event.input.systemPrompt } + : {}), + ...(event.input?.tools ? { tools: event.input.tools } : {}), }; + const parent = this.parentSpanForTurn(event); const span = startFlueSpan(parent, { - name: "flue.turn", + name: `llm:${event.model ?? event.purpose ?? "unknown"}`, spanAttributes: { type: SpanTypeAttribute.LLM }, + startTime: eventTime(event.timestamp), + event: { + input: event.input?.messages, + metadata, + }, }); - const state: TurnState = { - metadata, - span, - hasThinking: false, - startTime: getCurrentUnixTimestamp(), - text: [], - thinking: [], - toolCalls: [], - }; - safeLog(span, { metadata }); - this.turnsByScope.set(scope, state); - return state; + + this.turnsByKey.set(key, { metadata, span }); } private handleTurn(event: FlueTurnEvent): void { - const scope = scopeKey(event); - const state = this.ensureTurnState(event); - const text = state.text.join(""); - const reasoning = state.finalThinking ?? state.thinking.join(""); - const outputReasoning = - reasoning || - (state.hasThinking - ? "[reasoning stream present; content unavailable]" - : undefined); + const key = turnKey(event); + if (!key) { + return; + } + + const state = this.turnsByKey.get(key) ?? this.startSyntheticTurn(event); const metadata = { ...state.metadata, ...extractEventMetadata(event), + ...(event.api ? { "flue.api": event.api } : {}), ...(event.model ? { model: event.model, "flue.model": event.model } : {}), + ...(event.provider ? { provider: event.provider } : {}), + ...(event.provider ? { "flue.provider": event.provider } : {}), + ...(event.purpose ? { "flue.turn_purpose": event.purpose } : {}), ...(event.stopReason ? { "flue.stop_reason": event.stopReason } : {}), ...(event.isError !== undefined ? { "flue.is_error": event.isError } : {}), - provider: "flue", }; safeLog(state.span, { - ...(event.error ? { error: errorToString(event.error) } : {}), + ...(event.isError ? { error: errorToString(event.error) } : {}), metadata, metrics: { - ...durationMsMetrics(event.durationMs), + ...durationMetrics(event.durationMs), ...metricsFromUsage(event.usage), }, - output: toAssistantOutput( - text, - event.stopReason, - outputReasoning, - state.toolCalls, - ), + output: event.output, }); - state.span.end(); - this.turnsByScope.delete(scope); + safeEnd(state.span, eventTime(event.timestamp)); + this.turnsByKey.delete(key); } - private handleThinkingDelta(event: FlueThinkingDeltaEvent): void { - const delta = event.delta; - if (typeof delta !== "string" || !delta) { + private handleToolStart(event: FlueToolStartEvent): void { + if (!event.toolCallId) { return; } - const state = this.ensureTurnState(event); - state.hasThinking = true; - state.metadata["flue.thinking"] = true; - state.thinking.push(delta); - } - private handleThinkingStart(event: FlueBaseEvent): void { - const state = this.ensureTurnState(event); - state.hasThinking = true; - state.metadata["flue.thinking"] = true; - } - - private handleThinkingEnd(event: FlueThinkingEndEvent): void { - const state = this.ensureTurnState(event); - state.hasThinking = true; - state.metadata["flue.thinking"] = true; - if (typeof event.content === "string" && event.content) { - state.finalThinking = event.content; - } - } - - private handleToolStart( - event: FlueToolStartEvent, - options: { captureTurnSpans: boolean }, - ): void { - const toolCallId = event.toolCallId; - if (!toolCallId) { - return; - } - - const parent = this.parentSpanForEvent(event); - const scope = scopeKey(event); - let turnState = this.turnsByScope.get(scope); - if (!turnState && parent && options.captureTurnSpans) { - turnState = this.ensureTurnState(event); - } const metadata = { ...extractEventMetadata(event), ...(event.toolName ? { "flue.tool_name": event.toolName } : {}), - "flue.tool_call_id": toolCallId, + "flue.tool_call_id": event.toolCallId, provider: "flue", }; + const parent = this.parentSpanForEvent(event); const span = startFlueSpan(parent, { - name: `tool: ${event.toolName ?? "unknown"}`, + name: `tool:${event.toolName ?? "unknown"}`, spanAttributes: { type: SpanTypeAttribute.TOOL }, + startTime: eventTime(event.timestamp), + event: { + input: event.args, + metadata, + }, }); - if (turnState) { - turnState.toolCalls.push({ - args: event.args, - toolCallId, - toolName: event.toolName, - }); - } - safeLog(span, { - input: event.args, - metadata, - }); - this.toolsById.set(toolKey(event), { - metadata, - span, - startTime: getCurrentUnixTimestamp(), - }); + + this.toolsByKey.set(toolKey(event), { metadata, span }); } private handleToolCall(event: FlueToolCallEvent): void { + if (!event.toolCallId) { + return; + } + const key = toolKey(event); - const state = - this.toolsById.get(key) ?? - this.startSyntheticToolState(event, event.toolName ?? "unknown"); + const state = this.toolsByKey.get(key) ?? this.startSyntheticTool(event); const metadata = { ...state.metadata, ...extractEventMetadata(event), ...(event.toolName ? { "flue.tool_name": event.toolName } : {}), - ...(event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {}), + "flue.tool_call_id": event.toolCallId, ...(event.isError !== undefined ? { "flue.is_error": event.isError } : {}), @@ -674,35 +542,37 @@ export class FluePlugin extends BasePlugin { safeLog(state.span, { ...(event.isError ? { error: errorToString(event.result) } : {}), metadata, - metrics: durationMsMetrics(event.durationMs), + metrics: durationMetrics(event.durationMs), output: event.result, }); - state.span.end(); - this.toolsById.delete(key); + safeEnd(state.span, eventTime(event.timestamp)); + this.toolsByKey.delete(key); } private handleTaskStart(event: FlueTaskStartEvent): void { - const parent = this.parentSpanForEvent(event); + if (!event.taskId) { + return; + } + const metadata = { ...extractEventMetadata(event), - ...(event.role ? { "flue.role": event.role } : {}), + ...(event.agent ? { "flue.agent": event.agent } : {}), ...(event.cwd ? { "flue.cwd": event.cwd } : {}), "flue.task_id": event.taskId, provider: "flue", }; + const parent = this.parentSpanForEvent(event); const span = startFlueSpan(parent, { - name: "flue.task", + name: event.agent ? `task:${event.agent}` : "flue.task", spanAttributes: { type: SpanTypeAttribute.TASK }, + startTime: eventTime(event.timestamp), + event: { + input: event.prompt, + metadata, + }, }); - safeLog(span, { - input: event.prompt, - metadata, - }); - this.tasksById.set(event.taskId, { - metadata, - span, - startTime: getCurrentUnixTimestamp(), - }); + + this.tasksById.set(event.taskId, { metadata, span }); } private handleTask(event: FlueTaskEvent): void { @@ -716,266 +586,194 @@ export class FluePlugin extends BasePlugin { metadata: { ...state.metadata, ...extractEventMetadata(event), + ...(event.agent ? { "flue.agent": event.agent } : {}), ...(event.isError !== undefined ? { "flue.is_error": event.isError } : {}), }, - metrics: durationMsMetrics(event.durationMs), + metrics: durationMetrics(event.durationMs), output: event.result, }); - state.span.end(); + safeEnd(state.span, eventTime(event.timestamp)); this.tasksById.delete(event.taskId); } private handleCompactionStart(event: FlueCompactionStartEvent): void { - const operationState = this.operationStateForEvent(event); - const parent = operationState?.span ?? this.parentSpanForEvent(event); + const key = compactionKey(event); const metadata = { ...extractEventMetadata(event), ...(event.reason ? { "flue.compaction_reason": event.reason } : {}), provider: "flue", }; - const input = { - ...(typeof event.estimatedTokens === "number" - ? { estimatedTokens: event.estimatedTokens } - : {}), - ...(event.reason ? { reason: event.reason } : {}), - }; + const parent = this.parentSpanForEvent(event); const span = startFlueSpan(parent, { - name: "flue.compaction", + name: `compaction:${event.reason ?? "unknown"}`, spanAttributes: { type: SpanTypeAttribute.TASK }, + startTime: eventTime(event.timestamp), + event: { + input: { + ...(event.estimatedTokens !== undefined + ? { estimatedTokens: event.estimatedTokens } + : {}), + ...(event.reason ? { reason: event.reason } : {}), + }, + metadata, + }, }); - safeLog(span, { - input, - metadata, - }); - this.compactionsByScope.set(scopeKey(event), { - input, - metadata, - operationState, - span, - startTime: getCurrentUnixTimestamp(), - }); + + this.compactionsByKey.set(key, { metadata, span }); } private handleCompaction(event: FlueCompactionEvent): void { - const key = scopeKey(event); + const key = compactionKey(event); const state = - this.compactionsByScope.get(key) ?? this.findCompactionState(event); - if (!state) { - return; - } + this.compactionsByKey.get(key) ?? this.startSyntheticCompaction(event); + const metadata = { + ...state.metadata, + ...extractEventMetadata(event), + ...(event.usage ? { "flue.usage": event.usage } : {}), + }; safeLog(state.span, { - metadata: { - ...state.metadata, - ...extractEventMetadata(event), + metadata, + metrics: { + ...durationMetrics(event.durationMs), ...(typeof event.messagesBefore === "number" - ? { "flue.messages_before": event.messagesBefore } + ? { messages_before: event.messagesBefore } : {}), ...(typeof event.messagesAfter === "number" - ? { "flue.messages_after": event.messagesAfter } + ? { messages_after: event.messagesAfter } : {}), }, - metrics: { - ...durationMsMetrics(event.durationMs), - ...metricsFromUsage(event.usage), - }, output: { messagesAfter: event.messagesAfter, messagesBefore: event.messagesBefore, }, }); - state.span.end(); - this.deleteCompactionState(state); - } - - private findCompactionState(event: FlueBaseEvent): SpanState | undefined { - const operationState = this.operationStateForEvent(event); - for (const state of this.compactionsByScope.values()) { - if (operationState && state.operationState === operationState) { - return state; + safeEnd(state.span, eventTime(event.timestamp)); + this.compactionsByKey.delete(key); + } + + private parentSpanForTurn(event: FlueTurnRequestEvent): Span | undefined { + if ( + event.purpose === "compaction" || + event.purpose === "compaction_prefix" + ) { + const compaction = this.compactionsByKey.get(compactionKey(event)); + if (compaction) { + return compaction.span; } } - return undefined; + return this.parentSpanForEvent(event); } - private finishCompactionsForOperation(operationState: OperationState): void { - for (const state of [...this.compactionsByScope.values()]) { - if (state.operationState !== operationState) { - continue; + private parentSpanForEvent(event: FlueBaseEvent): Span | undefined { + const turn = turnKey(event); + if (turn) { + const turnState = this.turnsByKey.get(turn); + if (turnState) { + return turnState.span; } - safeLog(state.span, { - input: state.input, - metadata: state.metadata, - metrics: { - ...buildDurationMetrics(state.startTime), - }, - output: { completed: true }, - }); - state.span.end(); - this.deleteCompactionState(state); } - } - - private deleteCompactionState(state: SpanState): void { - for (const [key, candidate] of this.compactionsByScope) { - if (candidate !== state) { - continue; + if (event.taskId) { + const task = this.tasksById.get(event.taskId); + if (task) { + return task.span; + } + } + if (event.operationId) { + const operation = this.operationsById.get(event.operationId); + if (operation) { + return operation.span; } - this.compactionsByScope.delete(key); - return; } + if (event.runId) { + return this.runsById.get(event.runId)?.span; + } + return undefined; } - private startSyntheticToolState( - event: FlueToolCallEvent, - toolName: string, - ): SpanState { - const parent = this.parentSpanForEvent(event); + private startSyntheticOperation(event: FlueOperationEvent): SpanState { const metadata = { ...extractEventMetadata(event), - ...(event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {}), - "flue.tool_name": toolName, + "flue.operation": event.operationKind, provider: "flue", }; - const span = startFlueSpan(parent, { - name: `tool: ${toolName}`, - spanAttributes: { type: SpanTypeAttribute.TOOL }, + const span = startFlueSpan(this.parentSpanForEvent(event), { + name: `flue.${event.operationKind}`, + spanAttributes: { type: SpanTypeAttribute.TASK }, + startTime: eventTime(event.timestamp), + event: { metadata }, }); - safeLog(span, { metadata }); - return { metadata, span, startTime: getCurrentUnixTimestamp() }; + return { metadata, span }; } - private operationStateForEvent( - event: FlueBaseEvent, - ): OperationState | undefined { - if (event.operationId) { - const operation = - this.activeOperationsById.get(event.operationId) ?? - this.promotePendingOperationForEvent(event); - if (operation) { - return operation; - } - } - return ( - this.activeOperationForEventScope(event) ?? - this.pendingOperationForEventScope(event) - ); - } - - private parentSpanForEvent(event: FlueBaseEvent): Span | undefined { - if (event.operationId) { - const operation = this.operationStateForEvent(event); - if (operation) { - return operation.span; - } - } - if (event.taskId) { - return this.tasksById.get(event.taskId)?.span; - } - return this.operationStateForEvent(event)?.span; + private startSyntheticTurn(event: FlueTurnEvent): SpanState { + const metadata = { + ...extractEventMetadata(event), + ...(event.api ? { "flue.api": event.api } : {}), + ...(event.model ? { model: event.model, "flue.model": event.model } : {}), + ...(event.provider ? { provider: event.provider } : { provider: "flue" }), + ...(event.provider ? { "flue.provider": event.provider } : {}), + ...(event.purpose ? { "flue.turn_purpose": event.purpose } : {}), + }; + const span = startFlueSpan(this.parentSpanForEvent(event), { + name: `llm:${event.model ?? event.purpose ?? "unknown"}`, + spanAttributes: { type: SpanTypeAttribute.LLM }, + startTime: eventTime(event.timestamp), + event: { metadata }, + }); + return { metadata, span }; } - private promotePendingOperationForEvent( - event: FlueBaseEvent, - ): OperationState | undefined { - if (!event.operationId) { - return undefined; - } - - const scopePrefixes = operationScopePrefixes(event); - for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) { - if ( - !candidateQueue.length || - !operationKeyMatchesScopes(candidateKey, scopePrefixes) - ) { - continue; - } - - const state = candidateQueue.shift(); - if (!state) { - return undefined; - } - state.operationId = event.operationId; - this.activeOperationsById.set(event.operationId, state); - addScopedOperation(this.activeOperationsByScope, event, state); - state.metadata = { - ...state.metadata, - ...extractEventMetadata(event), - "flue.operation_id": event.operationId, - }; - safeLog(state.span, { metadata: state.metadata }); - return state; - } - - return undefined; + private startSyntheticTool(event: FlueToolCallEvent): SpanState { + const metadata = { + ...extractEventMetadata(event), + ...(event.toolName ? { "flue.tool_name": event.toolName } : {}), + "flue.tool_call_id": event.toolCallId, + provider: "flue", + }; + const span = startFlueSpan(this.parentSpanForEvent(event), { + name: `tool:${event.toolName ?? "unknown"}`, + spanAttributes: { type: SpanTypeAttribute.TOOL }, + startTime: eventTime(event.timestamp), + event: { metadata }, + }); + return { metadata, span }; } - private activeOperationForEventScope( - event: FlueBaseEvent, - ): OperationState | undefined { - for (const scope of operationScopeNames(event)) { - const operations = this.activeOperationsByScope.get(scope); - if (operations?.length) { - return operations[operations.length - 1]; - } - } - - return undefined; + private startSyntheticCompaction(event: FlueCompactionEvent): SpanState { + const metadata = { + ...extractEventMetadata(event), + provider: "flue", + }; + const span = startFlueSpan(this.parentSpanForEvent(event), { + name: "compaction:unknown", + spanAttributes: { type: SpanTypeAttribute.TASK }, + startTime: eventTime(event.timestamp), + event: { metadata }, + }); + return { metadata, span }; } - private pendingOperationForEventScope( - event: FlueBaseEvent, - ): OperationState | undefined { - const scopePrefixes = operationScopePrefixes(event); - for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) { - if ( - !candidateQueue.length || - !operationKeyMatchesScopes(candidateKey, scopePrefixes) - ) { + private finishCompactionsForOperation(event: FlueOperationEvent): void { + for (const [key, state] of this.compactionsByKey) { + if (!key.includes(`:${event.operationId}:`)) { continue; } - return candidateQueue[0]; - } - - return undefined; - } - - private takePendingOperationForEvent( - event: FlueOperationStartEvent, - ): OperationState | undefined { - const key = operationKey(event.session, event.operationKind); - const queue = this.pendingOperationsByKey.get(key); - if (queue?.length) { - return queue.shift(); - } - - for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) { - if ( - candidateKey.endsWith(`::${event.operationKind}`) && - candidateQueue.length - ) { - return candidateQueue.shift(); - } - } - - return undefined; - } - - private pendingOperationQueue(key: string): OperationState[] { - const existing = this.pendingOperationsByKey.get(key); - if (existing) { - return existing; + safeLog(state.span, { + metadata: state.metadata, + metrics: durationMetrics(event.durationMs), + output: { completed: true }, + }); + safeEnd(state.span, eventTime(event.timestamp)); + this.compactionsByKey.delete(key); } - const queue: OperationState[] = []; - this.pendingOperationsByKey.set(key, queue); - return queue; } } function isInstrumentedOperation( - operation: FlueOperationKind | "shell", + operation: FlueRuntimeOperationKind, ): operation is FlueOperationKind { return ( operation === "prompt" || @@ -985,116 +783,14 @@ function isInstrumentedOperation( ); } -function getSessionName(session: FlueSession | undefined): string | undefined { - return typeof session?.name === "string" ? session.name : undefined; -} - -function operationKey( - sessionName: string | undefined, - operation: FlueOperationKind | "shell", -): string { - return `${sessionName ?? "unknown"}::${operation}`; -} - -function operationScopePrefixes(event: FlueBaseEvent): Set { - const scopes = new Set(); - for (const scope of operationScopeNames(event)) { - scopes.add(`${scope}::`); - } - return scopes; -} - -function operationKeyMatchesScopes(key: string, scopes: Set): boolean { - for (const scope of scopes) { - if (key.startsWith(scope)) { - return true; - } - } - return false; -} - -function operationScopeNames(event: FlueBaseEvent): Set { - const scopes = new Set(); - if (event.session) { - scopes.add(event.session); - } - if (event.parentSession) { - scopes.add(event.parentSession); - } - if (!scopes.size) { - scopes.add("unknown"); - } - return scopes; -} - -function addScopedOperation( - operationsByScope: Map, +function extractEventMetadata( event: FlueBaseEvent, - state: OperationState, -): void { - for (const scope of operationScopeNames(event)) { - addOperationToScope(operationsByScope, scope, state); - } -} - -function addOperationToScope( - operationsByScope: Map, - scope: string, - state: OperationState, -): void { - const operations = operationsByScope.get(scope); - if (operations) { - if (!operations.includes(state)) { - operations.push(state); - } - } else { - operationsByScope.set(scope, [state]); - } -} - -function removeScopedOperation( - operationsByScope: Map, - state: OperationState, -): void { - for (const [scope, operations] of operationsByScope) { - const index = operations.indexOf(state); - if (index === -1) { - continue; - } - operations.splice(index, 1); - if (operations.length === 0) { - operationsByScope.delete(scope); - } - } -} - -function removePendingOperation( - pendingOperationsByKey: Map, - state: OperationState, -): void { - for (const [key, queue] of pendingOperationsByKey) { - const index = queue.indexOf(state); - if (index === -1) { - continue; - } - queue.splice(index, 1); - if (queue.length === 0) { - pendingOperationsByKey.delete(key); - } - return; - } -} - -function extractSessionMetadata( - session: FlueSession | undefined, + ctx?: FlueContext, ): Record { - const sessionName = getSessionName(session); - return sessionName ? { "flue.session": sessionName } : {}; -} - -function extractEventMetadata(event: FlueBaseEvent): Record { return { ...(event.runId ? { "flue.run_id": event.runId } : {}), + ...(event.instanceId ? { "flue.instance_id": event.instanceId } : {}), + ...(event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {}), ...(typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {}), @@ -1105,120 +801,14 @@ function extractEventMetadata(event: FlueBaseEvent): Record { ...(event.harness ? { "flue.harness": event.harness } : {}), ...(event.taskId ? { "flue.task_id": event.taskId } : {}), ...(event.operationId ? { "flue.operation_id": event.operationId } : {}), - }; -} - -function extractOperationInput( - operation: FlueOperationKind, - args: ArrayLike, -): unknown { - switch (operation) { - case "prompt": - case "task": - return args[0]; - case "skill": - return { - args: getOptionObject(args[1])?.args, - name: args[0], - }; - case "compact": - return undefined; - } -} - -function extractOperationInputMetadata( - operation: FlueOperationKind, - args: ArrayLike, -): Record { - const options = getOptionObject(args[1]); - return { - ...(operation === "skill" && typeof args[0] === "string" - ? { "flue.skill_name": args[0] } - : {}), - ...(options?.model - ? { model: options.model, "flue.model": options.model } - : {}), - ...(options?.role ? { "flue.role": options.role } : {}), - ...(options?.thinkingLevel - ? { "flue.thinking_level": options.thinkingLevel } - : {}), - ...(typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {}), - ...(Array.isArray(options?.tools) - ? { - "flue.tools_count": options.tools.length, - tools: summarizeTools(options.tools), - } - : {}), - ...(Array.isArray(options?.images) - ? { "flue.images_count": options.images.length } - : {}), - ...(options?.result || options?.schema - ? { "flue.result_schema": true } + ...(event.turnId ? { "flue.turn_id": event.turnId } : {}), + ...(typeof ctx?.id === "string" ? { "flue.context_id": ctx.id } : {}), + ...(typeof ctx?.runId === "string" + ? { "flue.context_run_id": ctx.runId } : {}), }; } -function getOptionObject( - value: unknown, -): (FlueCallOptions & FlueSkillOptions & FlueTaskOptions) | undefined { - return isObject(value) - ? (value as FlueCallOptions & FlueSkillOptions & FlueTaskOptions) - : undefined; -} - -function summarizeTools(tools: unknown[]): unknown[] { - return tools.flatMap((tool) => { - if (!isObject(tool)) { - return []; - } - const name = typeof tool.name === "string" ? tool.name : undefined; - if (!name) { - return []; - } - return [ - { - function: { - description: - typeof tool.description === "string" ? tool.description : undefined, - name, - parameters: tool.parameters, - }, - type: "function", - }, - ]; - }); -} - -function extractPromptResponseMetadata( - result: FluePromptResponse | undefined, -): Record { - const modelId = - result?.model && typeof result.model.id === "string" - ? result.model.id - : undefined; - return modelId - ? { - model: modelId, - "flue.model": modelId, - } - : {}; -} - -function extractOperationOutput( - result: FluePromptResponse | undefined, -): unknown { - if (!result) { - return undefined; - } - if ("data" in result) { - return result.data; - } - if ("text" in result) { - return result.text; - } - return result; -} - function metricsFromUsage( usage: FlueUsage | undefined, ): Record { @@ -1242,79 +832,37 @@ function metricsFromUsage( }; } -function buildDurationMetrics(startTime: number): Record { - return { - duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1000), - }; -} - -function durationMsMetrics(durationMs: unknown): Record { +function durationMetrics(durationMs: unknown): Record { return typeof durationMs === "number" ? { duration_ms: durationMs } : {}; } -function scopeKey(event: FlueBaseEvent): string { - if (event.operationId) { - return `operation:${event.operationId}`; - } - if (event.taskId) { - return `task:${event.taskId}`; - } - if (event.session) { - return `session:${event.session}`; +function eventTime(value: unknown): number | undefined { + if (typeof value !== "string") { + return undefined; } - return "flue:unknown"; + const timestamp = Date.parse(value); + return Number.isFinite(timestamp) ? timestamp / 1000 : undefined; } -function toolKey( - event: Pick & { - toolCallId?: string; - }, -): string { - return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`; +function turnKey(event: FlueBaseEvent): string | undefined { + return event.turnId; } -function toAssistantOutput( - text: string, - finishReason: string | undefined, - reasoning?: string, - toolCalls?: Array<{ - args?: unknown; - toolCallId?: string; - toolName?: string; - }>, -): unknown { +function toolKey(event: FlueBaseEvent & { toolCallId?: string }): string { + return `${event.turnId ?? event.operationId ?? event.taskId ?? event.runId ?? "unknown"}:${event.toolCallId ?? "unknown"}`; +} + +function compactionKey(event: FlueBaseEvent): string { return [ - { - finish_reason: finishReason ?? "stop", - index: 0, - message: { - content: text, - ...(reasoning ? { reasoning } : {}), - role: "assistant", - ...(toolCalls?.length - ? { - tool_calls: toolCalls.map((toolCall) => ({ - function: { - arguments: - toolCall.args === undefined - ? "{}" - : JSON.stringify(toolCall.args), - name: toolCall.toolName ?? "unknown", - }, - ...(toolCall.toolCallId ? { id: toolCall.toolCallId } : {}), - type: "function", - })), - } - : {}), - }, - }, - ]; + event.instanceId ?? "", + event.runId ?? "", + event.session ?? "", + event.operationId ?? "", + event.taskId ?? "", + ].join(":"); } -function startFlueSpan( - parent: Span | undefined, - args: Parameters[0], -): Span { +function startFlueSpan(parent: Span | undefined, args: StartSpanArgs): Span { return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args); } @@ -1326,6 +874,14 @@ function safeLog(span: Span, event: Parameters[0]): void { } } +function safeEnd(span: Span, endTime: number | undefined): void { + try { + span.end(endTime === undefined ? undefined : { endTime }); + } catch (error) { + logInstrumentationError("Flue span end", error); + } +} + function errorToString(error: unknown): string { if (error instanceof Error) { return error.message; diff --git a/js/src/vendor-sdk-types/flue.ts b/js/src/vendor-sdk-types/flue.ts index bc1174ebf..6c08fe7fe 100644 --- a/js/src/vendor-sdk-types/flue.ts +++ b/js/src/vendor-sdk-types/flue.ts @@ -1,11 +1,13 @@ /** - * Vendored types for @flue/runtime used by Braintrust instrumentation. + * Vendored types for @flue/runtime 0.8 observe-based instrumentation. * * Keep this surface intentionally narrow. These types are not exported to SDK - * users and should only cover fields we read, wrap, or log. + * users and should only cover fields we read, correlate, or log. */ export type FlueOperationKind = "prompt" | "skill" | "task" | "compact"; +export type FlueRuntimeOperationKind = FlueOperationKind | "shell"; +export type FlueTurnPurpose = "agent" | "compaction" | "compaction_prefix"; export interface FlueUsage { input?: number; @@ -22,83 +24,11 @@ export interface FlueUsage { }; } -export interface FluePromptResponse { - text?: string; - data?: unknown; - result?: unknown; - usage?: FlueUsage; - model?: { - id?: string; - }; - [key: string]: unknown; -} - -export interface FlueCallOptions { - model?: string; - role?: string; - thinkingLevel?: string; - tools?: FlueToolDef[]; - signal?: AbortSignal; - images?: unknown[]; - result?: unknown; - schema?: unknown; - [key: string]: unknown; -} - -export interface FlueSkillOptions extends FlueCallOptions { - args?: Record; -} - -export interface FlueTaskOptions extends FlueCallOptions { - cwd?: string; -} - -export interface FlueToolDef { - name?: string; - description?: string; - parameters?: unknown; - execute?: unknown; - [key: string]: unknown; -} - -export interface FlueCallHandle extends PromiseLike { - readonly signal: AbortSignal; - abort(reason?: unknown): void; -} - -export interface FlueSession { - readonly name?: string; - prompt(text: string, options?: FlueCallOptions): FlueCallHandle; - skill(name: string, options?: FlueSkillOptions): FlueCallHandle; - task(text: string, options?: FlueTaskOptions): FlueCallHandle; - compact(): Promise; - [key: string | symbol]: unknown; -} - -export interface FlueSessions { - get(name?: string, options?: unknown): Promise; - create(name?: string, options?: unknown): Promise; - [key: string | symbol]: unknown; -} - -export interface FlueHarness { - readonly name?: string; - session(name?: string, options?: unknown): Promise; - readonly sessions?: FlueSessions; - [key: string | symbol]: unknown; -} - -export interface FlueContext { - readonly id?: string; - readonly runId?: string; - init(options: unknown): Promise; - subscribeEvent?: (callback: (event: FlueEvent) => void) => () => void; - [key: string | symbol]: unknown; -} - export interface FlueBaseEvent { type?: string; runId?: string; + instanceId?: string; + dispatchId?: string; eventIndex?: number; timestamp?: string; session?: string; @@ -106,19 +36,42 @@ export interface FlueBaseEvent { taskId?: string; harness?: string; operationId?: string; + turnId?: string; [key: string]: unknown; } +export interface FlueRunStartEvent extends FlueBaseEvent { + type: "run_start"; + runId: string; + startedAt?: string; + workflowName?: string; + owner?: { + kind?: string; + workflowName?: string; + instanceId?: string; + }; + payload?: unknown; +} + +export interface FlueRunEndEvent extends FlueBaseEvent { + type: "run_end"; + runId: string; + result?: unknown; + isError?: boolean; + error?: unknown; + durationMs?: number; +} + export interface FlueOperationStartEvent extends FlueBaseEvent { type: "operation_start"; operationId: string; - operationKind: FlueOperationKind | "shell"; + operationKind: FlueRuntimeOperationKind; } export interface FlueOperationEvent extends FlueBaseEvent { type: "operation"; operationId: string; - operationKind: FlueOperationKind | "shell"; + operationKind: FlueRuntimeOperationKind; durationMs?: number; isError?: boolean; error?: unknown; @@ -126,37 +79,47 @@ export interface FlueOperationEvent extends FlueBaseEvent { usage?: FlueUsage; } +export interface FlueTurnRequestEvent extends FlueBaseEvent { + type: "turn_request"; + turnId: string; + purpose: FlueTurnPurpose; + model?: string; + provider?: string; + api?: string; + input?: { + systemPrompt?: string; + messages?: unknown[]; + tools?: unknown[]; + }; + reasoning?: string; +} + export interface FlueTurnEvent extends FlueBaseEvent { type: "turn"; + turnId: string; + purpose?: FlueTurnPurpose; durationMs?: number; model?: string; + provider?: string; + api?: string; + output?: unknown; usage?: FlueUsage; stopReason?: string; isError?: boolean; error?: unknown; } -export interface FlueThinkingDeltaEvent extends FlueBaseEvent { - type: "thinking_delta"; - delta?: string; -} - -export interface FlueThinkingEndEvent extends FlueBaseEvent { - type: "thinking_end"; - content?: string; -} - export interface FlueToolStartEvent extends FlueBaseEvent { type: "tool_start"; toolName?: string; - toolCallId?: string; + toolCallId: string; args?: unknown; } export interface FlueToolCallEvent extends FlueBaseEvent { type: "tool_call"; toolName?: string; - toolCallId?: string; + toolCallId: string; isError?: boolean; result?: unknown; durationMs?: number; @@ -166,13 +129,14 @@ export interface FlueTaskStartEvent extends FlueBaseEvent { type: "task_start"; taskId: string; prompt?: string; - role?: string; + agent?: string; cwd?: string; } export interface FlueTaskEvent extends FlueBaseEvent { type: "task"; taskId: string; + agent?: string; isError?: boolean; result?: unknown; durationMs?: number; @@ -192,16 +156,26 @@ export interface FlueCompactionEvent extends FlueBaseEvent { usage?: FlueUsage; } +export interface FlueContext { + readonly id?: string; + readonly runId?: string; + [key: string | symbol]: unknown; +} + +export interface FlueObservableContext extends FlueContext { + subscribeEvent(callback: (event: unknown) => unknown): () => void; +} + export type FlueEvent = + | FlueRunStartEvent + | FlueRunEndEvent | FlueOperationStartEvent | FlueOperationEvent - | FlueThinkingDeltaEvent - | FlueThinkingEndEvent + | FlueTurnRequestEvent | FlueTurnEvent | FlueToolStartEvent | FlueToolCallEvent | FlueTaskStartEvent | FlueTaskEvent | FlueCompactionStartEvent - | FlueCompactionEvent - | FlueBaseEvent; + | FlueCompactionEvent; diff --git a/js/src/wrappers/flue.test.ts b/js/src/wrappers/flue.test.ts deleted file mode 100644 index a654a30eb..000000000 --- a/js/src/wrappers/flue.test.ts +++ /dev/null @@ -1,277 +0,0 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; - -const { - publishAsyncEnd, - publishAsyncStart, - publishEnd, - publishStart, - tracePromise, - traceSync, -} = vi.hoisted(() => ({ - publishAsyncEnd: vi.fn(), - publishAsyncStart: vi.fn(), - publishEnd: vi.fn(), - publishStart: vi.fn(), - tracePromise: vi.fn( - async (fn: () => Promise, context: Record) => { - publishStart(context); - try { - const result = fn(); - publishEnd(context); - const resolved = await result; - context.result = resolved; - publishAsyncStart(context); - publishAsyncEnd(context); - return resolved; - } catch (error) { - throw error; - } - }, - ), - traceSync: vi.fn((fn: () => unknown) => fn()), -})); - -vi.mock("../isomorph", () => ({ - default: { - newTracingChannel: vi.fn(() => ({ - asyncEnd: { - publish: publishAsyncEnd, - }, - asyncStart: { - publish: publishAsyncStart, - }, - end: { - publish: publishEnd, - }, - error: { - publish: vi.fn(), - }, - start: { - publish: publishStart, - runStores: vi.fn((context, fn) => { - publishStart(context); - return fn(); - }), - }, - subscribe: vi.fn(), - tracePromise, - traceSync, - unsubscribe: vi.fn(), - })), - }, -})); - -import { - subscribeFlueContextEvents, - wrapFlueContext, - wrapFlueSession, -} from "./flue"; - -describe("wrapFlueSession", () => { - afterEach(() => { - vi.clearAllMocks(); - }); - - it("patches prompt, skill, task, and compact", async () => { - const session = makeSession(); - - wrapFlueSession(session); - - await session.prompt("hello", { model: "pi/test" }); - await session.skill("review", { args: { id: 1 } }); - await session.task("delegate this"); - await session.compact(); - - expect(publishStart).toHaveBeenCalledTimes(4); - expect(publishEnd).toHaveBeenCalledTimes(4); - expect(publishAsyncStart).toHaveBeenCalledTimes(4); - expect(publishAsyncEnd).toHaveBeenCalledTimes(4); - expect(session.originals.prompt).toHaveBeenCalledWith("hello", { - model: "pi/test", - }); - expect(session.originals.skill).toHaveBeenCalledWith("review", { - args: { id: 1 }, - }); - expect(session.originals.task).toHaveBeenCalledWith( - "delegate this", - undefined, - ); - expect(session.originals.compact).toHaveBeenCalledTimes(1); - }); - - it("preserves CallHandle signal, abort, and then behavior", async () => { - const controller = new AbortController(); - const abort = vi.fn(); - const promise = Promise.resolve({ text: "ok" }); - const handle = { - abort, - signal: controller.signal, - then: promise.then.bind(promise), - }; - const session = { - compact: vi.fn(async () => undefined), - name: "main", - prompt: vi.fn(() => handle), - skill: vi.fn(() => handle), - task: vi.fn(() => handle), - }; - - wrapFlueSession(session); - const returned = session.prompt("hello"); - - expect(returned).not.toBe(handle); - expect(returned.signal).toBe(controller.signal); - returned.abort("stop"); - await expect(returned).resolves.toEqual({ text: "ok" }); - expect(abort).toHaveBeenCalledWith("stop"); - }); - - it("is idempotent", async () => { - const session = makeSession(); - - wrapFlueSession(session); - wrapFlueSession(session); - await session.prompt("hello"); - - expect(publishStart).toHaveBeenCalledTimes(1); - expect(session.originals.prompt).toHaveBeenCalledTimes(1); - }); -}); - -describe("wrapFlueContext", () => { - afterEach(() => { - vi.clearAllMocks(); - }); - - it("subscribes to context events and wraps harness sessions returned by init", async () => { - let subscriber: ((event: unknown) => void) | undefined; - const session = makeSession(); - const harness = { - name: "default", - session: vi.fn(async () => session), - sessions: { - create: vi.fn(async () => session), - get: vi.fn(async () => session), - }, - }; - const ctx = { - init: vi.fn(async () => harness), - subscribeEvent: vi.fn((callback) => { - subscriber = callback; - return vi.fn(); - }), - }; - - wrapFlueContext(ctx); - const returnedHarness = await ctx.init({ model: "pi/test" }); - const returnedSession = await returnedHarness.session("main"); - - await returnedSession.prompt("hello"); - subscriber?.({ operationId: "op_1", type: "operation_start" }); - - expect(ctx.subscribeEvent).toHaveBeenCalledTimes(1); - expect(publishStart).toHaveBeenCalledTimes(1); - expect(traceSync).toHaveBeenCalledWith( - expect.any(Function), - expect.objectContaining({ - arguments: [{ operationId: "op_1", type: "operation_start" }], - captureTurnSpans: true, - context: ctx, - }), - ); - }); - - it("can subscribe to context events without Flue turn spans", () => { - let subscriber: ((event: unknown) => void) | undefined; - const ctx = { - init: vi.fn(), - subscribeEvent: vi.fn((callback) => { - subscriber = callback; - return vi.fn(); - }), - }; - - subscribeFlueContextEvents(ctx, { captureTurnSpans: false }); - subscriber?.({ operationId: "op_1", type: "turn" }); - - expect(traceSync).toHaveBeenCalledWith( - expect.any(Function), - expect.objectContaining({ - arguments: [{ operationId: "op_1", type: "turn" }], - captureTurnSpans: false, - context: ctx, - }), - ); - }); - - it("upgrades an existing context event subscription for manual wrapping", () => { - let subscriber: ((event: unknown) => void) | undefined; - const firstUnsubscribe = vi.fn(); - const secondUnsubscribe = vi.fn(); - const ctx = { - init: vi.fn(async () => ({ session: vi.fn() })), - subscribeEvent: vi - .fn() - .mockImplementationOnce((callback) => { - subscriber = callback; - return firstUnsubscribe; - }) - .mockImplementationOnce((callback) => { - subscriber = callback; - return secondUnsubscribe; - }), - }; - - subscribeFlueContextEvents(ctx, { captureTurnSpans: false }); - wrapFlueContext(ctx); - subscriber?.({ operationId: "op_1", type: "turn" }); - - expect(firstUnsubscribe).toHaveBeenCalledTimes(1); - expect(ctx.subscribeEvent).toHaveBeenCalledTimes(2); - expect(traceSync).toHaveBeenLastCalledWith( - expect.any(Function), - expect.objectContaining({ - captureTurnSpans: true, - }), - ); - }); - - it("returns invalid contexts unchanged", () => { - const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); - const value = { session: vi.fn() }; - - expect(wrapFlueContext(value)).toBe(value); - expect(warnSpy).toHaveBeenCalledWith( - "Unsupported Flue context. Not wrapping.", - ); - - warnSpy.mockRestore(); - }); -}); - -function makeHandle(result: unknown = { text: "ok" }) { - const promise = Promise.resolve(result); - return { - abort: vi.fn(), - signal: new AbortController().signal, - then: promise.then.bind(promise), - }; -} - -function makeSession() { - const originals = { - compact: vi.fn(async () => undefined), - prompt: vi.fn(() => makeHandle({ text: "prompt ok" })), - skill: vi.fn(() => makeHandle({ text: "skill ok" })), - task: vi.fn(() => makeHandle({ text: "task ok" })), - }; - - return { - compact: originals.compact, - name: "main", - originals, - prompt: originals.prompt, - skill: originals.skill, - task: originals.task, - }; -} diff --git a/js/src/wrappers/flue.ts b/js/src/wrappers/flue.ts deleted file mode 100644 index 98852f3ad..000000000 --- a/js/src/wrappers/flue.ts +++ /dev/null @@ -1,432 +0,0 @@ -import { flueChannels } from "../instrumentation/plugins/flue-channels"; -import type { IsoTracingChannelCollection } from "../isomorph"; -import type { - FlueCallHandle, - FlueCallOptions, - FlueContext, - FlueEvent, - FlueHarness, - FlueSession, - FlueSkillOptions, - FlueTaskOptions, -} from "../vendor-sdk-types/flue"; - -const WRAPPED_FLUE_CONTEXT = Symbol.for("braintrust.flue.wrapped-context"); -const WRAPPED_FLUE_HARNESS = Symbol.for("braintrust.flue.wrapped-harness"); -const WRAPPED_FLUE_SESSION = Symbol.for("braintrust.flue.wrapped-session"); -const SUBSCRIBED_FLUE_CONTEXT_EVENTS = Symbol.for( - "braintrust.flue.subscribed-context-events", -); - -type FlueContextRecord = FlueContext & Record; -type FlueHarnessRecord = FlueHarness & Record; -type FlueSessionRecord = FlueSession & Record; -type FlueContextEventSubscription = { - captureTurnSpans: boolean; - unsubscribe: () => void; -}; -type FlueContextEventSubscriptionOptions = { - captureTurnSpans?: boolean; -}; -type FlueOperationChannel = - | typeof flueChannels.prompt - | typeof flueChannels.skill - | typeof flueChannels.task - | typeof flueChannels.compact; -type FlueOperationTraceContext = Parameters< - FlueOperationChannel["tracePromise"] ->[1] & - Partial<{ - error: Error; - result: TResult; - }>; - -/** - * Wraps a Flue context with Braintrust tracing. Context wrapping subscribes to - * Flue's event stream and patches ctx.init() so returned harness sessions emit - * operation diagnostics-channel events. - */ -export function wrapFlueContext(ctx: T): T { - if (!isPlausibleFlueContext(ctx)) { - // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage. - console.warn("Unsupported Flue context. Not wrapping."); - return ctx; - } - - const context = ctx as FlueContextRecord; - subscribeFlueContextEvents(context, { captureTurnSpans: true }); - return patchFlueContextInPlace(context) as T; -} - -export function patchFlueContextInPlace(ctx: T): T { - const context = ctx as FlueContextRecord; - if (context[WRAPPED_FLUE_CONTEXT]) { - return ctx; - } - - const originalInit = context.init.bind(context); - try { - Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, { - configurable: false, - enumerable: false, - value: true, - }); - Object.defineProperty(context, "init", { - configurable: true, - value: async function wrappedFlueInit(options: unknown) { - const harness = await originalInit(options); - return wrapFlueHarness(harness); - }, - writable: true, - }); - } catch { - // Frozen/sealed contexts cannot be patched. Leave user behavior untouched. - } - - return ctx; -} - -/** - * Wraps a Flue session with Braintrust tracing. Direct session wrapping traces - * top-level prompt/skill/task/compact calls. Event-derived child spans require - * context instrumentation through wrapFlueContext() or auto-instrumentation. - */ -export function wrapFlueSession(session: T): T { - if (!isPlausibleFlueSession(session)) { - // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage. - console.warn("Unsupported Flue session. Not wrapping."); - return session; - } - - return patchFlueSessionInPlace(session as FlueSessionRecord) as T; -} - -export function subscribeFlueContextEvents( - ctx: FlueContext, - options: FlueContextEventSubscriptionOptions = {}, -): (() => void) | undefined { - if ( - !ctx || - typeof ctx !== "object" || - typeof ctx.subscribeEvent !== "function" - ) { - return undefined; - } - - const context = ctx as FlueContextRecord; - const captureTurnSpans = options.captureTurnSpans ?? true; - const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS] as - | FlueContextEventSubscription - | undefined; - if (existingSubscription) { - if (existingSubscription.captureTurnSpans || !captureTurnSpans) { - return undefined; - } - try { - existingSubscription.unsubscribe(); - } catch { - // Ignore failed cleanup and attempt to replace the subscription below. - } - } - - try { - const unsubscribe = ctx.subscribeEvent((event: FlueEvent) => { - flueChannels.contextEvent.traceSync(() => undefined, { - arguments: [event], - captureTurnSpans, - context: ctx, - } as never); - }); - if (existingSubscription) { - existingSubscription.captureTurnSpans = captureTurnSpans; - existingSubscription.unsubscribe = unsubscribe; - } else { - Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, { - configurable: false, - enumerable: false, - value: { - captureTurnSpans, - unsubscribe, - } satisfies FlueContextEventSubscription, - }); - } - return unsubscribe; - } catch { - return undefined; - } -} - -export function wrapFlueHarness(harness: T): T { - if (!isPlausibleFlueHarness(harness)) { - return harness; - } - - const target = harness as FlueHarnessRecord; - if (target[WRAPPED_FLUE_HARNESS]) { - return harness; - } - - const originalSession = target.session.bind(target); - try { - Object.defineProperty(target, WRAPPED_FLUE_HARNESS, { - configurable: false, - enumerable: false, - value: true, - }); - Object.defineProperty(target, "session", { - configurable: true, - value: async function wrappedFlueHarnessSession( - name?: string, - options?: unknown, - ) { - const session = await originalSession(name, options); - return patchFlueSessionInPlace(session as FlueSessionRecord); - }, - writable: true, - }); - - const sessions = target.sessions; - if (sessions && typeof sessions === "object") { - patchFlueSessionFactory(sessions, "get"); - patchFlueSessionFactory(sessions, "create"); - } - } catch { - // Frozen/sealed harnesses cannot be patched. Leave user behavior untouched. - } - - return harness; -} - -export function patchFlueSessionInPlace( - session: T, -): T { - if (session[WRAPPED_FLUE_SESSION]) { - return session; - } - - try { - Object.defineProperty(session, WRAPPED_FLUE_SESSION, { - configurable: false, - enumerable: false, - value: true, - }); - - patchCallHandleMethod(session, "prompt", flueChannels.prompt); - patchCallHandleMethod(session, "skill", flueChannels.skill); - patchCallHandleMethod(session, "task", flueChannels.task); - patchCompact(session); - } catch { - // Frozen/sealed sessions cannot be patched. Leave user behavior untouched. - } - - return session; -} - -function patchFlueSessionFactory( - sessions: Record, - method: "get" | "create", -): void { - const original = sessions[method]; - if (typeof original !== "function") { - return; - } - - const bound = original.bind(sessions); - Object.defineProperty(sessions, method, { - configurable: true, - value: async function wrappedFlueSessionFactory( - name?: string, - options?: unknown, - ) { - const session = await bound(name, options); - return patchFlueSessionInPlace(session as FlueSessionRecord); - }, - writable: true, - }); -} - -function patchCallHandleMethod( - session: FlueSessionRecord, - method: "prompt" | "skill" | "task", - channel: - | typeof flueChannels.prompt - | typeof flueChannels.skill - | typeof flueChannels.task, -): void { - const original = session[method]; - if (typeof original !== "function") { - return; - } - - const bound = original.bind(session); - Object.defineProperty(session, method, { - configurable: true, - value( - input: string, - options?: FlueCallOptions | FlueSkillOptions | FlueTaskOptions, - ) { - const args = [input, options] as never; - const { originalResult, traced } = traceFlueOperation(channel, { - context: { - arguments: args, - operation: method, - session, - } as never, - run: () => bound(input, options), - }); - return preserveCallHandle(originalResult, traced); - }, - writable: true, - }); -} - -function patchCompact(session: FlueSessionRecord): void { - const original = session.compact; - if (typeof original !== "function") { - return; - } - - const bound = original.bind(session); - Object.defineProperty(session, "compact", { - configurable: true, - value() { - const context = { - arguments: [], - operation: "compact", - session, - } as Parameters[1]; - return flueChannels.compact.tracePromise(() => bound(), context); - }, - writable: true, - }); -} - -function traceFlueOperation( - channel: FlueOperationChannel, - args: { - context: Parameters[1]; - run: () => PromiseLike; - }, -): { - originalResult: PromiseLike; - traced: Promise; -} { - const tracingChannel = - channel.tracingChannel() as IsoTracingChannelCollection< - FlueOperationTraceContext - >; - const context = args.context as FlueOperationTraceContext; - - let originalResult: PromiseLike; - let traced: Promise; - const run = () => { - try { - originalResult = args.run(); - tracingChannel.end?.publish(context); - } catch (error) { - context.error = normalizeError(error); - tracingChannel.error?.publish(context); - tracingChannel.end?.publish(context); - throw error; - } - - traced = Promise.resolve(originalResult).then( - (result) => { - context.result = result; - tracingChannel.asyncStart?.publish(context); - tracingChannel.asyncEnd?.publish(context); - return result; - }, - (error: unknown) => { - context.error = normalizeError(error); - tracingChannel.error?.publish(context); - tracingChannel.asyncStart?.publish(context); - tracingChannel.asyncEnd?.publish(context); - throw error; - }, - ); - }; - - if (tracingChannel.start?.runStores) { - tracingChannel.start.runStores(context, run); - } else { - tracingChannel.start?.publish(context); - run(); - } - - return { originalResult: originalResult!, traced: traced! }; -} - -function normalizeError(error: unknown): Error { - return error instanceof Error ? error : new Error(String(error)); -} - -function preserveCallHandle( - originalHandle: unknown, - traced: PromiseLike, -): PromiseLike { - if (!isFlueCallHandle(originalHandle)) { - return traced; - } - - const handle = originalHandle; - const wrapped = { - get signal() { - return handle.signal; - }, - abort(reason?: unknown) { - return handle.abort(reason); - }, - then( - onfulfilled?: - | ((value: unknown) => TResult1 | PromiseLike) - | undefined - | null, - onrejected?: - | ((reason: unknown) => TResult2 | PromiseLike) - | undefined - | null, - ) { - return traced.then(onfulfilled, onrejected); - }, - } satisfies FlueCallHandle; - - return wrapped; -} - -function isPlausibleFlueContext(value: unknown): value is FlueContext { - return ( - !!value && - typeof value === "object" && - typeof (value as { init?: unknown }).init === "function" - ); -} - -function isPlausibleFlueHarness(value: unknown): value is FlueHarness { - return ( - !!value && - typeof value === "object" && - typeof (value as { session?: unknown }).session === "function" - ); -} - -function isPlausibleFlueSession(value: unknown): value is FlueSession { - return ( - !!value && - typeof value === "object" && - typeof (value as { prompt?: unknown }).prompt === "function" && - typeof (value as { skill?: unknown }).skill === "function" && - typeof (value as { task?: unknown }).task === "function" && - typeof (value as { compact?: unknown }).compact === "function" - ); -} - -function isFlueCallHandle(value: unknown): value is FlueCallHandle { - return ( - !!value && - typeof value === "object" && - typeof (value as { then?: unknown }).then === "function" && - typeof (value as { abort?: unknown }).abort === "function" && - "signal" in value - ); -}