Pydantic AI Workspace sandboxes: fetch Sume artifacts
Pydantic AI's Workspace abstraction runs tools locally or in sandboxes. Inside a sandbox, fetch Sume artifact URLs, and give Sume inputs as public HTTPS URLs.

Pydantic AI's releases for September and October 2026 describe a new Workspace abstraction so tools work locally or in sandboxes such as E2B, Modal and Sprites. The Sume side is simple: media you send to Sume must be a public HTTPS URL, so a file that exists only inside a sandbox cannot be an input. Results come back as Sume media URLs you can download.
What the release says
From the Pydantic AI releases page, read on 2026-10-03: a Workspace abstraction lets the same tools run locally or in a sandbox, with E2B, Modal and Sprites named. See the release notes for the API; this post uses no Pydantic AI code.
Inputs: public HTTPS only
Sume generation requests accept media as public HTTPS URLs. Localhost, private-network, non-HTTPS, signed or private URLs and mismatched content types are rejected before submission. A path such as /workspace/clip.mp4, or a URL that only resolves inside the sandbox, will be refused.
| Input location | Accepted? |
|---|---|
| Public HTTPS URL | Yes |
| Sume-hosted media.sume.com artifact | Yes |
| localhost or private network | No, rejected |
| Signed or private URL | No, rejected |
To get a sandbox file to Sume, host it at a public HTTPS location first, or use the asset flow: sume assets upload-url on the CLI, or assets_upload_url then assets_complete on MCP. Hosted MCP cannot read files from your laptop, and the same is true of a remote sandbox.
Outputs: download from the result
Completed jobs return artifact objects whose url is a Sume-owned media URL. Sume mirrors generated outputs there before exposing them, and the docs tell integrations to store the Sume URL, not raw provider URLs. Treat the URL as opaque.
import requests
def fetch_artifact(job_id: str, api_key: str, dest: str) -> str:
headers = {"Authorization": f"Bearer {api_key}"}
r = requests.get(f"https://api.sume.com/v1/jobs/{job_id}/result",
headers=headers, timeout=30)
r.raise_for_status()
url = r.json()["result"]["artifacts"][0]["url"]
data = requests.get(url, timeout=120)
data.raise_for_status()
with open(dest, "wb") as f:
f.write(data.content)
return destKeep the key out of the sandbox
Prefer to call Sume from the host process and pass only the artifact URL or file into the sandbox. If the sandbox must call the API, give it a key scoped to what it needs, and never log the key or signed URLs.
Sources
Related posts
More in Developers
- Python 3.10 is end of life: a stdlib Sume webhook verifier
Python 3.10 has reached end of life. A standard-library verifier for Sume's signed webhooks that refuses an empty secret and accepts rotated signatures.
- Python 3.14.8 urllib credential fix: a stdlib Sume job poll script
Python 3.14.8 fixed urllib HTTPPasswordMgr handing credentials across schemes. Upgrade, and call Sume with an x-api-key header from a plain stdlib script.
- Railway webhook custom headers vs Sume's signed headers
Railway project webhooks now accept custom headers. Sume signs its callbacks with x-sume-webhook-timestamp and x-sume-webhook-signature; verify them in Python.
- Railway Sandboxes: run the Sume CLI with an env-var key
Inside a short-lived sandbox, install the Sume CLI with the hosted installer, pass SUME_API_KEY as an environment variable, and never print it.
Written by Sume