otelMiddleware: media generation spans never capture prompt, input media or output, even with captureContent
Maintainers usually reply within 1 day
@AlemTuzlak is already working on this.
Since Sep 27, 2026.
Assessment
This issue has not been assessed yet.
Description
Summary
otelMiddleware opens one CLIENT span for each media activity call (generateImage, generateVideo, generateAudio, generateSpeech, generateTranscription, …), added via #720. That span carries the provider, the model, the operation name and usage. It never records what was asked for or what came back, even with captureContent: true:
- no prompt
- no input media: reference images, start and end frames, source audio for transcription
- no output: generated image, video or audio URLs, or the transcript text
In PostHog, Langfuse or Datadog every media generation therefore shows up as an empty Input/Output pair with a cost attached. For image-to-video or reference-to-video, where the result depends mostly on the input images, there is nothing in the trace to debug from.
Root cause
startMediaSpan / endMediaSpan (packages/ai/src/middlewares/otel.ts:343–384) only set gen_ai.system, gen_ai.operation.name, gen_ai.request.model and usage. captureContent is only checked on the chat paths.
The inputs are already on the context: GenerationMiddlewareContext.artifactInputs holds the activity inputs. The media path never reads it, and the result is never inspected in the terminal hook.
The only workaround is attributeEnricher / onSpanEnd in every app, reimplementing the per-activity input and output shapes that the library already knows.
Proposal
When captureContent is on, the media span writes the same attributes the chat iteration spans do:
gen_ai.input.messages/langfuse.observation.input: the prompt as a text part, plus each input media reference as a URI part ({ type: 'uri', modality, uri }), reusing whatever part serialisation #1525 lands on.gen_ai.output.messages/langfuse.observation.output: output media URLs as URI parts, and transcript text as a text part.- Inline or base64 inputs and outputs follow the same rule as #1525: a placeholder by default, and an opt-in hook to swap in a URL.
redactandmaxContentLengthstill apply.
Related
- #720: added the media span (closed)
- #1525:
captureContentdrops non-text parts on chat spans
Version
@tanstack/ai 0.58.0 (current main has the same code).
I'm happy to open a PR.
- Dominant language
- TypeScript
- Stars
- 3.1k
- Forks
- 340
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 174
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the 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 TanStack/ai
-
StreamProcessor ignores the stream's message ids and files agent-loop calls on the wrong assistant messagePossibly taken @tombeckenham claimed this 1 day ago. Openwaiting-on: maintainer
TanStack/ai#1533 · 1 assignee ·
Maintainers usually reply within 1 day
-
StreamProcessor drops TEXT_MESSAGE_CHUNK events without a warningPossibly taken @AlemTuzlak claimed this 1 day ago. Openwaiting-on: maintainer
TanStack/ai#1531 · 1 assignee ·
Maintainers usually reply within 1 day
-
feat(ai): add a timeout option to chat(), matching the media activitiesPossibly taken @AlemTuzlak claimed this 2 days ago. Openwaiting-on: maintainer
TanStack/ai#1517 · 1 assignee ·
Maintainers usually reply within 1 day
-
Does a hosted provider package have to carry a key?Possibly taken @AlemTuzlak claimed this 3 days ago. Openwaiting-on: author
TanStack/ai#1506 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
Client tools never execute against spec-compliant AG-UI servers (plain `success` RUN_FINISHED)Possibly taken @jherr claimed this 5 days ago. Openwaiting-on: maintainer
TanStack/ai#1464 · 1 reaction · 1 assignee ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
microsoft/vscode-livepreview#876 ·
Maintainers usually reply within 1 day
-
needs-triage
Difficulty 1/5 Under an hour Newbie friendliness 90/100
JustJarethB/invoicer#54 ·
-
ICP 1.2.0 shows a scheduled task's interval in milliseconds under the label "Interval (In seconds)"OpenNeeds Triage Type/Bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
wso2/product-integrator#2585 ·
Maintainers usually reply within 1 day
-
check:passed streams:add
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
design
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
MTES-MCT/monitor-field#119 ·
Maintainers usually reply within 1 day