Skip to content

Upload media to an agent

Upload a file through the agent facade, then send it to the agent as a storage_ref in a WebSocket message. This avoids base64-encoding large files into the message.

  • An AgentRuntime with spec.media.storage set. Without it the facade answers upload_request with MEDIA_NOT_ENABLED. See Configure media storage.
  • A WebSocket connection to the agent and its session_id from the connected message.

Send an upload_request on the WebSocket:

{
"type": "upload_request",
"upload_request": {
"filename": "photo.jpg",
"mime_type": "image/jpeg",
"size_bytes": 102400
}
}

The facade answers with upload_ready. Keep upload_url, upload_id, storage_ref, method and headers.

To request the URL over HTTP instead, use POST /media/request-upload. See the WebSocket protocol reference for the request body and response keys.

Send the file to the upload URL with method (PUT), and set every header in headers. For local storage, S3 and GCS that is Content-Type, set to the MIME type you declared:

Terminal window
curl -X PUT -H "Content-Type: image/jpeg" \
--data-binary @photo.jpg "$UPLOAD_URL"

With local storage the upload URL has the form http://localhost:<facade port>/media/upload/<id>. Replace localhost:<facade port> with the address you reach the facade at. The facade answers 204 No Content.

With S3, GCS or Azure the URL is presigned for the cloud provider, so the upload goes straight to the bucket. The Content-Type header must match the declared MIME type, and Azure also needs x-ms-blob-type: BlockBlob, which headers lists. Then confirm the upload with its upload ID:

Terminal window
curl -X POST "http://<facade-host>:<port>/media/confirm-upload/<upload-id>"

Send a message whose part carries the storage_ref and the same MIME type:

{
"type": "message",
"session_id": "sess-abc123",
"parts": [
{ "type": "text", "text": "What's in this image?" },
{
"type": "image",
"media": {
"storage_ref": "omnia://sessions/sess-abc123/media/med-def456",
"mime_type": "image/jpeg"
}
}
]
}

Fetch the file’s metadata. The two path segments are the session ID and the media ID from the storage_ref:

Terminal window
curl "http://<facade-host>:<port>/media/info/sess-abc123/med-def456"

The response lists the filename, MIME type, size and expiry. To download the file, request /media/download/sess-abc123/med-def456. With S3, GCS or Azure that request redirects to a presigned URL, so add -L to curl.

SymptomCause
MEDIA_NOT_ENABLEDThe AgentRuntime has no spec.media.storage.
UPLOAD_FAILEDThe facade could not prepare the upload: the file exceeds the maximum size or the backend refused it.
400 upload failed on PUTThe upload ID is unknown or the upload URL expired. Request a new one.