A skills repo still recommends Sora 2 and gpt-image-1: swap guide

marketingskills issue 594 lists skill files that name Sora 2 and gpt-image-1. Which lines to edit and which Sume models fit video and image briefs now.

5 min readSume
All posts

Yes: according to an issue filed on September 22, 2026, several skill files in the marketingskills repository still recommend Sora 2 for video and gpt-image-1 for images. OpenAI shut Sora 2 down on September 24, 2026 and retires gpt-image-1 on October 23, 2026. If you copied those skills into an agent, edit the model names, because a recommendation to use a removed model fails at the first call.

Where the references are

The issue lists file paths and line numbers. For Sora 2: skills/video/SKILL.md (lines 44, 134 and 143), skills/ad-creative/SKILL.md (line 167), and skills/ad-creative/references/generative-tools.md (lines 13-14, 201-212, 230, 277, 289, 478 and 583). For gpt-image-1: skills/image/SKILL.md and skills/image/references/ai-image-prompting.md.

For video, the reporter proposes routing users to Veo 3.1, Kling, Seedance and other tools that remain, especially for audio and dialogue scenes. For images, the proposal is gpt-image-2. OpenAI's own deprecations page, read on 2026-10-07, names gpt-image-2.5-sunburst and gpt-image-2.5-flare as the replacements for gpt-image-1.

The issue also reports an unrelated broken relative link in skills/ad-creative/SKILL.md at line 154, which is a small reminder that skills are documents and need the same maintenance as code. Review them on a schedule, not when something fails.

Model references flagged in marketingskills issue 594 (read 2026-10-07)
Model named in the skill filesStatus on OpenAI's pageWhere it appears
Sora 2Shut down September 24, 2026skills/video, skills/ad-creative and its generative-tools reference
gpt-image-1Removed October 23, 2026skills/image and its ai-image-prompting reference

What a marketing brief needs from video

A skill that recommends a tool is really recommending a set of capabilities: audio and dialogue, vertical output, a start frame, a short duration. The Sume catalog answers those directly. Kling 3, Wan 3.0, MiniMax H3 Max, Seedance 2.5 and Gemini Omni Flash 1.1 each list audio support, and Omni and Kling accept 9:16.

Rewrite the skill's guidance as a short table of needs and models, then add the instruction to read GET /v1/videos/models, so that the skill does not go stale again when a model changes.

Sume video models and limits from the catalog (read 2026-10-07)
Model idSecondsResolutionsAudio
gemini-omni-flash-1.13 to 10360p, 720p, 1080p, 4Kyes
kling-34 to 15720p, 1080pyes
wan-3.02 to 30480p, 720p, 1080pyes
minimax-h3-max5 to 15480p, 768p, 1080pyes
seedance-2.54 to 30480p, 720p, 1080pyes

What a marketing brief needs from images

For still images, replace gpt-image-1 with openai/gpt-image-2.5, which takes up to 16 reference images, a mask_url, and quality up to max. Name the quality in the skill: the default is high when omitted, and high costs about four times medium, by the estimate of about $0.0659 against $0.0165 for a 1024x1024 text-only image before cent rounding.

If a skill describes a campaign with many variants, note the quantity next to the model: the 4-image ceiling per call on GPT Image 2.5 means a set of eight takes two requests, and a call with n set to 5 returns a 400 error.

A safe way to edit the skills

Replace names in one commit, then run one example from each skill. For the video skill, the script below checks the full submit-and-poll path with a short clip.

Treat model names as data: keep them in one reference file that the skills read, so the next retirement is a one-file change.

Then add a test: ask the agent to produce one image and one clip from the skill, and fail the check if either call returns a model error.

import json, os, time, urllib.request

key = os.environ.get("SUME_API_KEY")
if not key:
    raise SystemExit("SUME_API_KEY is not set")
H = {"Authorization": f"Bearer {key}", "Content-Type": "application/json"}

def call(url, body=None):
    data = json.dumps(body).encode() if body else None
    with urllib.request.urlopen(urllib.request.Request(url, data=data, headers=H)) as r:
        return json.load(r)

job = call("https://api.sume.com/v1/videos", {
    "model": "gemini-omni-flash-1.1",
    "prompt": "A slow dolly shot along a rainy neon street at night",
    "duration": 5,
    "resolution": "720p",
    "aspect_ratio": "16:9",
})
for _ in range(60):
    st = call(job["polling_url"])
    if st["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(15)
print(st["status"])
if st["status"] == "completed":
    req = urllib.request.Request(st["unsigned_urls"][0], headers=H)
    with urllib.request.urlopen(req) as r, open("clip.mp4", "wb") as f:
        f.write(r.read())

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume