Skip to content

Implement Langfuse Media Token attachment for inline UI rendering#69

Merged
jgwill merged 14 commits intoclaude/langfuse-media-support-01DKbZAHAypsV2cbMgs2Joqffrom
copilot/sub-pr-68
Nov 26, 2025
Merged

Implement Langfuse Media Token attachment for inline UI rendering#69
jgwill merged 14 commits intoclaude/langfuse-media-support-01DKbZAHAypsV2cbMgs2Joqffrom
copilot/sub-pr-68

Conversation

Copy link
Contributor

Copilot AI commented Nov 22, 2025

The media upload implementation was uploading files to S3 but not attaching Langfuse Media Tokens to traces/observations, preventing inline rendering in the Langfuse UI.

Changes

Media Token System

  • Added create_langfuse_media_token() - generates standardized @@@langfuseMedia:type={MIME}|id={ID}|source={TYPE}@@@ tokens
  • Added attach_media_token_to_trace() - injects tokens into trace fields via ingestion API
  • Added attach_media_token_to_observation() - injects tokens into observation fields
  • Enhanced upload_and_attach_media() to automatically generate and attach tokens after S3 upload

Security Hardening

  • Implemented domain validation for presigned URLs to prevent data exfiltration
  • Uses suffix-based matching to prevent subdomain spoofing attacks (malicious-amazonaws.com)
  • Restricts to trusted providers: AWS S3, GCP Storage, Azure Blob, Cloudflare R2
  • Allows AWS multi-level subdomains only for S3 patterns (bucket.s3.amazonaws.com)

Code Quality

  • Moved time and urlparse imports to module level
  • Replaced bare except with specific exception types and explanatory comments
  • Removed redundant local os import

Documentation

  • Created MEDIA_UPLOAD_GUIDE.md with CLI/API/MCP examples and troubleshooting

Example Usage

# Now returns media_token and automatically attaches to trace
result = upload_and_attach_media("screenshot.png", "trace_abc123", field="input")
# result["media_token"] = "@@@langfuseMedia:type=image/png|id=media_xyz789|source=file@@@"
# Token is automatically injected into trace input field for UI rendering
# CLI automatically handles token attachment
coaia fuse media upload photo.jpg trace_abc123 --field output

Token Format

Per Langfuse spec: @@@langfuseMedia:type={MIME_TYPE}|id={MEDIA_ID}|source={SOURCE}@@@

Tokens are injected via trace/observation PATCH operations using the ingestion API's event merging mechanism.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 5 commits November 22, 2025 17:13
…nd comments

Co-authored-by: jgwill <23141173+jgwill@users.noreply.github.com>
Co-authored-by: jgwill <23141173+jgwill@users.noreply.github.com>
Co-authored-by: jgwill <23141173+jgwill@users.noreply.github.com>
…ofing

Co-authored-by: jgwill <23141173+jgwill@users.noreply.github.com>
Co-authored-by: jgwill <23141173+jgwill@users.noreply.github.com>
Copilot AI changed the title [WIP] Add Langfuse media support implementation Implement Langfuse Media Token attachment for inline UI rendering Nov 22, 2025
@jgwill
Copy link
Owner

jgwill commented Nov 22, 2025

During testing of the coaia_fuse_media_upload tool (which utilizes upload_and_attach_media), an attempt to upload a 0-byte dummy.png file resulted in a 400 Bad Request error from the Langfuse API.

Details:

  1. Trace ID: 1d717b26-7a52-4974-a9f4-2db43785d455
  2. Command used: coaia_fuse_media_upload(content_type='image/png', file_path='./dummy.png', trace_id='1d717b26-7a52-4974-a9f4-2db43785d455')
  3. Error received: {"success": false, "error": "Failed to get upload URL: Failed to get upload URL: 400"}

Diagnosis:
The upload_and_attach_media function first calls get_media_upload_url to obtain a presigned URL from Langfuse. It appears that the Langfuse API rejects requests for media files with a contentLength of 0, especially for types like image/png, as these are expected to contain actual data.

Recommendation for Implementation Agent:
The upload_and_attach_media function (or coaia_fuse_media_upload at a higher level) should be enhanced to handle 0-byte files explicitly. This could involve:

  • Pre-validation: Adding a check to ensure file_path points to a non-empty file before making the get_media_upload_url call. If the file is empty, return a more descriptive error (e.g., "Cannot upload empty file") instead of relying on the API to return a generic 400.
  • API behavior clarification: If the Langfuse API does support 0-byte files for certain content types, ensure that the contentLength parameter is correctly handled for such cases. However, for media types like images, it's generally expected that the file contains data.

For future testing, a small, non-empty dummy.png or dummy.txt (uploaded as text/plain) would be required to fully validate the media upload workflow.

Copilot AI requested a review from jgwill November 22, 2025 17:25
Propagate error details from underlying upload_and_attach_media function to
provide better debugging information when media uploads fail.
…us updates (#68)

- Changed SHA256 hashing from hexdigest to base64 encoding (44-char format required by Langfuse)
- Accept both 200 and 201 status codes as success in media upload URL requests
- Add SHA256 checksum header to S3 uploads for integrity validation
- Handle media deduplication: skip upload if file already exists (uploadUrl null)
- Add uploadedAt timestamp to media patch status updates
- Include detail field in error responses for better debugging
- Properly handle existing media data when deduplication occurs
@jgwill jgwill marked this pull request as ready for review November 26, 2025 18:46
@jgwill jgwill merged commit ad577a7 into claude/langfuse-media-support-01DKbZAHAypsV2cbMgs2Joqf Nov 26, 2025
@jgwill jgwill deleted the copilot/sub-pr-68 branch November 26, 2025 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants