ceremony-media-proxy.yml is the executable bridge missing from direct Langfuse media actions. It uses the official Custom GPT openaiFileIdRefs mechanism, so the GPT sends a temporary reference to the user’s real file instead of attempting to place a large Base64 payload in function arguments.
The main ceremony-observations.yml talks directly to cloud.langfuse.com. A presigned media URL points to a dynamic object-storage host, which cannot be represented as a static OpenAPI path. The bridge therefore runs on a public HTTPS service you control and is imported as a second GPT Action. Together the specifications expose 24 actions, below the 30-action limit.
Build and run the included Node service:
npm install
npm run build
export LANGFUSE_PUBLIC_KEY='pk-lf-...'
export LANGFUSE_SECRET_KEY='sk-lf-...'
export LANGFUSE_BASE_URL='https://cloud.langfuse.com'
export COAIA_MEDIA_PROXY_API_KEY='generate-a-long-random-secret'
export PORT=8787
node dist/src/media-upload-proxy.js
# or, from the installed package:
coaiajs-media-proxy
Deploy it behind a public HTTPS URL. The Custom GPT service cannot reach localhost.
Optional controls:
COAIA_MEDIA_MAX_BYTES: maximum downloaded file size; defaults to 10 MiB.COAIA_OPENAI_FILE_HOSTS: comma-separated additional trusted conversation-file hosts.COAIA_MEDIA_UPLOAD_HOSTS: comma-separated additional trusted presigned-upload hosts for self-hosted storage.COAIA_MEDIA_ALLOW_HTTP=true: allows HTTP for local tests only; never use it in production.The proxy only downloads from approved OpenAI file hosts and only uploads to approved S3-compatible storage hosts. It rejects empty files, invalid media contexts, oversized payloads, and untrusted URLs.
https://replace-with-your-proxy.invalid in ceremony-media-proxy.yml with the deployed HTTPS origin.ceremony-observations.yml.X-Coaia-Proxy-KeyCOAIA_MEDIA_PROXY_API_KEY configured on the servicex-openai-isConsequential: false unchanged.Add this to the GPT instructions:
When the user supplies media for Langfuse, call media_uploadConversationFile
with exactly that conversation file in openaiFileIdRefs and the target trace or
dataset-item context. Never create placeholder bytes unless explicitly asked.
The bridge performs media-record creation, exact-byte hashing, the presigned PUT,
and media finalization. Do not claim success unless the bridge returns
success=true and a mediaToken.
Put the returned mediaToken unchanged into an observation input, output, or
metadata value, then call observations_export. Optionally call media_get with
the returned mediaId to verify uploadedAt and the temporary URL.
user/DALL-E/Code Interpreter file
→ openaiFileIdRefs temporary download URL
→ media_uploadConversationFile
→ download exact bytes
→ compute padded Base64 SHA-256 and exact length/type
→ POST /api/public/media
→ PUT exact bytes to the presigned storage URL
→ PATCH /api/public/media/{mediaId}
→ return @@@langfuseMedia:type=...|id=...|source=bytes@@@
→ observations_export containing the returned media token
→ observations_list / media_get verification
Primary references: