AI SDK tool spans don't respect `toModelOutput`
Maintainers usually reply within 1 day
Assessment
This issue has not been assessed yet.
Description
When a Vercel AI SDK tool defines toModelOutput, the model only sees that transformed value, but the wrapAISDK tool span still logs the raw execute result via the patched execute.
Apps use toModelOutput to keep data away from the model, for example query rows a user hasn't agreed to share. Braintrust's global setMaskingFunction doesn't fix this cleanly, because it doesn't know which tool a value came from.
Repro with [email protected] and [email protected], using a mock model:
import * as ai from 'ai'
import { MockLanguageModelV4 } from 'ai/test'
import { initLogger, wrapAISDK } from 'braintrust'
import { z } from 'zod'
initLogger({ projectName: 'repro' })
const { generateText } = wrapAISDK(ai)
await generateText({
model: new MockLanguageModelV4({
doGenerate: async () => ({
content: [{ type: 'tool-call', toolCallId: 'call-1', toolName: 'runQuery', input: '{}' }],
finishReason: { unified: 'tool-calls', raw: undefined },
usage: { inputTokens: { total: 1 }, outputTokens: { total: 1 } },
warnings: [],
}),
}),
prompt: 'Count signups',
tools: {
runQuery: ai.tool({
inputSchema: z.object({}),
execute: async () => ({ rows: [{ email: '[email protected]' }] }),
toModelOutput: () => ({ type: 'text', value: 'Rows hidden from the model' }),
}),
},
})
The runQuery tool span's output is { rows: [{ email: '[email protected]' }] }. I expected Rows hidden from the model. The raw rows also appear in the parent generateText span, under steps[].content[] in the tool result. The same happens with ai.registerTelemetry(braintrustAISDKTelemetry()).
| tool span | parent span |
|---|---|
When a tool defines toModelOutput, I expect the tool span and the parent span's tool results to log its result instead of the raw execute value. That way the trace matches what the model saw and avoids privacy footguns. If this is too big a change for the default, a wrapAISDK option to turn it on would cover our case.
- Dominant language
- TypeScript
- Stars
- 29
- Forks
- 21
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 70
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from braintrustdata/braintrust-sdk-javascript
-
High TypeScript checking cost from generated Zod 3 schemasPossibly taken @lforst claimed this 11 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 22/100
braintrustdata/braintrust-sdk-javascript#2624 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
[bot] Instrument Luma AI (17,324 weekly downloads)Possibly taken @karthiksenv claimed this 11 days ago. Opentypescript
Difficulty 4/5 3-5 days Newbie friendliness 55/100
braintrustdata/braintrust-sdk-javascript#2578 ·
Maintainers usually reply within 1 day
-
[bot] Instrument Letta Agent SDK (87,205 weekly downloads)Possibly taken @karthiksenv claimed this 14 days ago. Opentypescript
Difficulty 4/5 3-5 days Newbie friendliness 55/100
braintrustdata/braintrust-sdk-javascript#2577 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
braintrustdata/braintrust-sdk-javascript#2527 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 65/100
braintrustdata/braintrust-sdk-javascript#2526 ·
Maintainers usually reply within 1 day
All issues in braintrustdata/braintrust-sdk-javascript
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
VictoriaMetrics/victorialogs-datasource#747 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
Maintainers usually reply within 1 day
-
bug from-studio
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
esengine/DeepSeek-Reasonix#14608 ·
Maintainers usually reply within 1 day
-
triage
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
getarcaneapp/arcane#4590 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Clouditera/VulnHunter#57 ·