Share screenshots from a session
Persist images past the sandbox with assets, and paste org-gated links on pull requests.
A sandbox is ephemeral: when the session ends, every file in it is gone. Assets are the exception, images an agent uploads to Ellipsis that outlive the sandbox, each with a link only members of your organization can open. The payoff is an agent that shows its work: a UI change lands as a pull request with a screenshot of the result, not just a diff.
How assets work
An upload returns a link of the form https://app.ellipsis.dev/assets/{asset_id}. That link is gated: opening it requires being logged in as a member of the owning organization, and everyone else gets a 404, so it is safe to paste in a pull request on a private repository. The dashboard lists all of an account's assets, each linked to the session that produced it.
Constraints, all from POST /v1/assets: PNG images only, 10 MiB per upload, and 100 uploads or 100 MiB per session.
Upload from a session
Every sandbox carries ELLIPSIS_API_TOKEN, so an agent uploads with plain curl:
curl -s https://api.ellipsis.dev/v1/assets \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"filename\": \"schedule-grid.png\",
\"content_type\": \"image/png\",
\"data_b64\": \"$(base64 -i schedule-grid.png)\"
}"{
"asset": {
"id": "9f2c4b7d1e8a4c02b6f3a1d5e7c90842",
"filename": "schedule-grid.png",
"content_type": "image/png",
"size_bytes": 48213,
"created_at": "2026-07-06T14:09:31Z",
"agent_session_id": "session_7Hq2mX4p"
},
"url": "https://app.ellipsis.dev/assets/9f2c4b7d1e8a4c02b6f3a1d5e7c90842"
}The url is what the agent pastes into a PR comment or description. Paste it as a link, not an inline image: the page behind it requires login, so GitHub cannot render it inline, and that is the point.
An agent that screenshots its changes
A react agent that runs the app, captures the affected screen, and attaches the screenshot to the pull request it is reviewing. The browser comes from image.setup, so it is baked into the cached image rather than installed on every run:
ellipsis:
version: v1
name: UI screenshotter
description: Posts a screenshot of the affected screen on splitshift-web PRs
triggers:
- type: react
events:
- event: pull_request_open
repository: splitshift-web
claude:
model: claude-haiku-4-5-20251001
system: |
When a pull request touches UI code in splitshift-web:
1. Check out the PR branch, install dependencies, and start the dev server.
2. Open the affected page with playwright and capture a PNG screenshot.
3. Upload it: POST it to $ELLIPSIS_API_BASE_URL/v1/assets as base64 JSON
(filename, content_type "image/png", data_b64), authorized with
$ELLIPSIS_API_TOKEN.
4. Comment on the pull request with a one-line description of what changed
visually and the asset url from the upload response.
If the PR touches no UI code, do nothing.
sandbox:
repositories:
- name: splitshift-web
image:
setup: |
cd splitshift-web && npm install
npx playwright install --with-deps chromium
limits:
run: 3.00On a splitshift-web PR that restyles the schedule grid, the session ends with a PR comment like:
Schedule grid after this change (weekly view, manager account):
https://app.ellipsis.dev/assets/9f2c4b7d1e8a4c02b6f3a1d5e7c90842Reviewers who are members of the org click through and see the screenshot; the link stays valid after the sandbox is gone.
Pull assets back down
Listing and downloading work from anywhere with a credential, not just inside sessions. GET /v1/assets lists metadata newest first (filter to one session with agent_session_id); GET /v1/assets/{asset_id} adds a download_url, a presigned link for the bytes that expires in 60 seconds:
curl -s "https://api.ellipsis.dev/v1/assets/9f2c4b7d1e8a4c02b6f3a1d5e7c90842" \
-H "Authorization: Bearer $ELLIPSIS_API_TOKEN" | jq -r .download_url | xargs curl -s -o schedule-grid.pngNext
Endpoint details: Assets in the API reference. Installing tools like playwright into the image: Customize the sandbox.