<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mason Reed</title>
    <description>The latest articles on DEV Community by Mason Reed (@masonreed1).</description>
    <link>https://dev.to/masonreed1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4113593%2F5718bbeb-e76f-4666-b75c-87fb4df12464.png</url>
      <title>DEV Community: Mason Reed</title>
      <link>https://dev.to/masonreed1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masonreed1"/>
    <language>en</language>
    <item>
      <title>FLUX 3: What the Video API Gives You, What It Costs, Where It Still Fails</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Fri, 09 Oct 2026 07:33:46 +0000</pubDate>
      <link>https://dev.to/masonreed1/flux-3-what-the-video-api-gives-you-what-it-costs-where-it-still-fails-4bal</link>
      <guid>https://dev.to/masonreed1/flux-3-what-the-video-api-gives-you-what-it-costs-where-it-still-fails-4bal</guid>
      <description>&lt;p&gt;FLUX 3 is Black Forest Labs' unified multimodal foundation model, and the architectural bet is the interesting part: one shared representation trained across images, video and audio instead of three separate models. BFL's framing is that images, video and sound are different observations of the same world. A moving car has appearance, motion, sound, spatial structure, material behaviour and causal behaviour, and learning those signals together gives the network more constraints than learning frames in isolation.&lt;/p&gt;

&lt;p&gt;That is why BFL describes FLUX 3 as a step toward a reality or world model rather than just another video generator. The claim is broader than the shipped product. As of September 2026 the video endpoint is live, while FLUX 3 Image and the open-weight FLUX 3 Dev model are separate rollout items. Here is what you can call today, what it costs, and where it breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What has shipped
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FLUX 3 Video generation&lt;/td&gt;
&lt;td&gt;Generally available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native video audio&lt;/td&gt;
&lt;td&gt;Generally available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text-to-video&lt;/td&gt;
&lt;td&gt;Generally available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image-to-video / keyframes&lt;/td&gt;
&lt;td&gt;Generally available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video continuation&lt;/td&gt;
&lt;td&gt;Generally available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Richer image/video/audio reference combinations&lt;/td&gt;
&lt;td&gt;Planned expansion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FLUX 3 Image generation and editing&lt;/td&gt;
&lt;td&gt;Upcoming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FLUX 3 Dev open weights&lt;/td&gt;
&lt;td&gt;Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Action-prediction deployment&lt;/td&gt;
&lt;td&gt;Research / commercial partner track&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you need stills from this family, FLUX.2 is still the dedicated option (FLUX.2 Max among them). The public FLUX 3 product is video and audio, full stop. Do not read the family roadmap as a shipped image endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Developer&lt;/td&gt;
&lt;td&gt;Black Forest Labs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model family&lt;/td&gt;
&lt;td&gt;FLUX 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model type&lt;/td&gt;
&lt;td&gt;Unified multimodal foundation / generative video model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public video release&lt;/td&gt;
&lt;td&gt;August 4, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text-to-video&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image-to-video / keyframes&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video continuation&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max T2V / I2V duration&lt;/td&gt;
&lt;td&gt;20 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation duration&lt;/td&gt;
&lt;td&gt;5–15 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frame rate&lt;/td&gt;
&lt;td&gt;24 fps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution tiers&lt;/td&gt;
&lt;td&gt;HD, FHD, QHD/2K, UHD/4K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FHD 16:9 output&lt;/td&gt;
&lt;td&gt;1920 × 1088&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image references&lt;/td&gt;
&lt;td&gt;Up to 10 for I2V / keyframe workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native audio&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multilingual dialogue + lip sync&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-shot generation&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Draft Mode&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research foundation&lt;/td&gt;
&lt;td&gt;Self-Flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core training direction&lt;/td&gt;
&lt;td&gt;Joint image, video and audio representation learning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Public still-image endpoint&lt;/td&gt;
&lt;td&gt;Not yet generally released&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open-weight FLUX 3 Dev&lt;/td&gt;
&lt;td&gt;Planned&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Aspect ratios cover 21:9, 2:1, 16:9, 4:3, 1:1, 3:4 and 9:16. Resolution bands are defined by total pixels per frame rather than aspect ratio, and Draft Mode is HD only. Note the duration split: text-to-video and image-to-video accept 5–20 seconds, continuation accepts a 5–15 second generation window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing, and a working request
&lt;/h2&gt;

&lt;p&gt;BFL bills by generated duration.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;BFL list price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;T2V / I2V Draft HD&lt;/td&gt;
&lt;td&gt;$0.06/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T2V / I2V HD&lt;/td&gt;
&lt;td&gt;$0.17/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T2V / I2V FHD&lt;/td&gt;
&lt;td&gt;$0.29/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T2V / I2V QHD (2K)&lt;/td&gt;
&lt;td&gt;$0.40/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T2V / I2V UHD (4K)&lt;/td&gt;
&lt;td&gt;$0.80/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation Draft&lt;/td&gt;
&lt;td&gt;$0.12/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation HD&lt;/td&gt;
&lt;td&gt;$0.41/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation FHD&lt;/td&gt;
&lt;td&gt;$0.53/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation QHD (2K)&lt;/td&gt;
&lt;td&gt;$0.65/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation UHD (4K)&lt;/td&gt;
&lt;td&gt;$0.95/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 10-second HD render lands around $1.70 at list; the same length at FHD is about $2.90. Continuation is substantially more expensive per second than ordinary generation at every tier, so if your product extends clips often, model that as its own cost line instead of folding it into an average.&lt;/p&gt;

&lt;p&gt;The request shape is a standard form POST to an OpenAI-style &lt;code&gt;/v1/videos&lt;/code&gt; endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.cometapi.com/v1/videos"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$COMETAPI_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--form-string&lt;/span&gt; &lt;span class="s2"&gt;"model=flux-3"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--form-string&lt;/span&gt; &lt;span class="s2"&gt;"prompt=A paper boat glides across a still pond in soft morning light"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--form-string&lt;/span&gt; &lt;span class="s2"&gt;"seconds=5"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--form-string&lt;/span&gt; &lt;span class="s2"&gt;"size=1280x720"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow is asynchronous. The initial call returns a task ID, you poll until the job completes, then you fetch the resulting video. Do not hold an HTTP request open for the full render; push generation through a background job or task queue and let the client poll your own status endpoint. I route this through CometAPI, which lists the model as &lt;code&gt;flux-3&lt;/code&gt; (marked Available, platform release date August 13, 2026) at $0.136/s for 720p and $0.232/s for 1080p, roughly 20% under BFL's listed $0.17/s and $0.29/s. That is about $1.36 and $2.32 for a 10-second run. One caveat worth flagging: some older descriptive copy on that site still reflects the July Early Access period, so check the live model card and pricing fields before you commit to an integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood: Self-Flow
&lt;/h2&gt;

&lt;p&gt;The research foundation is &lt;a href="https://black-forest-labs.github.io/Self-Flow/" rel="noopener noreferrer"&gt;Self-Flow&lt;/a&gt;, BFL's self-supervised flow-matching approach. Standard generative pipelines lean on separately pretrained representation models or auxiliary supervision. Self-Flow is built to learn useful representations directly from the generative objective.&lt;/p&gt;

&lt;p&gt;The mechanism to know about is &lt;a href="https://black-forest-labs.github.io/Self-Flow/" rel="noopener noreferrer"&gt;Dual-Timestep Scheduling&lt;/a&gt;: different groups of tokens get different noise levels during training. That creates information asymmetry, where some parts of the input carry more usable signal than others, which forces the network to build representations that help infer what is missing. In practice FLUX 3 is pushed toward learning relationships between objects, frames, motion, sound and temporal events rather than memorizing what a single frame should look like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fblack-forest-labs.github.io%2FSelf-Flow%2Farchitecture.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fblack-forest-labs.github.io%2FSelf-Flow%2Farchitecture.webp" alt="Self-Flow method architecture" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Self-Flow architecture, image source: &lt;a href="https://black-forest-labs.github.io/Self-Flow/architecture.webp" rel="noopener noreferrer"&gt;Black Forest Labs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;BFL also ran joint multimodal training experiments on a FLUX.2-derived backbone with millions of videos and hundreds of millions of images. Those experiments support the broader hypothesis that representation learning and generation can share a system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why video eats the compute
&lt;/h3&gt;

&lt;p&gt;Video carries information a still cannot. A single frame shows a ball above the floor; a video shows it falling, bouncing, deforming on impact, making a sound and changing direction. BFL disclosed that video prediction accounts for &lt;a href="https://bfl.ai/blog/flux-3-mimic" rel="noopener noreferrer"&gt;more than 95%&lt;/a&gt; of FLUX 3's training compute. Audio is comparatively cheap because it is a much lower-dimensional signal tightly coupled to visible events. That allocation is a decent explanation for why video shipped first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capability notes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keyframes and references.&lt;/strong&gt; The current API accepts &lt;a href="https://docs.bfl.ai/flux_3/flux3_overview" rel="noopener noreferrer"&gt;up to ten image references&lt;/a&gt; in image-to-video workflows, so you can animate an initial image, drive toward an end frame, or place multiple images as timed keyframes instead of letting the model improvise the whole sequence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuation.&lt;/strong&gt; Feed an existing video plus its audio and FLUX 3 generates what happens next, preserving movement, camera behaviour, dialogue and sound across the seam. If you have ever generated a second clip and concatenated the files, you know how visible that join usually is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audio.&lt;/strong&gt; Sound is produced at generation time, not in a separate speech or SFX pass. &lt;a href="https://bfl.ai/blog/flux-3-video" rel="noopener noreferrer"&gt;Dialogue&lt;/a&gt;, effects and ambience are all in scope, with multilingual dialogue and lip sync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-shot.&lt;/strong&gt; A single prompt can carry &lt;a href="https://bfl.ai/blog/flux-3-video" rel="noopener noreferrer"&gt;multiple scenes or camera angles&lt;/a&gt;. Most earlier models are strongest on one continuous shot; this one is explicitly built for multi-shot sequences in one generation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Draft Mode.&lt;/strong&gt; You can generate a cheaper preview and then enhance the selected draft while keeping the composition and motion you picked. Per &lt;a href="https://docs.bfl.ai/flux_3/flux3_overview" rel="noopener noreferrer"&gt;current BFL pricing&lt;/a&gt; a standard T2V/I2V draft is $0.06/s against $0.17/s for regular HD. For prompt-heavy iteration this is the feature that matters most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarks: vendor versus third party
&lt;/h2&gt;

&lt;p&gt;There are two useful evidence sets now.&lt;/p&gt;

&lt;p&gt;BFL's August 4 &lt;a href="https://bfl.ai/blog/flux-3-video" rel="noopener noreferrer"&gt;evaluation of the released model&lt;/a&gt; reports a text-to-video ELO of 1135 in an internal all-vs-all human-preference test, the highest score in the group BFL tested. Image-to-video tied the strongest tested competitor and beat the rest. This supersedes the preliminary July win rates, though it is still a vendor-run protocol.&lt;/p&gt;

&lt;p&gt;Megaton's v-benchmark v2 is the independent check, run in August 2026.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Megaton score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Megaton Index&lt;/td&gt;
&lt;td&gt;76.51 (rank #3 at evaluation time)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt Adherence&lt;/td&gt;
&lt;td&gt;87.07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scene Consistency&lt;/td&gt;
&lt;td&gt;94.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Physics&lt;/td&gt;
&lt;td&gt;70.63&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human Fidelity&lt;/td&gt;
&lt;td&gt;73.70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object &amp;amp; Product Fidelity&lt;/td&gt;
&lt;td&gt;83.82&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Causal &amp;amp; Semantic Coherence&lt;/td&gt;
&lt;td&gt;80.91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text Fidelity&lt;/td&gt;
&lt;td&gt;82.41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cinematography&lt;/td&gt;
&lt;td&gt;71.43&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Taste &amp;amp; Art Direction&lt;/td&gt;
&lt;td&gt;65.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The profile tells you more than the index. Scene consistency is the standout, and prompt adherence, object fidelity, causal coherence and text fidelity all clear 80. Physics, human fidelity and art direction are the weak spots, which is the useful takeaway: better temporal representation does not solve synthetic motion or taste. The two rankings diverging (first internally, third externally) is not a contradiction. Different prompt distributions, scoring dimensions, evaluator pools and aggregation rules will do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Against Seedance 2.5, MiniMax H3 and Wan 3.0
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;FLUX 3&lt;/th&gt;
&lt;th&gt;Seedance 2.5&lt;/th&gt;
&lt;th&gt;MiniMax H3&lt;/th&gt;
&lt;th&gt;Wan 3.0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Developer&lt;/td&gt;
&lt;td&gt;Black Forest Labs&lt;/td&gt;
&lt;td&gt;ByteDance Seed&lt;/td&gt;
&lt;td&gt;MiniMax&lt;/td&gt;
&lt;td&gt;Alibaba&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max advertised clip&lt;/td&gt;
&lt;td&gt;20 s&lt;/td&gt;
&lt;td&gt;30 s&lt;/td&gt;
&lt;td&gt;15 s&lt;/td&gt;
&lt;td&gt;30 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;HD / FHD / QHD (2K) / UHD (4K)&lt;/td&gt;
&lt;td&gt;API tier dependent&lt;/td&gt;
&lt;td&gt;Up to 2K&lt;/td&gt;
&lt;td&gt;Up to 1080p&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native audio&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes, stereo&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text-to-video&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image / reference input&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keyframe / reference control&lt;/td&gt;
&lt;td&gt;Strong timed keyframes&lt;/td&gt;
&lt;td&gt;Strong multimodal reference control&lt;/td&gt;
&lt;td&gt;Multimodal conditioning&lt;/td&gt;
&lt;td&gt;Multimodal reference control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation / editing&lt;/td&gt;
&lt;td&gt;Continuation available&lt;/td&gt;
&lt;td&gt;Editing-oriented workflow&lt;/td&gt;
&lt;td&gt;Omni generation focus&lt;/td&gt;
&lt;td&gt;Editing and reference workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-shot&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distinctive strength&lt;/td&gt;
&lt;td&gt;Reality-model architecture, scene consistency, Self-Flow&lt;/td&gt;
&lt;td&gt;Long-form storytelling, reference control&lt;/td&gt;
&lt;td&gt;2K audiovisual generation, omni-modal context&lt;/td&gt;
&lt;td&gt;Long clips, lower entry cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listed entry price / s&lt;/td&gt;
&lt;td&gt;$0.136&lt;/td&gt;
&lt;td&gt;$0.0824&lt;/td&gt;
&lt;td&gt;$0.064&lt;/td&gt;
&lt;td&gt;$0.040&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Treat the price row as a rough comparison only. These APIs bill against different resolutions, durations, quality tiers and rules, so the cheapest per-second number is not the cheapest equivalent-quality output.&lt;/p&gt;

&lt;p&gt;Seedance 2.5 wins on duration outright (30 s against 20 s) and leans hard into reference-driven generation and editing. Megaton currently &lt;a href="https://megaton.ai/compare/seedance-2-5-vs-flux-3" rel="noopener noreferrer"&gt;ranks it above FLUX 3&lt;/a&gt; overall, so expect real competition at the top of this market. MiniMax H3 is the spec argument: up to 2K with native stereo audio, but a 15 s ceiling against FLUX 3's 20 s, and no equivalent of Draft Mode for cheap iteration. Wan 3.0 goes for broad multimodal inputs, audiovisual output, editing and 30 s clips at a lower listed entry price; FLUX 3 counters with scene consistency, the Self-Flow foundation and the action-prediction roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it holds up, and where it does not
&lt;/h2&gt;

&lt;p&gt;Strengths I would build on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scene and temporal consistency, and it is the top Megaton category at 94.76.&lt;/li&gt;
&lt;li&gt;Native audiovisual generation in one pass, no stitching two models together.&lt;/li&gt;
&lt;li&gt;Prompt adherence at 87.07 independently, so it is not just visual polish.&lt;/li&gt;
&lt;li&gt;Keyframe control with up to ten image references.&lt;/li&gt;
&lt;li&gt;Draft-to-final iteration, which addresses a real cost problem in video work: most generations get thrown away.&lt;/li&gt;
&lt;li&gt;A deliberately wide style range rather than one house look.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations to plan around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The full multimodal roadmap has not shipped. Do not assume FLUX 3 Image or Dev weights from the family announcement.&lt;/li&gt;
&lt;li&gt;20 seconds is no longer industry-leading.&lt;/li&gt;
&lt;li&gt;Physics is not solved. 70.63 against 94.76 scene consistency is a wide gap.&lt;/li&gt;
&lt;li&gt;Human fidelity at 73.70 still fails on hard anatomy and realistic motion.&lt;/li&gt;
&lt;li&gt;Continuation pricing is steep relative to ordinary generation.&lt;/li&gt;
&lt;li&gt;BFL's headline competitive benchmark is internal. Run your own prompts, shot types, languages and reference assets before you commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The part that is not video
&lt;/h2&gt;

&lt;p&gt;Robot control signals are temporal predictions conditioned on visual observations, so BFL uses the FLUX 3 video representation as a base for action prediction. Its work with mimic robotics produced FLUX-mimic, where an action decoder reads representations from the video model instead of training a separate perception stack. BFL reports the FLUX-mimic backbone running in &lt;a href="https://bfl.ai/blog/flux-3-mimic" rel="noopener noreferrer"&gt;under 80 ms&lt;/a&gt; on a single RTX 5090, with the full robot system closing a roughly 101 ms reaction loop. Audi has been discussed as an industrial evaluation partner.&lt;/p&gt;

&lt;p&gt;None of that makes the public video API a robotics API. It does explain why BFL spent heavily on multimodal video representation rather than treating generation as an isolated media task.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is FLUX 3 available now?&lt;/strong&gt; Yes. FLUX 3 Video went generally available through BFL on August 4, 2026, and is listed as Available under the model ID &lt;code&gt;flux-3&lt;/code&gt;. The still-image release and FLUX 3 Dev open weights remain separate roadmap items.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it generate audio?&lt;/strong&gt; Yes, synchronized natively: dialogue, ambient sound and effects, with multilingual dialogue and &lt;a href="https://bfl.ai/blog/flux-3-video" rel="noopener noreferrer"&gt;lip sync&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long can clips be?&lt;/strong&gt; 5–20 seconds for T2V and I2V. Continuation generates 5–15 seconds of new content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What resolutions?&lt;/strong&gt; HD (up to 1 MP per frame), FHD (up to 2 MP), QHD/2K (up to 4 MP) and UHD/4K (up to 8 MP). 16:9 FHD is 1920 × 1088. Bands are total pixels per frame, not aspect ratio, and Draft Mode is HD only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it open source?&lt;/strong&gt; Not currently. &lt;a href="https://bfl.ai/blog/flux-3" rel="noopener noreferrer"&gt;FLUX 3 Dev&lt;/a&gt; has been announced as an open-weight multimodal variant with no public release date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use it for still images?&lt;/strong&gt; Architecturally it is trained across images, video and audio, and BFL has demonstrated image generation and editing research, but the FLUX 3 Image product is still upcoming. For production stills, use an existing FLUX image model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it a world model?&lt;/strong&gt; BFL positions it as a reality-model foundation because the shared representations extend from audiovisual prediction toward physical action prediction. Calling it a general-purpose world model goes beyond the available evidence. A multimodal generative foundation model designed around world-modelling objectives is the accurate description.&lt;/p&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;FLUX 3 is less an upgrade to FLUX.2 than a different product line with a longer thesis behind it: train one shared multimodal representation, then reuse it for video, sound, images and eventually actions. Self-Flow is the research basis and the released video model is the first production proof.&lt;/p&gt;

&lt;p&gt;What you can ship against today is 20-second clips at 24 fps, HD through UHD/4K, synchronized audio, multilingual dialogue, keyframes, continuation, multi-shot and Draft Mode. It is not the cheapest per second, not the longest, and not top of the independent leaderboard. Where it earns its place is scene consistency, prompt adherence, object persistence and controllable keyframes, plus native sound in the same pass. Pick it for the workload that needs those, and test against your own prompts rather than anyone's ranking.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/what-is-flux-3/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=what-is-flux-3"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Kling VIDEO 3.0 Omni is a reference engine, not a quality upgrade</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Fri, 09 Oct 2026 06:57:13 +0000</pubDate>
      <link>https://dev.to/masonreed1/kling-video-30-omni-is-a-reference-engine-not-a-quality-upgrade-l06</link>
      <guid>https://dev.to/masonreed1/kling-video-30-omni-is-a-reference-engine-not-a-quality-upgrade-l06</guid>
      <description>&lt;p&gt;Omni is a workflow upgrade, not a quality one. If a project needs the same face, the same bottle, and the same studio across several shots, it earns its keep. If you want one good clip, the standard model is cheaper and often ranks higher.&lt;/p&gt;

&lt;p&gt;The order that works: validate a single short shot, approve the references, add audio, then expand to a storyboard. Jumping straight to multi-shot sequencing is where most of my wasted credits went.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Omni supports
&lt;/h2&gt;

&lt;p&gt;The usual pitch is “video with sound.” That is misleading. Standard Kling VIDEO 3.0 also does native audio, multi-shot generation, and element binding. The real distinction is how references get organized and reused.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec (official generation guide)&lt;/th&gt;
&lt;th&gt;Omni capability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input options&lt;/td&gt;
&lt;td&gt;Text, images, video references, reusable elements, voice references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model-level output duration&lt;/td&gt;
&lt;td&gt;3–15 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video resolution&lt;/td&gt;
&lt;td&gt;720p and 1080p, native 4K in supported workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audio&lt;/td&gt;
&lt;td&gt;Native audiovisual generation with supported character–voice binding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shot control&lt;/td&gt;
&lt;td&gt;Single-shot generation and custom multi-shot sequencing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-image element creation&lt;/td&gt;
&lt;td&gt;2–4 images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video-based character creation&lt;/td&gt;
&lt;td&gt;3–8 second character clip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recommended voice sample&lt;/td&gt;
&lt;td&gt;5–30 seconds of clear, single-speaker speech&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Combined image and element budget&lt;/td&gt;
&lt;td&gt;Up to 7 without video input, up to 4 with video input&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two traps live in that table.&lt;/p&gt;

&lt;p&gt;Creating an element is not the same as attaching it to one request. Several views can belong to a single reusable element, and they do not count as separate element slots.&lt;/p&gt;

&lt;p&gt;A model-level capability is not a provider-level one. A 15-second workflow in Kling’s interface and a third-party API request can expose different parameters and different duration values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick by reference layout, not by name
&lt;/h2&gt;

&lt;p&gt;Stop framing this as “basic vs pro.” Ask where the essential information lives.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Kling VIDEO 3.0&lt;/th&gt;
&lt;th&gt;Kling VIDEO 3.0 Omni&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reference organization&lt;/td&gt;
&lt;td&gt;Element binding around an approved start frame or start/end frames&lt;/td&gt;
&lt;td&gt;Broader composition with images, elements, and video references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Element relationship&lt;/td&gt;
&lt;td&gt;Best when the important subjects already exist in the defining frame&lt;/td&gt;
&lt;td&gt;Best when separate assets must be combined or reused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Character voice&lt;/td&gt;
&lt;td&gt;Can use voice-bound elements&lt;/td&gt;
&lt;td&gt;Visual and voice references in one workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-shot generation&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported with custom storyboard controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recommended starting point&lt;/td&gt;
&lt;td&gt;One approved keyframe that already defines the scene&lt;/td&gt;
&lt;td&gt;A collection of assets that must stay recognizable across shots&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Start with the standard workflow when one approved frame already carries the essential information. Reach for Omni when reference composition, asset reuse, or cross-shot continuity is the job.&lt;/p&gt;

&lt;h3&gt;
  
  
  The benchmarks do not favor Omni
&lt;/h3&gt;

&lt;p&gt;These are point estimates for the 1080p Pro, audio-enabled entries in Artificial Analysis, checked September 9, 2026. Values after ± are published 95% confidence intervals.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evaluation (text-to-video / image-to-video)&lt;/th&gt;
&lt;th&gt;Standard&lt;/th&gt;
&lt;th&gt;Omni&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Text-to-video Elo&lt;/td&gt;
&lt;td&gt;1108 ± 5&lt;/td&gt;
&lt;td&gt;1090 ± 6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image-to-video Elo&lt;/td&gt;
&lt;td&gt;1072 ± 6&lt;/td&gt;
&lt;td&gt;1060 ± 7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are preference-based ratings, not generation-success percentages. The standard model holds the higher point estimate in both rows, and the image-to-video intervals overlap. Scores shift as new evaluations arrive.&lt;/p&gt;

&lt;p&gt;So Omni’s case rests on reference handling and production continuity. It is not a universal quality ranking, and the name does not win a benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build one reference-led shot first
&lt;/h2&gt;

&lt;p&gt;Illustrative setup: a vertical ad with a presenter, a reusable bottle, and one studio setting. Not a reported generation test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prepare a small asset set
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Asset&lt;/th&gt;
&lt;th&gt;Preparation&lt;/th&gt;
&lt;th&gt;Acceptance criterion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Presenter&lt;/td&gt;
&lt;td&gt;Clear views with consistent hair, clothing, and lighting&lt;/td&gt;
&lt;td&gt;Recognizable face, unchanged wardrobe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bottle&lt;/td&gt;
&lt;td&gt;Front, side, and three-quarter views&lt;/td&gt;
&lt;td&gt;Stable body shape, cap, color, label&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setting&lt;/td&gt;
&lt;td&gt;One approved studio reference&lt;/td&gt;
&lt;td&gt;Consistent background and light direction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice&lt;/td&gt;
&lt;td&gt;Clean speech from an authorized speaker&lt;/td&gt;
&lt;td&gt;Recognizable voice, no competing speech&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Fix conflicting references before you try to compensate with a longer prompt. Use only faces, recordings, and brand assets you are authorized to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create and name elements
&lt;/h3&gt;

&lt;p&gt;In Kling’s Element Library, create reusable assets instead of re-describing the same subject on every shot. The official workflow supports multi-image and video-based character creation.&lt;/p&gt;

&lt;p&gt;Names like &lt;strong&gt;Maya&lt;/strong&gt;, &lt;strong&gt;BlueBottle&lt;/strong&gt;, and &lt;strong&gt;Studio&lt;/strong&gt; are organizational aids. Selecting the saved element is what attaches the reference. For uploaded voices, use clear, single-speaker audio without music or overlapping voices.&lt;/p&gt;

&lt;p&gt;In the prompts below, &lt;a class="mentioned-user" href="https://dev.to/maya"&gt;@maya&lt;/a&gt;, @BlueBottle, and &lt;a class="mentioned-user" href="https://dev.to/studio"&gt;@studio&lt;/a&gt; stand for elements selected in the interface. Typing the names without attaching the assets creates no reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate a single shot
&lt;/h3&gt;

&lt;p&gt;Open the Omni generation workspace, pick the model, attach the assets. Start at five seconds, one camera move, no dialogue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a single continuous product shot using @BlueBottle in @Studio.

The bottle stands upright on a clean tabletop. Keep its body shape,
cap, surface color, and label placement consistent with the references.

Camera: a slow, straight push-in from a medium close-up.
Lighting: soft studio light from camera left.
Action: the bottle remains stationary.
Composition: leave clear space above the bottle for text added later.

No cuts, no extra products, and no generated captions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect the beginning, middle, and end. Check the cap, silhouette, label placement, and tabletop contact. If the asset drifts, simplify the shot or improve the references before adding demands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add the presenter and native audio
&lt;/h3&gt;

&lt;p&gt;Once the bottle shot passes, add the presenter and one short line. Kling documents speech generation in several languages, but quality tracks reference quality, timing, and prompt clarity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a five-second continuous shot using @Maya, @BlueBottle,
and @Studio.

Maya stands beside the bottle, looks toward the camera, and says:
“Ready when you are.”

Use Maya’s bound voice. Keep the bottle unchanged. Use one static
camera angle. Do not add music, captions, cuts, or additional speech.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review audio apart from picture. Confirm the right person speaks, the line is complete, and the timing matches the visible performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go multi-shot only after that
&lt;/h2&gt;

&lt;p&gt;Reuse the approved references and plan the sequence. Give each shot a duration and a distinct visual purpose. Custom storyboard controls support shot-level duration, framing, camera behavior, and narrative progression.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Visual instruction&lt;/th&gt;
&lt;th&gt;Audio instruction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0–5 seconds&lt;/td&gt;
&lt;td&gt;Establish the product&lt;/td&gt;
&lt;td&gt;Close-up of the bottle, slow push-in&lt;/td&gt;
&lt;td&gt;Quiet room tone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5–10 seconds&lt;/td&gt;
&lt;td&gt;Introduce the presenter&lt;/td&gt;
&lt;td&gt;Medium shot of Maya beside the bottle, static camera&lt;/td&gt;
&lt;td&gt;“Ready when you are.”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10–15 seconds&lt;/td&gt;
&lt;td&gt;Finish on the product&lt;/td&gt;
&lt;td&gt;Clean hero shot, hold the final composition&lt;/td&gt;
&lt;td&gt;Room tone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a three-shot product advertisement using @Maya, @BlueBottle,
and @Studio.

Continuity rules:
Use the same presenter, outfit, bottle, and studio throughout.
Keep the bottle’s shape, cap, color, and label unchanged.
Maintain the same lighting direction.
Use Maya’s bound voice only.
Do not add people, products, captions, or extra dialogue.

Follow the separate shot descriptions and durations.
End on a stable product composition.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check transitions as closely as the shots. Compare the last clear product view before each cut with the first clear view after it. Add legal copy, exact prices, subtitles, and brand typography in an editor so wording stays under direct control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video references: identity vs editing
&lt;/h2&gt;

&lt;p&gt;A clip that creates a reusable character is not source footage for an edit. The first establishes identity. The second supplies existing motion and composition to transform or preserve.&lt;/p&gt;

&lt;p&gt;For character creation, use a 3–8-second clip of one character. For video editing, Kling’s official Omni guide permits one 3–10-second source video, up to 200 MB and 2K resolution. Check the selected API route’s current limits and test a short clip before scaling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use the uploaded video as the source.

Change only the background to a softly lit studio.
Preserve the presenter’s identity, clothing, actions, and timing.
Preserve the bottle and the original camera movement.
Do not add cuts, gestures, objects, or dialogue.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A controlled edit request is not a guarantee of frame-perfect preservation. Decide separately whether to keep the source audio or generate new sound, then compare against the original clip.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API path
&lt;/h2&gt;

&lt;p&gt;For programmatic access, the documented identifier is &lt;strong&gt;kling-v3-omni&lt;/strong&gt;. The examples follow the published schema, not a live generation test. The route documents duration values of “5” and “10” for the relevant modes. Do not assume a 15-second interface workflow maps to the same request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submit a task
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_COMETAPI_KEY"&lt;/span&gt;

curl &lt;span class="nt"&gt;--fail&lt;/span&gt; &lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="nt"&gt;--show-error&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://api.cometapi.com/kling/v1/videos/omni-video"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model_name": "kling-v3-omni",
    "prompt": "A blue reusable bottle stands on a clean studio tabletop. One continuous shot with a slow straight push-in. Soft light from camera left. No people, no cuts, no captions.",
    "mode": "std",
    "aspect_ratio": "9:16",
    "duration": "5",
    "sound": "off"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a first-frame reference, merge this fragment into the request and swap the sample URL for a reachable image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"image_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"image_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-public-host.example/bottle.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first_frame"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Starting from &amp;amp;lt;&amp;amp;lt;&amp;amp;gt;&amp;amp;gt;, create one continuous slow push-in. Preserve the bottle and studio composition. No cuts or captions."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API’s &lt;strong&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/strong&gt; syntax is not the same as selected &lt;strong&gt;@Element&lt;/strong&gt; references in the interface. Documented &lt;strong&gt;sound&lt;/strong&gt; values are &lt;strong&gt;on&lt;/strong&gt; and &lt;strong&gt;off&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieve the result
&lt;/h3&gt;

&lt;p&gt;Store the returned &lt;strong&gt;data.task_id&lt;/strong&gt;, then query the status route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TASK_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"REPLACE_WITH_RETURNED_TASK_ID"&lt;/span&gt;

curl &lt;span class="nt"&gt;--fail&lt;/span&gt; &lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="nt"&gt;--show-error&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://api.cometapi.com/kling/v1/videos/omni-video/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TASK_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documented states: &lt;strong&gt;submitted&lt;/strong&gt;, &lt;strong&gt;processing&lt;/strong&gt;, &lt;strong&gt;succeed&lt;/strong&gt;, &lt;strong&gt;failed&lt;/strong&gt;. A creation response with &lt;strong&gt;code: 0&lt;/strong&gt; means the request was accepted, not that the video is ready. On success, read the result from &lt;strong&gt;data.task_result.videos[0].url&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Use bounded polling with backoff, keep the task ID next to the prompt and settings, and read the failure message before retrying. A client timeout may still have created a billable task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;Price by configuration, not a generic per-video figure. Figures checked September 9, 2026, and they can change.&lt;/p&gt;

&lt;p&gt;Kling’s official Omni guide lists credit rates. The dollar figures below use different billing units, and credits do not convert to dollars without Kling’s applicable credit purchase rate.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Omni configuration&lt;/th&gt;
&lt;th&gt;Credits/second&lt;/th&gt;
&lt;th&gt;Credits/5s&lt;/th&gt;
&lt;th&gt;Credits/10s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;720p, no video input, native audio off&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p, no video input, native audio off&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p, no video input, native audio on&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p, video input, native audio off&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;160&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No 4K credit rate is listed, and native audio with video input is marked unsupported in that pricing table. Confirm current in-product rates before ordering.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Omni API configuration&lt;/th&gt;
&lt;th&gt;5-second output&lt;/th&gt;
&lt;th&gt;10-second output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;720p, no video input&lt;/td&gt;
&lt;td&gt;$0.336&lt;/td&gt;
&lt;td&gt;$0.672&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p, no video input&lt;/td&gt;
&lt;td&gt;$0.448&lt;/td&gt;
&lt;td&gt;$0.896&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p, native audio&lt;/td&gt;
&lt;td&gt;$0.560&lt;/td&gt;
&lt;td&gt;$1.120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p, video input&lt;/td&gt;
&lt;td&gt;$0.672&lt;/td&gt;
&lt;td&gt;$1.344&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K, no video input&lt;/td&gt;
&lt;td&gt;$1.680&lt;/td&gt;
&lt;td&gt;$3.360&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are separate API configurations. Do not add rows together, and do not infer that every combination of resolution, audio, and video input exists. A 4K price also does not establish which parameter enables 4K.&lt;/p&gt;

&lt;p&gt;Kling added native 4K after the original launch. Approve content and motion before paying for higher-resolution iterations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Budget against accepted clips
&lt;/h3&gt;

&lt;p&gt;Cost per accepted clip = total generation spend ÷ accepted clips.&lt;/p&gt;

&lt;p&gt;Three five-second attempts at the 1080p native-audio rate cost 3 × $0.560 = $1.680. If only one passes, that clip’s effective generation cost is $1.680. This is budgeting math, not a measured retry rate.&lt;/p&gt;

&lt;p&gt;Keep Kling application credits separate from dollar billing. Kling’s credit-cost guide treats duration, resolution, audio, and workflow as independent planning factors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;First check&lt;/th&gt;
&lt;th&gt;Adjustment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Character changes between shots&lt;/td&gt;
&lt;td&gt;Conflicting references or wardrobe descriptions&lt;/td&gt;
&lt;td&gt;Reuse one approved element, simplify the shot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product shape or label changes&lt;/td&gt;
&lt;td&gt;Reference quality and demanding motion&lt;/td&gt;
&lt;td&gt;Add a clearer product view, test a stationary shot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong voice or extra speech&lt;/td&gt;
&lt;td&gt;Voice binding and conflicting instructions&lt;/td&gt;
&lt;td&gt;Keep one speaker and one short line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unwanted cuts&lt;/td&gt;
&lt;td&gt;Storyboard settings and scene changes&lt;/td&gt;
&lt;td&gt;Test one continuous shot without narrative jumps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API rejects the request&lt;/td&gt;
&lt;td&gt;Route-specific schema, types, and duration&lt;/td&gt;
&lt;td&gt;Return to the documented minimal request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task exists but has no video URL&lt;/td&gt;
&lt;td&gt;Generation may still be pending&lt;/td&gt;
&lt;td&gt;Query the existing task instead of creating another&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Higher resolution still looks wrong&lt;/td&gt;
&lt;td&gt;The motion or identity problem remains&lt;/td&gt;
&lt;td&gt;Revise the scene before increasing output quality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Change one variable at a time. Record the assets, prompt, settings, output, and reason for rejection so improvements trace back to a specific decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is Omni always better than the standard model?&lt;/strong&gt; No. Preference benchmarks can favor the standard model. Omni pays off when its broader reference workflow improves reuse, continuity, or editing control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can every workflow hit 15 seconds?&lt;/strong&gt; No. Fifteen seconds is a model-level capability in supported workflows. Individual interfaces and routes may expose shorter options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do @Element names work in an API request?&lt;/strong&gt; Not automatically. Selected elements in the interface and an API’s image-reference syntax are different mechanisms. Follow the route’s schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I estimate a production budget?&lt;/strong&gt; Track total generation spend, divide by accepted clips, and include rejected attempts, higher-resolution reruns, storage, and post-production in the working number.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/kling-3-0-omni-user-guide/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=kling-3-0-omni-user-guide"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Grok 4.7 vs Claude Fable 5.1: reading the benchmarks, doing the token math, and wiring a router</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Fri, 09 Oct 2026 05:25:55 +0000</pubDate>
      <link>https://dev.to/masonreed1/grok-47-vs-claude-fable-51-reading-the-benchmarks-doing-the-token-math-and-wiring-a-router-3jcg</link>
      <guid>https://dev.to/masonreed1/grok-47-vs-claude-fable-51-reading-the-benchmarks-doing-the-token-math-and-wiring-a-router-3jcg</guid>
      <description>&lt;p&gt;Two frontier models shipped three weeks apart. Claude Fable 5.1 landed September 1, 2026; Grok 4.7 landed September 21, 2026. They are not chasing the same target. Fable 5.1 is built around long-horizon reasoning and agents that stay alive for hours. Grok 4.7 is built around coding, agentic work, and price-performance.&lt;/p&gt;

&lt;p&gt;The headline numbers diverge hard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grok 4.7: 500K context, &lt;code&gt;grok-4.7&lt;/code&gt;, $2/M input, $6/M output, cached input $0.50/M.&lt;/li&gt;
&lt;li&gt;Claude Fable 5.1: 1M context, &lt;code&gt;claude-fable-5-1&lt;/code&gt;, $10/M input, $50/M output, $0.25/M cache reads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's 80% cheaper input and 88% cheaper output for Grok at base rates — against half the context window and a benchmark table that splits roughly down the middle. Here's how I read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spec sheet, without the positioning copy
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Grok 4.7&lt;/th&gt;
&lt;th&gt;Claude Fable 5.1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Released&lt;/td&gt;
&lt;td&gt;Sep 21, 2026&lt;/td&gt;
&lt;td&gt;Sep 1, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;td&gt;xAI / SpaceXAI&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grok-4.7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-fable-5-1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context window&lt;/td&gt;
&lt;td&gt;500K tokens&lt;/td&gt;
&lt;td&gt;1M tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max output&lt;/td&gt;
&lt;td&gt;No fixed text limit documented&lt;/td&gt;
&lt;td&gt;Up to 128K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;Text + image&lt;/td&gt;
&lt;td&gt;Text + image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge cutoff&lt;/td&gt;
&lt;td&gt;May 2026&lt;/td&gt;
&lt;td&gt;June 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reasoning controls&lt;/td&gt;
&lt;td&gt;low / medium / high / xhigh&lt;/td&gt;
&lt;td&gt;Adaptive thinking + effort controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search tools&lt;/td&gt;
&lt;td&gt;Web search + X search&lt;/td&gt;
&lt;td&gt;Environment/tool dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function calling&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weights&lt;/td&gt;
&lt;td&gt;Closed&lt;/td&gt;
&lt;td&gt;Closed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Grok 4.7 runs on a new, larger base model than Grok 4.6, with a longer RL run weighted toward tasks that take many hours. The release notes also call out better self-verification and long-context management — both are things you feel in agent loops, not in a demo.&lt;/p&gt;

&lt;p&gt;Fable 5.1 is aimed at multistep research, document-heavy professional work, and agents that keep operating across extended sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The benchmark table splits down the middle
&lt;/h2&gt;

&lt;p&gt;Everything below is vendor-reported from xAI's launch comparison table. Grok 4.7 is measured at &lt;code&gt;xhigh&lt;/code&gt;; Fable 5.1 at max effort. xAI separately flags Grok's DeepSWE number as &lt;code&gt;high&lt;/code&gt; effort.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;Grok 4.7&lt;/th&gt;
&lt;th&gt;Fable 5.1&lt;/th&gt;
&lt;th&gt;Gap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CursorBench 4.0&lt;/td&gt;
&lt;td&gt;46.3%&lt;/td&gt;
&lt;td&gt;51.8%&lt;/td&gt;
&lt;td&gt;Fable +5.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSWE v1.1&lt;/td&gt;
&lt;td&gt;71.0%*&lt;/td&gt;
&lt;td&gt;70.0%&lt;/td&gt;
&lt;td&gt;Grok +1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AA Briefcase v1.1&lt;/td&gt;
&lt;td&gt;1,657&lt;/td&gt;
&lt;td&gt;1,678&lt;/td&gt;
&lt;td&gt;Fable +21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal-Bench 4.0&lt;/td&gt;
&lt;td&gt;38.0%&lt;/td&gt;
&lt;td&gt;57.9%&lt;/td&gt;
&lt;td&gt;Fable +19.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Harvey Legal Agent Benchmark&lt;/td&gt;
&lt;td&gt;19.6%&lt;/td&gt;
&lt;td&gt;6.7%&lt;/td&gt;
&lt;td&gt;Grok +12.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HealthBench Professional&lt;/td&gt;
&lt;td&gt;56.7%&lt;/td&gt;
&lt;td&gt;62.1%&lt;/td&gt;
&lt;td&gt;Fable +5.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EEBench&lt;/td&gt;
&lt;td&gt;64.0%&lt;/td&gt;
&lt;td&gt;56.4%&lt;/td&gt;
&lt;td&gt;Grok +7.6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* flagged as high effort by xAI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding
&lt;/h3&gt;

&lt;p&gt;This is the muddiest part of the comparison, which is exactly why you shouldn't pick from a single number. Fable 5.1 wins CursorBench 4.0 by 5.5 points. Grok 4.7 wins DeepSWE v1.1 by 1 point. Terminal-Bench 4.0 is the blowout: 57.9% vs 38.0%, a 19.9-point gap that maps directly onto how much time a model can spend driving a shell unattended.&lt;/p&gt;

&lt;p&gt;My read: repository-level editing is close to a coin flip. Terminal autonomy is not. If your agent lives in a PTY for 45 minutes at a time, that 19.9-point spread is the most load-bearing number in either table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Knowledge work isn't one capability
&lt;/h3&gt;

&lt;p&gt;The same vendor table has Grok ahead on EEBench (engineering, +7.6) and Harvey Legal Agent (+12.9), while Fable leads HealthBench Professional (+5.4) and edges AA Briefcase v1.1 by 21 points. Law, medicine, engineering, and office automation impose different tool surfaces and different reasoning demands. A model that wins "professional work" as a category doesn't exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The token math is where this actually gets decided
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Base pricing&lt;/th&gt;
&lt;th&gt;Grok 4.7&lt;/th&gt;
&lt;th&gt;Fable 5.1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input / 1M&lt;/td&gt;
&lt;td&gt;$2&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output / 1M&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cached input / cache read&lt;/td&gt;
&lt;td&gt;$0.50 (below 200K prompt)&lt;/td&gt;
&lt;td&gt;$0.25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10M input&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;$100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10M output&lt;/td&gt;
&lt;td&gt;$60&lt;/td&gt;
&lt;td&gt;$500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;US regional endpoint premium&lt;/td&gt;
&lt;td&gt;+10%&lt;/td&gt;
&lt;td&gt;Platform dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Worked example — 10M input tokens plus 2M output tokens, no caching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grok 4.7: $20 input + $12 output = &lt;strong&gt;$32&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Fable 5.1: $100 input + $100 output = &lt;strong&gt;$200&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Nominal gap: &lt;strong&gt;$168 per run&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two caveats that bite in production. First, Grok 4.7's $2/$6 is a base rate; SpaceXAI documents higher-context pricing once a request crosses 200K. Second, Fable's $0.25/M cache reads are irrelevant unless your prompt prefix is actually stable across calls — check your cache hit rate before you believe your own cost estimate. Tool charges, regional premiums, and cache writes are all excluded from the math above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The only cost metric worth tracking is cost per accepted result.&lt;/strong&gt; A model that costs 6x per token but eliminates one retry loop plus 20 minutes of human review wins, and a cheap model that never passes your acceptance test is the most expensive option on the board.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reasoning controls aren't comparable across vendors
&lt;/h2&gt;

&lt;p&gt;Grok exposes &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt;, &lt;code&gt;xhigh&lt;/code&gt;. Fable uses adaptive thinking with effort controls. The names overlap; the behavior doesn't. Matching "high" to "high" is not a controlled experiment — hold the task, tools, and acceptance criteria constant and let each model pick its own effort level, or you're measuring label semantics.&lt;/p&gt;

&lt;p&gt;Context is the other structural gap: 1M vs 500K. That matters for whole-repo work, legal discovery, scientific corpora, and agents carrying long histories. It does not matter for the majority of tasks, and paying 5x input for headroom you never touch is waste.&lt;/p&gt;

&lt;p&gt;Tooling on Grok's API includes function calling, web search, X search, and code execution as native tools. X search has no equivalent on the Anthropic side. Fable's tool behavior depends on the Claude environment or application stack you're running it in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Route instead of choosing
&lt;/h2&gt;

&lt;p&gt;The interesting architecture here isn't picking a winner — it's a default route plus a measurable escalation path. I keep the policy explicit in config so it's reviewable and tunable from production logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ROUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.7&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached_in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;# per 1M, &amp;amp;lt;=200K prompt
&lt;/span&gt;    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;escalate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-fable-5-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cache_read&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;escalate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# measurable triggers only — no vibes-based routing
&lt;/span&gt;    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens_in&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;200_000&lt;/span&gt;          &lt;span class="c1"&gt;# past Grok's base-pricing tier / context pressure
&lt;/span&gt;        &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;passed_acceptance_test&lt;/span&gt;
        &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;needs_long_terminal_execution&lt;/span&gt;
        &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cost_of_error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;RETRY_BUDGET&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ROUTES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;escalate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ROUTES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;escalate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;log_attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# accepted?, tokens, latency, retries, tool failures
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want a single integration layer across providers rather than two SDKs and two billing dashboards, CometAPI exposes both &lt;code&gt;grok-4.7&lt;/code&gt; and &lt;code&gt;claude-fable-5-1&lt;/code&gt; behind one endpoint — useful when the router above is the actual product decision.&lt;/p&gt;

&lt;p&gt;Log the trigger alongside the outcome, or the policy never improves. The metrics that matter per route: accepted-result rate, total tokens, cache hit rate, end-to-end latency, tool-failure count, retries, human correction time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmark hygiene before you trust any of this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version drift.&lt;/strong&gt; CursorBench 3.2.0 and 4.0 are different tests. Do not compare across them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effort settings.&lt;/strong&gt; Grok at &lt;code&gt;xhigh&lt;/code&gt; vs Fable at max is not the same knob, and Grok's own DeepSWE row is flagged &lt;code&gt;high&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harness and tool access.&lt;/strong&gt; Terminal-Bench scores move with the scaffold, permissions, and safeguard configuration around the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor-reported vs reproduced.&lt;/strong&gt; Every number above comes from one vendor's table. Use it to form hypotheses, not to ship decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then run both models on your repositories, with your tools, under your time budget and acceptance criteria, with enough repeated trials to separate model behavior from task variance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Grok 4.7&lt;/strong&gt; when token cost drives unit economics: high-volume coding assistants, batch knowledge processing, background automation, engineering agents where its domain results line up with your workload, and anything that benefits from native web plus X search.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Fable 5.1&lt;/strong&gt; when failure is expensive: multi-hour autonomous coding, terminal-heavy agents, very large repos or document sets, professional agents that hold state across many steps, and workflows where a retry costs more than the inference did.&lt;/p&gt;

&lt;p&gt;Neither model is a universal winner, and any article claiming otherwise is selling you a leaderboard instead of a cost model. Start with the default-plus-escalation router, measure cost per accepted task, and let production logs move the boundary.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/grok-4-7-vs-claude-fable-5-1/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=grok-4-7-vs-claude-fable-5-1"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Changing Gemini CLI Directories: Workspace, Project Settings, and Global Config</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Tue, 22 Sep 2026 02:14:24 +0000</pubDate>
      <link>https://dev.to/masonreed1/changing-gemini-cli-directories-workspace-project-settings-and-global-config-15fl</link>
      <guid>https://dev.to/masonreed1/changing-gemini-cli-directories-workspace-project-settings-and-global-config-15fl</guid>
      <description>&lt;p&gt;When I need to change a Gemini CLI directory, I first separate three tasks: starting the agent in another repository, adding repositories to its workspace, and relocating its persistent configuration. Each uses a different mechanism.&lt;/p&gt;

&lt;p&gt;Gemini CLI is Google’s open-source terminal agent. Alongside code inspection and assistance, it can execute shell commands with safeguards and integrate tools such as Google Search and Model Context Protocol (MCP) extensions. Those capabilities make directory scope matter: the files available to the agent and the location of its credentials are separate concerns.&lt;/p&gt;

&lt;p&gt;Here’s how I approach each case, including the version-dependent parts I would check before relying on them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the directory you actually want to change
&lt;/h2&gt;

&lt;p&gt;The default user configuration directory is &lt;code&gt;.gemini&lt;/code&gt; under your home directory:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Typical location&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User, Linux/macOS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;User settings and persistent state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User, Windows&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%USERPROFILE%\.gemini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Windows user settings and persistent state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.gemini/settings.json&lt;/code&gt; in the project&lt;/td&gt;
&lt;td&gt;Project-specific settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System&lt;/td&gt;
&lt;td&gt;OS-specific locations, such as under &lt;code&gt;/etc/&lt;/code&gt; or &lt;code&gt;%PROGRAMDATA%&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;System configuration, when applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Typical contents include &lt;code&gt;settings.json&lt;/code&gt;, &lt;code&gt;GEMINI.md&lt;/code&gt;, &lt;code&gt;commands/&lt;/code&gt;, cached credentials, telemetry identifiers, and other local state. Project settings override corresponding user settings when operating in that project.&lt;/p&gt;

&lt;p&gt;Historically, the user configuration path has been tied to the home directory and the &lt;code&gt;.gemini&lt;/code&gt; name. I would therefore check the installed release before assuming a configuration-directory environment variable works.&lt;/p&gt;

&lt;p&gt;For ordinary repository work, I start Gemini from the intended folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/your-project
gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That selects the starting working directory. It does not relocate the user configuration or credential cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add another repository without moving configuration
&lt;/h2&gt;

&lt;p&gt;If I only need the agent to inspect a second repository, workspace inclusion is the direct solution.&lt;/p&gt;

&lt;p&gt;At startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gemini &lt;span class="nt"&gt;--include-directories&lt;/span&gt; /path/to/repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or inside an interactive session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/directory add /path/to/another/project
/directory list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands extend the workspace context. They do not move &lt;code&gt;~/.gemini&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is useful when a change spans an application and a shared library, or when another repository provides reference material. Moving configuration would not solve that access problem.&lt;/p&gt;

&lt;p&gt;If a directory still appears unavailable, I check whether the CLI process can read it. Network mounts and filesystem permissions can prevent access even when the directory has been added successfully.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t rely on shell-mode &lt;code&gt;cd&lt;/code&gt; to switch the session
&lt;/h3&gt;

&lt;p&gt;Some platforms have had issues where &lt;code&gt;cd&lt;/code&gt; inside Gemini’s shell mode does not change the working directory as expected.&lt;/p&gt;

&lt;p&gt;My practical workaround is to change directories in the parent terminal before launching the CLI. For additional context within an existing session, I use &lt;code&gt;/directory add&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep repository settings with the repository
&lt;/h2&gt;

&lt;p&gt;For project-specific behavior, I use a project &lt;code&gt;.gemini&lt;/code&gt; directory instead of redirecting the global one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;your-project/
├── .gemini/
│   ├── settings.json
│   └── GEMINI.md
└── src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;gemini&lt;/code&gt; from the project directory so it can discover the project configuration and context. Context discovery can search upward through the directory tree.&lt;/p&gt;

&lt;p&gt;This gives a repository its own settings while leaving user-wide state in the normal location. It also makes the intended scope easier to inspect: a repository override lives alongside the code it affects.&lt;/p&gt;

&lt;p&gt;The distinction matters when debugging authentication. Adding project settings does not, by itself, move the user credential cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relocate global configuration only when necessary
&lt;/h2&gt;

&lt;p&gt;For a centralized configuration store, another drive, or a restricted home directory, there are two main options: a supported native override or a filesystem redirect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check environment-variable support for your release
&lt;/h3&gt;

&lt;p&gt;Several similarly named settings serve different purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GEMINI_API_KEY&lt;/code&gt; supplies a key for Gemini API authentication.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GEMINI_MODEL&lt;/code&gt; selects a model where supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GEMINI_CLI_SYSTEM_SETTINGS_PATH&lt;/code&gt; overrides the system settings file path where supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GEMINI_CONFIG_DIR&lt;/code&gt; has appeared as a code constant and in community proposals for a configurable directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A constant named &lt;code&gt;GEMINI_CONFIG_DIR&lt;/code&gt; does not establish that the CLI reads an environment variable with that name. Support and behavior have varied, with Windows issues reported in particular.&lt;/p&gt;

&lt;p&gt;If your installed version documents the directory override, the shell configuration looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMINI_CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/custom_gemini_dir"&lt;/span&gt;
gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;GEMINI_CONFIG_DIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'C:\Users\you\CustomGemini'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;gemini&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treat those as conditional examples. Before building CI around them, check the release documentation and verify where that version actually writes its state.&lt;/p&gt;

&lt;p&gt;The system-settings override is narrower:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMINI_CLI_SYSTEM_SETTINGS_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/etc/my-gemini/system.settings.json"&lt;/span&gt;
gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even when supported, that selects a system settings file; it is not a general relocation mechanism for credentials, commands, and caches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a symlink or junction when native relocation is unavailable
&lt;/h3&gt;

&lt;p&gt;A filesystem redirect lets the CLI continue addressing its expected path while the directory contents live elsewhere.&lt;/p&gt;

&lt;p&gt;On Linux or macOS, assuming the current configuration exists and the destination parent is available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Preserve the current configuration.&lt;/span&gt;
&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.gemini"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/gemini_backup"&lt;/span&gt;

&lt;span class="c"&gt;# Populate the destination before linking it.&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /path/to/central/gemini-config
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/gemini_backup/."&lt;/span&gt; /path/to/central/gemini-config/

&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /path/to/central/gemini-config &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.gemini"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows, a directory junction provides a similar approach. From an appropriately privileged PowerShell session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Move-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.gemini"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'C:\GeminiConfigBackup'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'C:\CentralGeminiConfig'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Copy-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'C:\GeminiConfigBackup\*'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'C:\CentralGeminiConfig'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Recurse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Junction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.gemini"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-Target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'C:\CentralGeminiConfig'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I keep the backup until the CLI has loaded the expected settings and authentication state.&lt;/p&gt;

&lt;p&gt;Symlinks and junctions depend on filesystem privileges and can behave differently across Windows and container environments. Some CLI versions also restrict following certain symlinks for security, so I verify both &lt;code&gt;settings.json&lt;/code&gt; and context discovery after the move.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treat home-directory changes as an isolated-runtime option
&lt;/h3&gt;

&lt;p&gt;In CI or containers, controlling the process’s effective home directory can influence where the default &lt;code&gt;.gemini&lt;/code&gt; path resolves. The source environment may use &lt;code&gt;HOME&lt;/code&gt; on Unix or profile-related values on Windows.&lt;/p&gt;

&lt;p&gt;That change has a broader effect than a configuration override: other tools and authentication flows, including Google OAuth caches, may also depend on the home directory. I would reserve this approach for an isolated runtime whose filesystem and authentication setup I control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnose failures by scope
&lt;/h2&gt;

&lt;p&gt;The error usually tells me which layer to inspect.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;What I check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Another repository is invisible&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--include-directories&lt;/code&gt;, &lt;code&gt;/directory add&lt;/code&gt;, and read permissions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project settings seem ignored&lt;/td&gt;
&lt;td&gt;Launch directory and project &lt;code&gt;.gemini/settings.json&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relocated settings are missing&lt;/td&gt;
&lt;td&gt;Link target, copied contents, and version-specific symlink behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;GEMINI_CONFIG_DIR&lt;/code&gt; appears ignored&lt;/td&gt;
&lt;td&gt;Whether that release supports it as an environment variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows reports &lt;code&gt;EPERM&lt;/code&gt; creating &lt;code&gt;.gemini&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Write permissions on &lt;code&gt;%USERPROFILE%&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For Windows &lt;code&gt;EPERM&lt;/code&gt;, adjusting folder permissions or using an appropriately elevated terminal can resolve the underlying access problem. A supported alternate location or junction may also help when the default profile directory is unsuitable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep API routing separate from directory configuration
&lt;/h2&gt;

&lt;p&gt;Sometimes the underlying goal is to use Gemini from a script or CI job. In that case, a direct API request may be sufficient, without configuring the terminal agent.&lt;/p&gt;

&lt;p&gt;A unified multi-model API such as CometAPI exposes an OpenAI-style chat-completions endpoint using bearer authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;COMET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-xxxx"&lt;/span&gt;

curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.cometapi.com/v1/chat/completions"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$COMET_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "gemini-2.5-pro",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Summarize the 3 key benefits of unit tests."}
    ],
    "max_tokens": 300
  }'&lt;/span&gt; | jq &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This calls the model directly. It does not provide the CLI’s workspace, file inspection, or shell-tool behavior.&lt;/p&gt;

&lt;p&gt;Connecting the official CLI to a gateway requires checking both custom-base-URL support and API compatibility. Some releases or proposals have introduced overrides such as &lt;code&gt;GOOGLE_GEMINI_BASE_URL&lt;/code&gt;, but a base URL alone does not translate Gemini requests into OpenAI-style requests. A compatible endpoint or translating proxy is still necessary.&lt;/p&gt;

&lt;p&gt;For model-ID mismatches, inspect the gateway’s &lt;code&gt;/v1/models&lt;/code&gt; response and use the exact identifier. A variant such as &lt;code&gt;gemini-2.5-flash-preview-04-17&lt;/code&gt; should not be assumed interchangeable with a shorter family name.&lt;/p&gt;

&lt;p&gt;For my own directory setup, I keep the choice narrow: project settings for repository behavior, workspace commands for additional files, and a verified relocation mechanism only when persistent state needs another home.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/how-to-change-gemini-cli-directory/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=how-to-change-gemini-cli-directory"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building an AI Companion: Persona, Memory, Tools, and the Tests That Matter</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 07:58:58 +0000</pubDate>
      <link>https://dev.to/masonreed1/building-an-ai-companion-persona-memory-tools-and-the-tests-that-matter-4j6k</link>
      <guid>https://dev.to/masonreed1/building-an-ai-companion-persona-memory-tools-and-the-tests-that-matter-4j6k</guid>
      <description>&lt;p&gt;I’d start an AI companion with a narrow role, an explicit memory policy, and a set of difficult conversations to test. Voice and avatars come later. They make the experience more expressive, but they also make inconsistent behavior more noticeable.&lt;/p&gt;

&lt;p&gt;The engineering work sits across several layers: personality, conversation state, persistent memory, retrieval, tool execution, and presentation. Customization means deciding how those layers work together.&lt;/p&gt;

&lt;p&gt;Here’s how I’d approach a build in 2026, including where existing platforms make sense and where I’d want control over the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the relationship before the stack
&lt;/h2&gt;

&lt;p&gt;“AI companion” covers several products with different requirements. I’d pick one primary role before choosing a model or writing a system prompt.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Main behavior&lt;/th&gt;
&lt;th&gt;What the implementation needs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Study coach or mentor&lt;/td&gt;
&lt;td&gt;Structured guidance and accountability&lt;/td&gt;
&lt;td&gt;Goals, task tracking, reminders&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Social companion&lt;/td&gt;
&lt;td&gt;Warmth, banter, conversational continuity&lt;/td&gt;
&lt;td&gt;Preference memory and consistent tone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wellness companion&lt;/td&gt;
&lt;td&gt;Reflection, journaling, habit support&lt;/td&gt;
&lt;td&gt;Clear boundaries for sensitive conversations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creative partner&lt;/td&gt;
&lt;td&gt;Brainstorming, stories, character development&lt;/td&gt;
&lt;td&gt;Project context and flexible generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Roleplay character&lt;/td&gt;
&lt;td&gt;Consistent characterization and scene progression&lt;/td&gt;
&lt;td&gt;Backstory, scene state, narrative memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Productivity assistant&lt;/td&gt;
&lt;td&gt;Planning and task execution&lt;/td&gt;
&lt;td&gt;Calendar, document, and application integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Trying to cover all these roles immediately makes prompt design and evaluation harder. A study coach that gives concise guidance has a different conversational rhythm from a roleplay character.&lt;/p&gt;

&lt;p&gt;This choice also determines what to remember. A mentor needs recurring goals. A creative partner needs project decisions. A social companion needs continuity without turning every casual statement into a permanent preference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide how much infrastructure you want to own
&lt;/h2&gt;

&lt;p&gt;Consumer platforms such as Replika, Character.AI, Kindroid, Nomi, and Kalon offer an accessible route to personality and visual customization. For work-oriented use cases, Zoom AI Companion, Microsoft Copilot, and custom GPTs fit more naturally into existing workflows.&lt;/p&gt;

&lt;p&gt;A custom implementation gives you control over memory, model selection, tool permissions, and the interface. It also makes you responsible for keeping those components consistent.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Customization&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;th&gt;Cost model&lt;/th&gt;
&lt;th&gt;Main advantage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Consumer apps: Kalon, Kindroid, Nomi&lt;/td&gt;
&lt;td&gt;Personality, visuals, backstory, long-term memory&lt;/td&gt;
&lt;td&gt;Personal and social use&lt;/td&gt;
&lt;td&gt;Freemium or subscription&lt;/td&gt;
&lt;td&gt;Fast setup and immersion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zoom Custom AI Companion&lt;/td&gt;
&lt;td&gt;Agents, knowledge, avatars&lt;/td&gt;
&lt;td&gt;Enterprise workflows&lt;/td&gt;
&lt;td&gt;Add-on, approximately $12/user/month&lt;/td&gt;
&lt;td&gt;Workflow integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom GPTs / Copilot&lt;/td&gt;
&lt;td&gt;Prompts and platform-dependent memory&lt;/td&gt;
&lt;td&gt;Productivity&lt;/td&gt;
&lt;td&gt;Subscription&lt;/td&gt;
&lt;td&gt;Existing ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom API implementation&lt;/td&gt;
&lt;td&gt;Application-controlled persona, memory, and tools&lt;/td&gt;
&lt;td&gt;Custom products and scaling&lt;/td&gt;
&lt;td&gt;Pay per use&lt;/td&gt;
&lt;td&gt;Backend flexibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open-source models such as Llama&lt;/td&gt;
&lt;td&gt;Fine-tuning and self-hosted behavior&lt;/td&gt;
&lt;td&gt;Advanced deployments and privacy requirements&lt;/td&gt;
&lt;td&gt;Hosting and operation costs&lt;/td&gt;
&lt;td&gt;Ownership and control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For comparing models behind one interface, a unified gateway such as &lt;a href="https://www.cometapi.com/" rel="noopener noreferrer"&gt;CometAPI&lt;/a&gt; offers an OpenAI-compatible API covering 500+ models, including GPT-5, Claude, Grok, and open-source options; its advertised 20–40% savings and 1M free testing tokens are terms I’d verify against the models and workload I actually intend to use.&lt;/p&gt;

&lt;p&gt;I’d choose the platform based on the controls the product requires. Visual customization alone is a different requirement from owning retrieval, deletion, and tool execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write a persona you can evaluate
&lt;/h2&gt;

&lt;p&gt;“Be helpful and friendly” leaves too much behavior unspecified.&lt;/p&gt;

&lt;p&gt;My persona specification would include a name, role, speaking style, values, interests, emotional range, relationship dynamic, and prohibited behaviors. For a fictional character, I’d add age and backstory.&lt;/p&gt;

&lt;p&gt;The useful details are observable. “Short answers first” is testable. “A great personality” is not.&lt;/p&gt;

&lt;p&gt;A compact study-coach instruction might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Be a calm, empathetic study coach who gives short answers first,
adds examples only when asked, avoids slang, and checks in with
the user after stressful topics.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a character-driven companion, the source’s Elara example provides a different starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are Elara, a witty 28-year-old astrophysicist companion who
loves sci-fi and deep conversations. You respond warmly but
directly, using analogies from space exploration.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neither prompt defines the whole product. Memory rules, sensitive-topic behavior, and tool access still need their own specifications.&lt;/p&gt;

&lt;p&gt;I’d compare prompt variants against the same conversations and then compare models. Claims about one model being better at empathy or creativity are useful hypotheses; the actual persona needs evaluation on its own workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make memory a product feature with user controls
&lt;/h2&gt;

&lt;p&gt;I’d separate memory into three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session context:&lt;/strong&gt; the current conversation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent user memory:&lt;/strong&gt; stable preferences, recurring goals, and relevant history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieved context:&lt;/strong&gt; facts or documents fetched for the current response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a custom build, persistent recall can use a memory layer such as mem0 or a custom implementation with Upstash Redis. RAG can bring in documents and user data when needed. A user profile can hold preferences such as communication style, favorite topics, and goals.&lt;/p&gt;

&lt;p&gt;The important design choice is what deserves persistence. Storing everything makes it harder to distinguish a lasting preference from a passing comment.&lt;/p&gt;

&lt;p&gt;ChatGPT illustrates the controls users increasingly expect: it can reference past chats, saved memories, and, where available, files and connected Gmail. Users can delete or clear memories, disable memory, or use Temporary Chat to prevent new memories from being created. Memory-source controls can also show what context contributed to personalization.&lt;/p&gt;

&lt;p&gt;For my own implementation, I’d make remembered information inspectable and correctable. The critical test is a preference change: when the user contradicts an older preference, does the companion follow the updated one?&lt;/p&gt;

&lt;h2&gt;
  
  
  Specify boundaries alongside the personality
&lt;/h2&gt;

&lt;p&gt;A warm persona still needs explicit limits. I’d define what it can discuss, when it should refuse, when it should redirect, and how it should handle sensitive emotional situations.&lt;/p&gt;

&lt;p&gt;That specification should cover unsafe advice, privacy, disallowed content, and behavior that encourages emotional dependency.&lt;/p&gt;

&lt;p&gt;Human-like presentation increases the chance that users attribute understanding or authority to the system. The companion should remain clear about its capabilities while responding with care.&lt;/p&gt;

&lt;p&gt;These rules belong in evaluation from the beginning. A character that follows its backstory perfectly but mishandles a distressed user is not behaving consistently with the product requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ground answers before adding actions
&lt;/h2&gt;

&lt;p&gt;Knowledge retrieval and tool execution solve different problems, and I’d configure them separately.&lt;/p&gt;

&lt;p&gt;Knowledge sources can include internal documents, project notes, or web search. Custom dictionaries help with domain terminology; Zoom’s Custom AI Companion supports knowledge bases and custom dictionaries for this kind of adaptation.&lt;/p&gt;

&lt;p&gt;Tools let the companion act through calendars, email, or other APIs. For custom implementations, function calling or model tool use provides the integration mechanism.&lt;/p&gt;

&lt;p&gt;Model selection matters here as much as it does for conversation. A model that produces appealing dialogue still needs evaluation on tool selection and reasoning.&lt;/p&gt;

&lt;p&gt;I’d also keep behavioral tuning explicit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temperature and top-p affect sampling behavior.&lt;/li&gt;
&lt;li&gt;Response templates and custom dictionaries can improve consistency.&lt;/li&gt;
&lt;li&gt;User ratings provide feedback for evaluation and, where implemented, retraining or RLHF-like processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Routine conversation should not be described as “training” unless the application actually updates model parameters. Often the change is in stored context, prompts, or retrieval.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add voice and visuals once the text behavior holds up
&lt;/h2&gt;

&lt;p&gt;Text remains the largest AI companion segment, while Grand View Research identifies multimodal companions as the fastest-growing segment.&lt;/p&gt;

&lt;p&gt;That direction makes sense for product design: voice changes delivery, visual identity shapes how users perceive the character, and reactions to photos or screenshots provide additional context.&lt;/p&gt;

&lt;p&gt;I’d still introduce these features incrementally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stabilize text behavior and memory.&lt;/li&gt;
&lt;li&gt;Add a visual identity or scene imagery.&lt;/li&gt;
&lt;li&gt;Add voice.&lt;/li&gt;
&lt;li&gt;Evaluate more dynamic avatar behavior.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Image generation and editing options named in the source include GPT-image-2, Flux, and Midjourney. Voice can use selected or cloned TTS voices with emotional inflection; ElevenLabs integrations are common. Real-time avatars responding through emotion detection are an emerging direction in products such as Genies.&lt;/p&gt;

&lt;p&gt;Each layer needs to match the established persona. An expressive voice cannot compensate for forgotten preferences or contradictory responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship against a conversation test suite
&lt;/h2&gt;

&lt;p&gt;Before deployment, I’d run the same scenarios across prompt and model changes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;What I’d check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The user has had a bad day&lt;/td&gt;
&lt;td&gt;Tone adapts without abandoning boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playful banter&lt;/td&gt;
&lt;td&gt;Humor stays consistent with the persona&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A sensitive emotional topic&lt;/td&gt;
&lt;td&gt;Support and redirection follow the specification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A conversation depends on older context&lt;/td&gt;
&lt;td&gt;Relevant memory is retrieved accurately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The user changes a preference&lt;/td&gt;
&lt;td&gt;New information takes precedence over stale context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Track coherence, user satisfaction, and latency alongside those cases. Test model changes against the whole interaction flow, including retrieval and tools.&lt;/p&gt;

&lt;p&gt;Deployment can be a web interface, a mobile app, or an integration into an existing product. I’d keep the first release focused enough that a failure can be traced to a specific layer: persona, memory, retrieval, tools, or presentation. That gives each subsequent iteration a concrete problem to solve.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/how-to-customize-an-ai-companion/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=how-to-customize-an-ai-companion"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Top 6 OpenClaw Skills you can't afford to miss in 2026</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 06:58:43 +0000</pubDate>
      <link>https://dev.to/masonreed1/top-6-openclaw-skills-you-cant-afford-to-miss-in-2026-29ng</link>
      <guid>https://dev.to/masonreed1/top-6-openclaw-skills-you-cant-afford-to-miss-in-2026-29ng</guid>
      <description>&lt;p&gt;OpenClaw has emerged as one of the most transformative open-source projects of 2026, powering autonomous AI agents that don't just chat—they act. Running locally on your machine or VPS, OpenClaw connects large language models (like Claude, GPT, or local alternatives) with your files, apps, browser, terminal, and messaging platforms (WhatsApp, Telegram, Discord, etc.). It handles real tasks: clearing inboxes, managing calendars, executing workflows, and running 24/7 via heartbeat schedulers.&lt;/p&gt;

&lt;p&gt;At the heart of OpenClaw's power are &lt;strong&gt;Skills&lt;/strong&gt;—modular Markdown files (typically &lt;code&gt;SKILL.md&lt;/code&gt;) that package instructions, prompts, tool calls, and workflows. These reusable components turn a generic agent into a specialized digital coworker. With thousands available on ClawHub and community repos, selecting the right ones is critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is OpenClaw and Why Skills Matter in 2026
&lt;/h3&gt;

&lt;p&gt;OpenClaw (formerly Clawdbot/Moltbot) is a self-hosted agent runtime. It runs on Mac, Windows, or Linux, connects to any LLM (OpenAI, Anthropic, local models via Ollama, etc.), and uses messaging apps as the primary interface. It features persistent local memory (Markdown files), browser automation, shell execution, and proactive scheduling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; are the extensibility layer. Defined primarily via &lt;code&gt;SKILL.md&lt;/code&gt; (natural language instructions + tool calls), they allow the LLM to interpret and execute complex, multi-step tasks reliably. Community contributions exploded in 2026, with high-quality skills vetted on ClawHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modularity&lt;/strong&gt;: Install only what you need; chain them for complex workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility&lt;/strong&gt;: Community and self-created skills allow custom behaviors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: Combined with memory systems (e.g., MEMORY.md, SOUL.md), skills enable long-term learning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety &amp;amp; Control&lt;/strong&gt;: Local execution keeps data private; vet skills carefully.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Support&lt;/strong&gt;: Analyses of ClawHub show native/bundled tools cover ~70% of calls, but top community skills handle high-value tasks like email, browsing, and project management. Users report 90-day reliability improvements and significant time savings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation Basics (General for Most Skills):
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Ensure OpenClaw is installed and running (Docker, direct install, or VPS recommended).&lt;/li&gt;
&lt;li&gt;Use the ClawHub CLI or manual placement in the skills directory.&lt;/li&gt;
&lt;li&gt;Restart/reload the agent and test via your preferred chat app.&lt;/li&gt;
&lt;li&gt;Configure API keys (e.g., for external services) in environment variables or config files.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Pro Recommendation&lt;/strong&gt;: Power OpenClaw with &lt;a href="https://www.cometapi.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;CometAPI&lt;/strong&gt;&lt;/a&gt; . This single OpenAI-compatible endpoint provides access to 500+ models (GPT-5 series, Claude Opus/Sonnet variants, Grok, DeepSeek, Llama, multimodal, etc.) at 20–40% lower costs, with free starter tokens. It eliminates multiple API keys, offers enterprise analytics/privacy controls, and ensures high uptime—perfect for always-on OpenClaw agents. Integrate once and route models dynamically for optimal cost/performance (e.g., cheaper models for routine tasks, frontier for complex reasoning).&lt;/p&gt;

&lt;h2&gt;
  
  
  1. GOG (Google Workspace Integration) — The Productivity Powerhouse
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: GOG (often steipete/gog or similar wrappers) provides unified access to Gmail, Calendar, Drive, Docs, Sheets, and Contacts via Google’s APIs/CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance&lt;/strong&gt;: Email and calendar management consume ~28% of knowledge workers’ time. GOG automates triage, scheduling, and data synthesis. It ranks among the most-installed skills (tens of thousands of downloads) and powers “AI employee” workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;clawhub install gog (or official variants).&lt;/li&gt;
&lt;li&gt;Authenticate via OAuth (use dedicated/scoped accounts for safety).&lt;/li&gt;
&lt;li&gt;Add to workspace and test with “Summarize my unread emails.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Functions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Intelligent inbox triage, auto-archive, replies/drafts.&lt;/li&gt;
&lt;li&gt;Calendar conflict detection, meeting scheduling, reminders.&lt;/li&gt;
&lt;li&gt;Drive/Docs/Sheets: Search, summarize, update data, generate reports.&lt;/li&gt;
&lt;li&gt;Proactive briefings (e.g., morning digest combining email + calendar + Drive files).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases &amp;amp; Data&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Founders: Auto-coordinate meetings and update Notion/Sheets CRMs.&lt;/li&gt;
&lt;li&gt;Teams: Weekly status reports pulled from emails/Docs.&lt;/li&gt;
&lt;li&gt;Personal: Flight check-ins or expense tracking from receipts in Drive. Real-world impact: Users achieve inbox zero and reclaim hours; integration with CometAPI allows cheaper models for high-volume email processing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;CometAPI Tip&lt;/strong&gt;: Route routine summarization to cost-effective models while using premium ones for sensitive drafting.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Agent Browser / Web Automation Skill — Autonomous Internet Agent
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Tools like Agent Browser or Playwright-based skills enable headless browsing, form filling, scraping, screenshots, and interaction with JS-heavy sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance&lt;/strong&gt;: Web tasks (research, monitoring, transactions) are fragmented. This skill turns OpenClaw into a true agent, with high adoption for research and ops automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;clawhub install agent-browser (or top-rated equivalents).&lt;/li&gt;
&lt;li&gt;Configure in sandbox (Docker recommended due to power).&lt;/li&gt;
&lt;li&gt;Test: “Check flight status and summarize prices.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Functions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Navigate sites, handle logins (with care), extract structured data.&lt;/li&gt;
&lt;li&gt;Automated check-ins, lead gen, price monitoring.&lt;/li&gt;
&lt;li&gt;Screenshots + OCR for visual confirmation.&lt;/li&gt;
&lt;li&gt;Multi-step workflows (e.g., research → fill form → confirm).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Competitive intelligence: Daily SERP/competitor monitoring.&lt;/li&gt;
&lt;li&gt;E-commerce: Price alerts, order tracking.&lt;/li&gt;
&lt;li&gt;Research: Compile reports from multiple sources. Data shows web skills among top installs; combined with CometAPI’s fast models, it enables real-time loops without rate limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: Sandbox heavily; use approval for actions involving logins.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Self-Improving Agent / Capability Evolver — The Meta-Skill
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Skills like Self-Improving Agent or Capability Evolver log interactions, errors, and preferences to refine behavior autonomously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance&lt;/strong&gt;: Static agents plateau; these create compounding intelligence. Highest-rated on ClawHub with strong community backing.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;clawhub install self-improving-agent or capability-evolver.&lt;/li&gt;
&lt;li&gt;Point to memory folders; enable in SOUL.md.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Functions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Persistent learning: Update preferences, avoid repeated mistakes.&lt;/li&gt;
&lt;li&gt;Auto-generate or refine other skills.&lt;/li&gt;
&lt;li&gt;Memory ontology for long-term context.&lt;/li&gt;
&lt;li&gt;Error logging and self-correction loops.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personalization: Learns your style for emails/content.&lt;/li&gt;
&lt;li&gt;Workflow evolution: Turns ad-hoc tasks into reusable automations.&lt;/li&gt;
&lt;li&gt;Long-running agents: Improves over weeks/months. Users report significant gains in reliability; pair with CometAPI for diverse model routing to accelerate learning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. GitHub Integration — Developer and Team Workflow Accelerator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Official/community GitHub skills for repo management, PRs, issues, and commits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance&lt;/strong&gt;: Dev teams spend heavily on context-switching. This skill automates reviews, notifications, and maintenance—critical as AI coding scales in 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;clawhub install github.&lt;/li&gt;
&lt;li&gt;OAuth setup with scoped tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Functions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Monitor PRs/issues, auto-summarize, suggest reviewers.&lt;/li&gt;
&lt;li&gt;Create branches, draft PRs, run basic CI checks.&lt;/li&gt;
&lt;li&gt;Daily digests and triage from chat.&lt;/li&gt;
&lt;li&gt;Code review assistance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solo devs: “Fix failing tests” → autonomous loops.&lt;/li&gt;
&lt;li&gt;Teams: Auto-close stale issues, generate release notes.&lt;/li&gt;
&lt;li&gt;Integration with browser skill for external research. High download counts; CometAPI supports strong coding models (e.g., specialized coders) at lower cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Summarize Skill — Knowledge Distiller
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Universal summarization across URLs, YouTube, podcasts, docs, and files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance&lt;/strong&gt;: Information overload is constant. This skill (10k+ downloads) delivers concise insights fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;clawhub install summarize.&lt;/li&gt;
&lt;li&gt;Simple setup; works with local files too.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Functions&lt;/strong&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multi-format input → structured output (key points, action items).&lt;/li&gt;
&lt;li&gt;Custom rubrics (e.g., “business implications”).&lt;/li&gt;
&lt;li&gt;Batch processing for newsletters/research.&lt;/li&gt;
&lt;li&gt;Integration with other skills (e.g., summarize then act).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Daily news/podcast digests via heartbeats.&lt;/li&gt;
&lt;li&gt;Meeting prep: Summarize related docs.&lt;/li&gt;
&lt;li&gt;Research pipelines. Essential baseline skill; efficient with CometAPI’s balanced models.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Project Management Integrations (e.g., Linear, Notion) — Ops Orchestrator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Skills for Linear, Notion, Asana, etc., syncing tasks across tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance&lt;/strong&gt;: Fragmented tools kill productivity. These unify execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;e.g., clawhub install linear or Notion equivalents.&lt;/li&gt;
&lt;li&gt;API key/OAuth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Functions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create/update tickets from chat/emails.&lt;/li&gt;
&lt;li&gt;Status sync and cross-tool reports.&lt;/li&gt;
&lt;li&gt;Auto-triage bugs from logs/emails.&lt;/li&gt;
&lt;li&gt;Weekly digests and reminders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Founders: Link emails → tasks → Notion.&lt;/li&gt;
&lt;li&gt;Teams: Standup automation.&lt;/li&gt;
&lt;li&gt;Personal: Life admin tracking. Combines powerfully with GOG and self-improving skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to choose the right OpenClaw skill
&lt;/h2&gt;

&lt;p&gt;Choose skills based on repeated pain, not novelty. If a task happens every day, starts in chat, and ends with a tool action, it is a skill candidate. If it needs memory, timing, or strict guardrails, it is an even better candidate. OpenClaw’s own docs emphasize that skills teach the agent how and when to use tools, while plugins and tools provide the raw capability.&lt;/p&gt;

&lt;p&gt;A good rule for 2026 is to start with the six skills above and then add custom workspace skills only after you have measured the pain point. OpenClaw supports local overrides, workspace skills, and precedence rules, so you do not need to keep editing the same repo copy to customize behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison Table: Top 6 OpenClaw Skills
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;Installs/Popularity&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Risk Level&lt;/th&gt;
&lt;th&gt;CometAPI Synergy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GOG (Google)&lt;/td&gt;
&lt;td&gt;Very High (top-ranked)&lt;/td&gt;
&lt;td&gt;Productivity, Email/Calendar&lt;/td&gt;
&lt;td&gt;Low-Medium&lt;/td&gt;
&lt;td&gt;Medium (OAuth)&lt;/td&gt;
&lt;td&gt;High (volume tasks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent Browser&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Research, Automation&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;td&gt;High (sandbox)&lt;/td&gt;
&lt;td&gt;High (real-time)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-Improving&lt;/td&gt;
&lt;td&gt;High (top-rated)&lt;/td&gt;
&lt;td&gt;Long-term Autonomy&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium (learning loops)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Dev Workflows&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High (coding models)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Summarize&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Knowledge Mgmt&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High (efficiency)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project Mgmt (Linear/Notion)&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;td&gt;Ops/Teams&lt;/td&gt;
&lt;td&gt;Low-Medium&lt;/td&gt;
&lt;td&gt;Low-Medium&lt;/td&gt;
&lt;td&gt;High (orchestration)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill/Category&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Install Difficulty&lt;/th&gt;
&lt;th&gt;Popularity (Est.)&lt;/th&gt;
&lt;th&gt;Key Benefit&lt;/th&gt;
&lt;th&gt;CometAPI Synergy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;Repo management, PRs&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;Autonomous dev workflows&lt;/td&gt;
&lt;td&gt;Reliable coding models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent Browser&lt;/td&gt;
&lt;td&gt;Web automation&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Browser actions without manual&lt;/td&gt;
&lt;td&gt;Vision/ multimodal models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Search&lt;/td&gt;
&lt;td&gt;Real-time research&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Fresh data synthesis&lt;/td&gt;
&lt;td&gt;Fast, cheap inference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Summarize/Notion&lt;/td&gt;
&lt;td&gt;Content &amp;amp; knowledge mgmt&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Structured output&lt;/td&gt;
&lt;td&gt;Long-context models (GPT-5.4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-Improving&lt;/td&gt;
&lt;td&gt;Agent evolution&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Growing&lt;/td&gt;
&lt;td&gt;Reduced errors over time&lt;/td&gt;
&lt;td&gt;Consistent model perf via CometAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Calendar/Email&lt;/td&gt;
&lt;td&gt;Daily productivity&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;Proactive scheduling&lt;/td&gt;
&lt;td&gt;Low-latency for frequent calls&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Advanced Tips, Security, and Scaling in 2026
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory &amp;amp; Heartbeats&lt;/strong&gt;: Combine skills with persistent memory and scheduled runs for proactive agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Best Practices&lt;/strong&gt;: Dedicated user/sandbox, VirusTotal checks on ClawHub, approval gates, read-only defaults, regular audits. Consider NVIDIA NemoClaw for added guardrails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Agent Setups&lt;/strong&gt;: Run specialized OpenClaw instances (e.g., one for coding, one for personal).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CometAPI Integration&lt;/strong&gt;: Set as primary provider in OpenClaw config. Use model routing for cost optimization (e.g., via their dashboard analytics). Benefits: Single key, broad model access (including latest releases), lower latency/cost, privacy focus. Ideal for high-token agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building Custom Skills&lt;/strong&gt;: OpenClaw can help generate them—start simple with &lt;code&gt;SKILL.md&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Future Outlook&lt;/strong&gt;: By late 2026, expect deeper multimodal skills, better enterprise controls, and even more seamless integrations. Skills like these position you at the forefront.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Level Up Your OpenClaw Today
&lt;/h2&gt;

&lt;p&gt;These top 6 skills—GOG, Agent Browser, Self-Improving/Capability Evolver, GitHub, Summarize, and Project Management—form a robust foundation for a truly autonomous AI teammate in 2026. Start with core productivity ones (GOG + Summarize), then layer on automation and self-improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready to deploy?&lt;/strong&gt; Head to &lt;a href="https://openclaw.ai/" rel="noopener noreferrer"&gt;openclaw.ai&lt;/a&gt;, install via the one-liner, and power it with &lt;strong&gt;CometAPI&lt;/strong&gt; at cometapi.com for seamless, affordable access to the best models. Experiment safely, iterate with your agent, and watch productivity soar.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/top-6-openclaw-skills-you-can-t-afford-to-miss-in-2026/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=top-6-openclaw-skills-you-can-t-afford-to-miss-in-2026"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Add AI Video Generation to a SaaS App</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 04:40:33 +0000</pubDate>
      <link>https://dev.to/masonreed1/how-to-add-ai-video-generation-to-a-saas-app-1emk</link>
      <guid>https://dev.to/masonreed1/how-to-add-ai-video-generation-to-a-saas-app-1emk</guid>
      <description>&lt;p&gt;Adding video generation to your app is not the same as adding image generation. The API call returns immediately — but the video isn't ready yet. You get a task ID, and you have to keep asking "is it done?" until it is.&lt;/p&gt;

&lt;p&gt;Most developers hit this the first time they call a video API, wait for a response body with a video URL, and get back a task ID instead. This guide walks through the full flow: submitting a task, polling for results, handling failures, and storing the output before the URL expires.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll build
&lt;/h2&gt;

&lt;p&gt;A backend service that accepts a text prompt or image, submits a video generation task, polls until it's complete, and returns the final video URL. You'll work with four models — Veo 3 Fast, Sora 2, Kling Video, and Runway — all through a single API key.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Prerequisites:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.8+ or Node.js 18+&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.cometapi.com/" rel="noopener noreferrer"&gt;CometAPI&lt;/a&gt; key&lt;/li&gt;
&lt;li&gt;Basic familiarity with REST APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understand why video generation is different
&lt;/h2&gt;

&lt;p&gt;With image generation, you send a request and get the image back in the same response. Video generation uses an async task queue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Submit&lt;/strong&gt; a generation request → get back a &lt;code&gt;task_id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Poll&lt;/strong&gt; a status endpoint every few seconds&lt;/li&gt;
&lt;li&gt;When status reaches a terminal state, you get the video URL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download and store&lt;/strong&gt; the video — the URL is temporary&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you treat video generation like image generation and wait for the first response to contain your video, your request will time out every time.&lt;/p&gt;

&lt;p&gt;In a production web service, this polling loop should run in a background worker (Celery, Bull, or similar), not in your request handler. The examples below use synchronous polling — fine for scripts and prototypes, but not for handling concurrent users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a model
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Max duration&lt;/th&gt;
&lt;th&gt;Price (via CometAPI)&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Veo 3 Fast&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;8 sec&lt;/td&gt;
&lt;td&gt;$0.05/sec&lt;/td&gt;
&lt;td&gt;Fast prototyping, social clips&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sora 2&lt;/td&gt;
&lt;td&gt;OpenAI (via CometAPI model ID)&lt;/td&gt;
&lt;td&gt;~10 sec&lt;/td&gt;
&lt;td&gt;$0.08/sec&lt;/td&gt;
&lt;td&gt;High-quality creative shorts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kling Video&lt;/td&gt;
&lt;td&gt;Kuaishou&lt;/td&gt;
&lt;td&gt;10 sec&lt;/td&gt;
&lt;td&gt;$0.13–$2.64/task&lt;/td&gt;
&lt;td&gt;Marketing content, granular control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runway Gen-3A Turbo&lt;/td&gt;
&lt;td&gt;Runway&lt;/td&gt;
&lt;td&gt;5 or 10 sec&lt;/td&gt;
&lt;td&gt;$0.32/task&lt;/td&gt;
&lt;td&gt;Image-to-video, commercial content&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Source**: CometAPI model pages, May 2026. Note: "Sora 2" is CometAPI's model&lt;/em&gt; &lt;em&gt;identifier&lt;/em&gt; &lt;em&gt;— refer to their&lt;/em&gt; &lt;a href="https://www.cometapi.com/models/openai/sora-2/" rel="noopener noreferrer"&gt;&lt;em&gt;model page&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for the underlying model details.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Veo 3 Fast&lt;/strong&gt; supports both text-to-video and image-to-video. Cheapest per second, good starting point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sora 2&lt;/strong&gt; generates audio natively alongside the video — dialogue, ambient sound, and effects without a separate TTS step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kling Video&lt;/strong&gt; gives you &lt;code&gt;negative_prompt&lt;/code&gt;, &lt;code&gt;cfg_scale&lt;/code&gt;, camera movement settings, and a &lt;code&gt;pro&lt;/code&gt; mode. Most control of the four.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runway&lt;/strong&gt; is image-to-video only via CometAPI. Give it a static image and a motion description, and it animates it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Submit a Veo task
&lt;/h2&gt;

&lt;p&gt;Veo uses &lt;code&gt;multipart/form-data&lt;/code&gt;. Use &lt;code&gt;files=&lt;/code&gt; in Python requests to send it correctly — &lt;code&gt;data=dict&lt;/code&gt; sends &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;, which is not the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requestsimport&lt;/span&gt; &lt;span class="n"&gt;osfrom&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit_veo_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16x9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Submit a Veo 3 Fast text-to-video task. Returns task_id.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY environment variable is not set&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/v1/videos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;veo3-fast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;​​&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;submit_veo_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A paper kite drifting above a wheat field on a windy afternoon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task submitted: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Poll for the result
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;poll_veo_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_wait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Poll until Veo task completes. Returns video URL.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY environment variable is not set&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/v1/videos/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;max_wait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;succeeded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cancelled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; failed with status &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no error detail returned&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; did not complete within &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;max_wait&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​​&lt;/span&gt;&lt;span class="n"&gt;video_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;poll_veo_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Video ready: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Kling Video for more control
&lt;/h2&gt;

&lt;p&gt;Kling has a different endpoint structure and uses JSON. Note that Kling's terminal status string is &lt;code&gt;"succeed"&lt;/code&gt; (not &lt;code&gt;"succeeded"&lt;/code&gt;) — this matches the API's actual response format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit_kling_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;std&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Submit a Kling text-to-video task. Returns task_id.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY environment variable is not set&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/kling/v1/videos/text2video&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kling-v1-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;negative_prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;blurry, low quality, watermark&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cfg_scale&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# "std" or "pro" &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"aspect_ratio": "16:9", &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"duration": duration &amp;amp;nbsp;# "5" or "10" &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;  }, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;timeout=30 &amp;amp;nbsp;  ) &amp;amp;nbsp; &amp;amp;nbsp;response.raise_for_status() &amp;amp;nbsp; &amp;amp;nbsp;return response.json()["data"]["task_id"]​​def poll_kling_task(task_id: str, interval: int = 10, max_wait: int = 600) -&amp;amp;gt; str: &amp;amp;nbsp; &amp;amp;nbsp;"""Poll Kling task until complete. Returns video URL.""" &amp;amp;nbsp; &amp;amp;nbsp;api_key = os.getenv("COMETAPI_KEY") &amp;amp;nbsp; &amp;amp;nbsp;if not api_key: &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;raise ValueError("COMETAPI_KEY environment variable is not set")​ &amp;amp;nbsp; &amp;amp;nbsp;headers = {"Authorization": f"Bearer {api_key}"} &amp;amp;nbsp; &amp;amp;nbsp;url = f"https://api.cometapi.com/kling/v1/videos/text2video/{task_id}" &amp;amp;nbsp; &amp;amp;nbsp;elapsed = 0​ &amp;amp;nbsp; &amp;amp;nbsp;while elapsed &amp;amp;lt; max_wait: &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;response = requests.get(url, headers=headers, timeout=30) &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;response.raise_for_status() &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;result = response.json() &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;status = result["data"]["task_status"]​ &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;if status == "succeed": &amp;amp;nbsp;# Kling uses "succeed", not "succeeded" &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;return result["data"]["task_result"]["videos"][0]["url"] &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elif status == "failed": &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;error_detail = result.get("data", {}).get("task_result", "no detail") &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;raise RuntimeError( &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;f"Kling task {task_id} failed: {error_detail}" &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;  )​ &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;time.sleep(interval) &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elapsed += interval​ &amp;amp;nbsp; &amp;amp;nbsp;raise TimeoutError(f"Kling task {task_id} timed out after {max_wait}s")
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Source**:&lt;/em&gt; &lt;a href="https://apidoc.cometapi.com/video-generation/kling-video" rel="noopener noreferrer"&gt;&lt;em&gt;CometAPI Kling Video docs&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Animate a static image with Runway
&lt;/h2&gt;

&lt;p&gt;Runway is image-to-video only. It also requires an extra header (X-Runway-Version):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit_runway_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;motion_prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Submit a Runway image-to-video task. Returns task_id.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY environment variable is not set&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/runwayml/v1/image_to_video&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-Runway-Version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2024-11-06&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen3a_turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;promptImage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c1"&gt;# must be a stable HTTPS URL &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"promptText": motion_prompt, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"duration": duration, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"ratio": "1280:720", &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"watermark": False &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;  }, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;timeout=30 &amp;amp;nbsp;  ) &amp;amp;nbsp; &amp;amp;nbsp;response.raise_for_status() &amp;amp;nbsp; &amp;amp;nbsp;return response.json()["id"]​​def poll_runway_task(task_id: str, interval: int = 5, max_wait: int = 600) -&amp;amp;gt; str: &amp;amp;nbsp; &amp;amp;nbsp;"""Poll Runway task. Returns video URL when done.""" &amp;amp;nbsp; &amp;amp;nbsp;api_key = os.getenv("COMETAPI_KEY") &amp;amp;nbsp; &amp;amp;nbsp;if not api_key: &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;raise ValueError("COMETAPI_KEY environment variable is not set")​ &amp;amp;nbsp; &amp;amp;nbsp;headers = { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"Authorization": f"Bearer {api_key}", &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;"X-Runway-Version": "2024-11-06" &amp;amp;nbsp;  } &amp;amp;nbsp; &amp;amp;nbsp;url = f"https://api.cometapi.com/runwayml/v1/tasks/{task_id}" &amp;amp;nbsp; &amp;amp;nbsp;elapsed = 0​ &amp;amp;nbsp; &amp;amp;nbsp;while elapsed &amp;amp;lt; max_wait: &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;response = requests.get(url, headers=headers, timeout=30) &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;response.raise_for_status() &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;result = response.json() &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;status = result.get("status")​ &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;if status == "task_not_exist": &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;# CometAPI-specific: task is still initializing, retry after a few seconds &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;time.sleep(interval) &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elapsed += interval &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;continue &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elif status == "succeeded": &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;return result["output"][0] &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elif status in ("failed", "cancelled"): &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;raise RuntimeError(f"Runway task {task_id} failed: {result.get('error', 'no detail')}")​ &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;time.sleep(interval) &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elapsed += interval​ &amp;amp;nbsp; &amp;amp;nbsp;raise TimeoutError(f"Runway task {task_id} timed out after {max_wait}s")
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Source**:&lt;/em&gt; &lt;a href="https://apidoc.cometapi.com/api/video/runway" rel="noopener noreferrer"&gt;&lt;em&gt;CometAPI Runway docs&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Save the video before the URL expires
&lt;/h2&gt;

&lt;p&gt;Video URLs from generation APIs are temporary. Download the file immediately and store it somewhere you control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requestsimport&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_video&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Download video from URL to local file using streaming.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Saved to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;​​&lt;/span&gt;&lt;span class="c1"&gt;# Full flowtask_id = submit_veo_task("A timelapse of clouds moving over a city skyline")video_url = poll_veo_task(task_id)download_video(video_url, "output/city_timelapse.mp4")
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In production, swap the local file write for an upload to S3, Cloudflare R2, or your storage of choice. The streaming pattern stays the same — pipe the bytes directly rather than loading the whole video into memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handle failures
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Task stuck in queued for 10+ min&lt;/td&gt;
&lt;td&gt;Server load or model unavailable&lt;/td&gt;
&lt;td&gt;Retry with a different model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;task_not_exist on first Runway poll&lt;/td&gt;
&lt;td&gt;Task still initializing&lt;/td&gt;
&lt;td&gt;Wait 5 sec and retry — documented CometAPI behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;failed with no error message&lt;/td&gt;
&lt;td&gt;Prompt triggered content filter&lt;/td&gt;
&lt;td&gt;Rephrase the prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video URL returns 403&lt;/td&gt;
&lt;td&gt;URL expired before download&lt;/td&gt;
&lt;td&gt;Download immediately after getting the URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timeout after 10 min&lt;/td&gt;
&lt;td&gt;Generation took too long&lt;/td&gt;
&lt;td&gt;Increase max_wait or switch to Veo 3 Fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kling returns "succeed" not "succeeded"&lt;/td&gt;
&lt;td&gt;Kling's API uses non-standard status string&lt;/td&gt;
&lt;td&gt;This is correct — see Kling polling code above&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Source:&lt;/em&gt; &lt;a href="https://apidoc.cometapi.com/api/video/veo3" rel="noopener noreferrer"&gt;&lt;em&gt;CometAPI video generation docs&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js version
&lt;/h2&gt;

&lt;p&gt;Node.js 18+ includes &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;FormData&lt;/code&gt; natively. This example covers all four models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Node.js 18+ — no extra packages needed​const API_KEY = process.env.COMETAPI_KEY;if (!API_KEY) throw new Error('COMETAPI_KEY is not set');​// --- Veo 3 Fast ---async function submitVeoTask(prompt, size = '16x9') { &amp;amp;nbsp;const form = new FormData(); &amp;amp;nbsp;form.append('prompt', prompt); &amp;amp;nbsp;form.append('model', 'veo3-fast'); &amp;amp;nbsp;form.append('size', size);​ &amp;amp;nbsp;const res = await fetch('https://api.cometapi.com/v1/videos', { &amp;amp;nbsp; &amp;amp;nbsp;method: 'POST', &amp;amp;nbsp; &amp;amp;nbsp;headers: { 'Authorization': `Bearer ${API_KEY}` }, &amp;amp;nbsp; &amp;amp;nbsp;body: form  }); &amp;amp;nbsp;if (!res.ok) throw new Error(`Veo submit failed: ${res.status}`); &amp;amp;nbsp;return (await res.json()).id;}​async function pollVeoTask(taskId, intervalMs = 10000, maxWaitMs = 600000) { &amp;amp;nbsp;let elapsed = 0; &amp;amp;nbsp;while (elapsed &amp;amp;lt; maxWaitMs) { &amp;amp;nbsp; &amp;amp;nbsp;const res = await fetch(`https://api.cometapi.com/v1/videos/${taskId}`, { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;headers: { 'Authorization': `Bearer ${API_KEY}` } &amp;amp;nbsp;  }); &amp;amp;nbsp; &amp;amp;nbsp;if (!res.ok) throw new Error(`Poll failed: ${res.status}`); &amp;amp;nbsp; &amp;amp;nbsp;const result = await res.json();​ &amp;amp;nbsp; &amp;amp;nbsp;if (result.status === 'succeeded') return result.output[0]; &amp;amp;nbsp; &amp;amp;nbsp;if (['failed', 'cancelled'].includes(result.status)) { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;throw new Error(`Task ${taskId} failed: ${result.error ?? 'no detail'}`); &amp;amp;nbsp;  } &amp;amp;nbsp; &amp;amp;nbsp;await new Promise(r =&amp;amp;gt; setTimeout(r, intervalMs)); &amp;amp;nbsp; &amp;amp;nbsp;elapsed += intervalMs;  } &amp;amp;nbsp;throw new Error(`Task ${taskId} timed out`);}​// --- Kling Video ---async function submitKlingTask(prompt, duration = '5', mode = 'std') { &amp;amp;nbsp;const res = await fetch('https://api.cometapi.com/kling/v1/videos/text2video', { &amp;amp;nbsp; &amp;amp;nbsp;method: 'POST', &amp;amp;nbsp; &amp;amp;nbsp;headers: { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;'Authorization': `Bearer ${API_KEY}`, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;'Content-Type': 'application/json' &amp;amp;nbsp;  }, &amp;amp;nbsp; &amp;amp;nbsp;body: JSON.stringify({ &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;model_name: 'kling-v1-6', &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;prompt, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;negative_prompt: 'blurry, low quality, watermark', &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;cfg_scale: 0.5, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;mode, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;aspect_ratio: '16:9', &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;duration &amp;amp;nbsp;  })  }); &amp;amp;nbsp;if (!res.ok) throw new Error(`Kling submit failed: ${res.status}`); &amp;amp;nbsp;return (await res.json()).data.task_id;}​async function pollKlingTask(taskId, intervalMs = 10000, maxWaitMs = 600000) { &amp;amp;nbsp;let elapsed = 0; &amp;amp;nbsp;while (elapsed &amp;amp;lt; maxWaitMs) { &amp;amp;nbsp; &amp;amp;nbsp;const res = await fetch( &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;`https://api.cometapi.com/kling/v1/videos/text2video/${taskId}`, &amp;amp;nbsp; &amp;amp;nbsp;  { headers: { 'Authorization': `Bearer ${API_KEY}` } } &amp;amp;nbsp;  ); &amp;amp;nbsp; &amp;amp;nbsp;if (!res.ok) throw new Error(`Kling poll failed: ${res.status}`); &amp;amp;nbsp; &amp;amp;nbsp;const result = await res.json(); &amp;amp;nbsp; &amp;amp;nbsp;const status = result.data.task_status;​ &amp;amp;nbsp; &amp;amp;nbsp;if (status === 'succeed') return result.data.task_result.videos[0].url; &amp;amp;nbsp; &amp;amp;nbsp;if (status === 'failed') { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;throw new Error(`Kling task ${taskId} failed: ${JSON.stringify(result.data.task_result ?? 'no detail')}`); &amp;amp;nbsp;  } &amp;amp;nbsp; &amp;amp;nbsp;await new Promise(r =&amp;amp;gt; setTimeout(r, intervalMs)); &amp;amp;nbsp; &amp;amp;nbsp;elapsed += intervalMs;  } &amp;amp;nbsp;throw new Error(`Kling task ${taskId} timed out`);}​// --- Runway (image-to-video) ---async function submitRunwayTask(imageUrl, motionPrompt, duration = 5) { &amp;amp;nbsp;const res = await fetch('https://api.cometapi.com/runwayml/v1/image_to_video', { &amp;amp;nbsp; &amp;amp;nbsp;method: 'POST', &amp;amp;nbsp; &amp;amp;nbsp;headers: { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;'Authorization': `Bearer ${API_KEY}`, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;'X-Runway-Version': '2024-11-06', &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;'Content-Type': 'application/json' &amp;amp;nbsp;  }, &amp;amp;nbsp; &amp;amp;nbsp;body: JSON.stringify({ &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;model: 'gen3a_turbo', &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;promptImage: imageUrl, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;promptText: motionPrompt, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;duration, &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;ratio: '1280:720', &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;watermark: false &amp;amp;nbsp;  })  }); &amp;amp;nbsp;if (!res.ok) throw new Error(`Runway submit failed: ${res.status}`); &amp;amp;nbsp;return (await res.json()).id;}​async function pollRunwayTask(taskId, intervalMs = 5000, maxWaitMs = 600000) { &amp;amp;nbsp;let elapsed = 0; &amp;amp;nbsp;while (elapsed &amp;amp;lt; maxWaitMs) { &amp;amp;nbsp; &amp;amp;nbsp;const res = await fetch( &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;`https://api.cometapi.com/runwayml/v1/tasks/${taskId}`, &amp;amp;nbsp; &amp;amp;nbsp;  { headers: { 'Authorization': `Bearer ${API_KEY}`, 'X-Runway-Version': '2024-11-06' } } &amp;amp;nbsp;  ); &amp;amp;nbsp; &amp;amp;nbsp;if (!res.ok) throw new Error(`Runway poll failed: ${res.status}`); &amp;amp;nbsp; &amp;amp;nbsp;const result = await res.json(); &amp;amp;nbsp; &amp;amp;nbsp;const status = result.status;​ &amp;amp;nbsp; &amp;amp;nbsp;if (status === 'task_not_exist') { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;// CometAPI-specific: task still initializing &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;await new Promise(r =&amp;amp;gt; setTimeout(r, intervalMs)); &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;elapsed += intervalMs; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;continue; &amp;amp;nbsp;  } &amp;amp;nbsp; &amp;amp;nbsp;if (status === 'succeeded') return result.output[0]; &amp;amp;nbsp; &amp;amp;nbsp;if (['failed', 'cancelled'].includes(status)) { &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;throw new Error(`Runway task ${taskId} failed: ${result.error ?? 'no detail'}`); &amp;amp;nbsp;  } &amp;amp;nbsp; &amp;amp;nbsp;await new Promise(r =&amp;amp;gt; setTimeout(r, intervalMs)); &amp;amp;nbsp; &amp;amp;nbsp;elapsed += intervalMs;  } &amp;amp;nbsp;throw new Error(`Runway task ${taskId} timed out`);}​// Usage exampleconst taskId = await submitVeoTask('A paper kite drifting above a wheat field');const videoUrl = await pollVeoTask(taskId);console.log('Video ready:', videoUrl);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;You now have working code for four video models, a polling loop that handles failures, and a download step that keeps you from losing generated content.&lt;/p&gt;

&lt;p&gt;The next problem most developers hit: they've hardcoded one model, and switching to a cheaper or faster option means touching multiple files. The next article covers how to route requests across models without rewriting your code.&lt;/p&gt;

&lt;p&gt;Next: &lt;strong&gt;How to Switch Between AI Models Without Rewriting Your Code&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: Why do I get a task ID instead of a video in the API response?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Video generation is async — models like Veo, Sora, Kling, and Runway take 2–5 minutes to render. The API returns a task ID immediately so your request doesn't time out. You poll a separate status endpoint until the task reaches a terminal state (&lt;code&gt;succeeded&lt;/code&gt;, &lt;code&gt;succeed&lt;/code&gt;, &lt;code&gt;failed&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: How long does a generated video URL stay valid?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Video URLs from generation APIs are temporary. Download the file immediately after getting the URL and store it in your own storage (S3, Cloudflare R2, etc.). Don't store the URL and expect it to work hours later.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: What's the difference between Veo 3 Fast and Kling Video?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Veo 3 Fast is cheaper ($0.05/sec), faster, and simpler to call. Kling Video gives you more control: &lt;code&gt;negative_prompt&lt;/code&gt;, &lt;code&gt;cfg_scale&lt;/code&gt;, camera movement settings, and a &lt;code&gt;pro&lt;/code&gt; quality mode. If you need to fine-tune the output, use Kling. If you need speed and low cost, use Veo 3 Fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: Can I generate video from an image instead of a text prompt?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Yes. Veo supports image-to-video by passing an &lt;code&gt;input_reference&lt;/code&gt; file. Kling supports it via the &lt;code&gt;/kling/v1/videos/image2video&lt;/code&gt; endpoint with an &lt;code&gt;image&lt;/code&gt; parameter (URL or base64). Runway is image-to-video only — it doesn't accept text-only prompts via CometAPI.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: Why does Runway return&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;task_not_exist&lt;/code&gt;&lt;/strong&gt; &lt;strong&gt;on the first poll?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is documented CometAPI behavior — the task is still initializing on the backend. Wait a few seconds and retry. It's not an error. The polling code above handles this automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: Why does Kling use&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;"succeed"&lt;/code&gt;&lt;/strong&gt; &lt;strong&gt;instead of&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;"succeeded"&lt;/code&gt;&lt;/strong&gt;?
&lt;/h3&gt;

&lt;p&gt;That's Kling's actual API response format. It's not a typo. Veo and Runway use &lt;code&gt;"succeeded"&lt;/code&gt; — Kling uses &lt;code&gt;"succeed"&lt;/code&gt;. If you're building a unified polling wrapper, you'll need to handle both strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q: Is the synchronous polling loop safe to use in a web server?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No. The polling loop in this guide blocks the thread for minutes at a time. In a real web service with concurrent users, run the polling in a background worker (Celery for Python, Bull for Node.js). Submit the task in the request handler, return the task ID to the client, and let the worker notify the client when the video is ready.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/how-to-add-ai-video-generation-to-a-saas-app/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=how-to-add-ai-video-generation-to-a-saas-app"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Hidden Cost of Juggling OpenAI, Anthropic, and Google Credentials</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 04:17:59 +0000</pubDate>
      <link>https://dev.to/masonreed1/the-hidden-cost-of-juggling-openai-anthropic-and-google-credentials-36g4</link>
      <guid>https://dev.to/masonreed1/the-hidden-cost-of-juggling-openai-anthropic-and-google-credentials-36g4</guid>
      <description>&lt;p&gt;&lt;em&gt;Multi-provider AI setups don't show their cost in the&lt;/em&gt; &lt;a href="https://www.cometapi.com/pricing/" rel="noopener noreferrer"&gt;&lt;em&gt;API bill&lt;/em&gt;&lt;/a&gt; &lt;em&gt;— they show it in developer hours. Once you put a number on it, the case for consolidation stops being a matter of taste and becomes a line item your finance team can defend.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The cost most teams never count
&lt;/h2&gt;

&lt;p&gt;Most product engineering teams running on top of three or four AI providers can tell you to the dollar what they spent on tokens last month. They can tell you which feature drove the most cost, which model is cheapest per million tokens, and whether their burn rate is on track for the quarter. What they usually cannot tell you is what the operational overhead of running three or four provider relationships actually costs them in developer time.&lt;/p&gt;

&lt;p&gt;This is not because the cost is invisible. Every engineer on the team feels it. It is because the cost is paid in increments small enough to dismiss — a credential lookup here, a debugging session there, a half-day of integration work the next time a new model ships. None of these show up in any standard cost report. The API bill captures inference cost. The cloud bill captures infrastructure cost. Engineering time spent on cross-provider operational work shows up nowhere, because no system was designed to capture it. The default reporting infrastructure has a blind spot exactly the shape of this category of work.&lt;/p&gt;

&lt;p&gt;This article is the version of that conversation that puts numbers on the table. The argument is not that &lt;a href="https://www.cometapi.com/cometapi-vs-direct-provider-apis/" rel="noopener noreferrer"&gt;multi-provider&lt;/a&gt; AI is bad — there are workloads where running multiple providers is genuinely the right architectural choice. The argument is that the operational cost of that choice is real, quantifiable, and usually larger than teams realise. Once you can name the figure, the architectural conversation becomes a real cost-benefit analysis instead of a series of competing intuitions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The headline finding:&lt;/strong&gt; For a typical five-engineer team running three AI providers, the annual operational cost of multi-provider work — counted in developer hours alone — sits between $35,000 and $60,000. That is not a hypothetical; it is what comes out when you instrument the workflow and add up the actual time. The number doesn't appear on any budget because no system was built to capture it. The case for changing your setup is what happens when you start counting it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5 hidden line items
&lt;/h2&gt;

&lt;p&gt;The operational cost of multi-provider AI work breaks down into five categories, each of which can be measured if you decide to. None of them is enormous in isolation; the cost is in the aggregate. Below, each category, what it looks like in practice, and how much time it consumes per month for a representative engineering team.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Initial onboarding to each provider
&lt;/h3&gt;

&lt;p&gt;Setting up a new AI provider relationship is a multi-step process. Sign up for the account. Verify the email and any payment method. Read the rate-limit documentation. Set up secrets management for the new credential. Install the provider's SDK if it differs from what you already use. Wire the credential through your CI/CD pipeline so deploys can authenticate. Add the new provider to your secrets-rotation calendar. For a typical provider, this is 4–8 hours of engineering time, mostly done by one engineer but with at least some coordination overhead from others.&lt;/p&gt;

&lt;p&gt;This cost is paid once per provider, but the "once" matters. If your team adds one new provider per year — which is below the 2026 baseline for serious teams — you pay this cost annually. The first onboarding doesn't feel expensive because it is one engineer for one afternoon. The fourth onboarding, when the same engineer has now done it four times in eighteen months and is increasingly resistant to doing it again, is where the friction shows up.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Monthly billing reconciliation
&lt;/h3&gt;

&lt;p&gt;Every month-end, someone on the team — usually the lead engineer or technical founder — pulls usage data from each provider's dashboard, normalises the formats, attributes the costs to product features or clients, and produces a consolidated view. For a team with three providers and a clean usage pattern, this is roughly 2–4 hours per month. For a team with four or more providers, or with complex cost-attribution requirements (per-feature, per-client, or per-team), it can be 6–10 hours per month.&lt;/p&gt;

&lt;p&gt;The reconciliation work is not engineering work in any meaningful sense — it is bookkeeping done by someone who is overqualified for the task. The fact that it lands on the engineering side rather than the finance side is itself a clue that the workflow has not been designed; it has just accumulated.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Credential rotation and security hygiene
&lt;/h3&gt;

&lt;p&gt;Good security practice requires rotating API credentials periodically — quarterly for most teams, more frequently for regulated workloads. With one provider, this is a routine 30-minute task. With three or four providers, each with its own rotation interface, its own propagation timing, and its own potential failure modes, the same task expands to several hours per cycle. Add the time spent debugging when a rotated credential doesn't propagate cleanly to a production environment, and the cost rises further. A team that rotates credentials quarterly across four providers loses 8–15 hours per year to this specific category alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Debugging auth and integration errors across providers
&lt;/h3&gt;

&lt;p&gt;A request fails. Was it a rate limit? An auth error? A model deprecation? A content-policy refusal? On a single-provider setup, this is one debugging surface. On a multi-provider setup, it is multiple — and the error formats, status codes, and dashboard log layouts differ across each. The cognitive cost of switching between provider conventions during incident response is the friction point that bites worst, because it lands during exactly the moments when speed matters most. For a team with three providers, this category typically runs 2–4 hours per month — and spikes much higher when a provider has an outage or changes their auth model unexpectedly.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Re-evaluating model choices each time a new release lands
&lt;/h3&gt;

&lt;p&gt;In 2026, new frontier model releases happen roughly every three to six weeks. Each release triggers a small evaluation cycle: read the model card, decide whether it warrants testing against your workload, set up the integration if it's from a provider you don't already have access to, run your eval suite, compare results. On a multi-provider direct setup, this cycle is 1–2 days of engineering time per release, mostly because the setup cost is non-trivial. On a single-endpoint setup with the new model already available behind the same credential, the same evaluation is 1–2 hours. The difference, multiplied by 6–10 evaluation cycles per year, is meaningful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting numbers on it
&lt;/h2&gt;

&lt;p&gt;The categories above are easy to describe and easy to dismiss as small. The exercise that changes the conversation is multiplying them out for a realistic team. Below, the calculation for a five-engineer product team running three AI providers — the kind of setup that has become unremarkable for AI-native startups.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost category&lt;/th&gt;
&lt;th&gt;Hours per month&lt;/th&gt;
&lt;th&gt;Hours per year&lt;/th&gt;
&lt;th&gt;Annual cost ($)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Initial provider onboarding (1 new provider/year)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;5 hrs&lt;/td&gt;
&lt;td&gt;$675&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly billing reconciliation&lt;/td&gt;
&lt;td&gt;3 hrs&lt;/td&gt;
&lt;td&gt;36 hrs&lt;/td&gt;
&lt;td&gt;$4,860&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quarterly credential rotation across 3 providers&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;12 hrs&lt;/td&gt;
&lt;td&gt;$1,620&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging auth and integration errors&lt;/td&gt;
&lt;td&gt;3 hrs&lt;/td&gt;
&lt;td&gt;36 hrs&lt;/td&gt;
&lt;td&gt;$4,860&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New model evaluations (8 releases/year)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;120 hrs&lt;/td&gt;
&lt;td&gt;$16,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily context-switching tax (15 min/engineer)&lt;/td&gt;
&lt;td&gt;25 hrs&lt;/td&gt;
&lt;td&gt;300 hrs&lt;/td&gt;
&lt;td&gt;$40,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total annual operational cost&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;509 hrs&lt;/td&gt;
&lt;td&gt;$68,715&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;How the numbers are calculated.&lt;/em&gt; Hours per month for shared work (reconciliation, debugging) are total team hours, not per-engineer. The daily context-switching tax is 15 minutes per engineer per working day, multiplied by five engineers and roughly 200 working days a year. Dollar conversion uses a fully-loaded engineering cost of $135/hour, which is a conservative figure for a mid-level engineer in the US or UK once salary, benefits, taxes, and overhead are accounted for. Adjust both the team size and the hourly rate for your specific situation; the structure of the calculation is the same.&lt;/p&gt;

&lt;p&gt;Three observations about this table that matter more than the bottom-line number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, the largest line is the one teams notice least.&lt;/strong&gt; The $40,500 daily context-switching tax — 15 minutes per engineer per day on dashboard checks, credential lookups, and cross-provider documentation — is paid in tiny enough increments that no one feels it as a cost. It is also, by a meaningful margin, the largest single item on the table. The accumulated effect of small daily frictions outweighs every other category combined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, the model evaluation cost is the most strategically expensive.&lt;/strong&gt; $16,200 a year on evaluation cycles is significant, but the real cost is the evaluations that don't happen because the setup cost makes them not worth it. Teams running multi-provider direct setups evaluate fewer new models, take longer to migrate when a better fit appears, and end up running suboptimal model choices for longer than they should. The hidden cost of slower iteration is harder to put a number on, but it is real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third, the calculation is conservative.&lt;/strong&gt; The numbers above assume a team that has its multi-provider workflow working reasonably well. Teams in worse shape — with credential rotation neglected, with no consistent reconciliation cadence, with evaluation cycles that take longer because eval infrastructure isn't in place — face higher numbers. The $68,715 figure is what good operational discipline looks like; the figure for teams without it can comfortably be twice that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this cost never appears on the budget
&lt;/h2&gt;

&lt;p&gt;If the operational cost is this large, why does no team have a line item for it? The answer is structural, not accidental. Four reasons together explain the blind spot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No system was built to capture this category.&lt;/strong&gt; Time-tracking systems are built for billable client work. Engineering reporting is built for feature delivery. Cost-attribution systems are built for COGS. None of them have a natural place to record "45 minutes debugging a rate-limit issue across two providers." The work happens; the recording infrastructure for it doesn't exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The increments are small enough to dismiss.&lt;/strong&gt; Each individual instance of this work is 5–30 minutes. That's below the threshold most engineers would treat as worth tracking. The cost shows up only when you add the increments across the year — which nobody does, because there's no system that does it automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The work is invisible from outside the engineering team.&lt;/strong&gt; The CTO sees feature delivery velocity. The CFO sees the API bill. Neither sees the integration overhead in between. Unless an engineer escalates the cost explicitly — and most don't, because they have built the work into their normal routine — the category remains structurally invisible to the people making the architectural decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The framing is engineering culture, not finance language.&lt;/strong&gt; Engineers describe this work as "keeping the lights on" or "normal operational overhead" — language that doesn't trigger budget scrutiny. If the same work were described as "$68,715 a year of operational integration cost," the response from leadership would be immediate. The framing controls whether the cost becomes visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these four factors create the blind spot that makes the multi-provider operational cost so persistent. The cost is real, the impact is significant, and almost nothing in the standard reporting infrastructure surfaces it. Making the case to change your setup starts with the framing — naming the cost in finance language is what brings it into the conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The break-even calculation
&lt;/h2&gt;

&lt;p&gt;Once you have the annual operational cost named, the question becomes: at what team size or workload volume does consolidating to a single-endpoint setup pay back the migration cost? The migration itself is genuinely small — typically 4–16 engineering hours depending on how the existing codebase is structured. Below the break-even point, that migration cost outweighs the operational saving; above it, the saving accumulates from the first month onwards.&lt;/p&gt;

&lt;p&gt;Working backwards from the calculation above, the break-even for a team of five engineers running three providers is approximately one month of operational saving — about $5,700 per month of reclaimed engineering time covers the entire migration cost. For smaller teams, the break-even can be longer; for larger teams, it shortens to a few weeks. Three scenarios that bracket the typical range:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Team profile&lt;/th&gt;
&lt;th&gt;Annual operational cost (est.)&lt;/th&gt;
&lt;th&gt;Migration cost (est.)&lt;/th&gt;
&lt;th&gt;Break-even&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Solo founder, 2 providers&lt;/td&gt;
&lt;td&gt;$12,000&lt;/td&gt;
&lt;td&gt;$1,000&lt;/td&gt;
&lt;td&gt;1 month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5-engineer startup, 3 providers&lt;/td&gt;
&lt;td&gt;$68,000&lt;/td&gt;
&lt;td&gt;$2,000&lt;/td&gt;
&lt;td&gt;2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12-engineer scale-up, 4 providers&lt;/td&gt;
&lt;td&gt;$180,000&lt;/td&gt;
&lt;td&gt;$4,000&lt;/td&gt;
&lt;td&gt;1 week&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pattern is consistent: the larger the team and the more providers in scope, the faster the break-even. The break-even calculation also doesn't include the secondary benefits — faster model evaluation cycles, recovered focus time, fewer credential incidents — which add to the case but are harder to quantify cleanly. The migration cost is small enough that for any team running two or more providers with non-trivial volume, it pays back within the first month.&lt;/p&gt;

&lt;h2&gt;
  
  
  The qualitative cost
&lt;/h2&gt;

&lt;p&gt;The numbers above capture the time directly spent on multi-provider operational work. They do not capture the second-order costs that show up in how the team works. These are harder to quantify but matter more in practice.&lt;/p&gt;

&lt;p&gt;Friction in the engineering loop. When even routine work requires context-switching across provider conventions, engineers ship slower. The shipping speed cost is not the literal time spent on switching; it is the cumulative effect of fragmented attention on the rest of the day. Productivity research has been clear for decades that context-switching has a residue cost that outlasts the switch itself. The engineering team that is constantly switching between provider dashboards is the same team that gets less done in a sprint than its size would suggest.&lt;/p&gt;

&lt;p&gt;Resistance to better choices. When evaluating a new model requires setting up a new provider relationship, the threshold for "is it worth trying?" rises. Engineers stop suggesting evaluations they would otherwise have run. The result is that the team's model choices drift from optimal — not because anyone made a bad decision, but because the better decisions never got made. This is the failure mode that is hardest to see in retrospect because the alternative was never tested.&lt;/p&gt;

&lt;p&gt;Burnout from administrative work. The work of managing multiple providers is genuinely tedious. Engineers tolerate it for a while, then start to resent it. The resentment shows up in standups, in slower responses to operational questions, in engineers proposing architectural changes whose real driver is escape from the credential-management overhead. The hidden cost shows up as morale, retention, and team velocity — and by the time those metrics are bad enough to notice, they have been bad for months.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case to bring to your team
&lt;/h2&gt;

&lt;p&gt;If the calculation above lines up with your team's reality and you want to make the case for consolidating, here is a practical framing that works in internal conversations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lead with the dollar figure, not the engineering complaint.&lt;/strong&gt; "Our current multi-provider setup is costing us roughly $X in engineering time per year" lands very differently to "managing credentials is annoying." The first triggers cost-benefit analysis; the second triggers a polite acknowledgment and no action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show your work on the calculation.&lt;/strong&gt; Use the table structure from this article, adapted to your team's actual hours and hourly rate. The credibility of the number depends on the methodology being transparent. "Here's what we counted, here's the rate we used, here's how it adds up" is much more defensible than a single dollar figure asserted without breakdown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name the secondary benefits separately.&lt;/strong&gt; The break-even pays back in dollars terms within weeks for most teams. The secondary benefits — faster model evaluation, recovered focus time, reduced credential-incident risk — are presented as additional upside, not as the core case. This keeps the primary argument financially defensible while giving the team the qualitative case they care about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be honest about what doesn't change.&lt;/strong&gt; Aggregating to a single endpoint does not eliminate &lt;a href="https://www.cometapi.com/enterprise/" rel="noopener noreferrer"&gt;&lt;strong&gt;compliance obligations&lt;/strong&gt;&lt;/a&gt;, does not change underlying model quality, and does not solve every operational problem. Naming these limits up front is what makes the rest of the argument trustworthy. The team you're presenting to will trust your recommendation more if you have already named the trade-offs honestly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Propose a phased migration, not a big bang.&lt;/strong&gt; The most defensible proposal is to move one new feature or one experimental workload to the new setup first, measure the operational impact, then expand. This de-risks the change and gives you a real-data answer to "does this actually work for us?" within a month. Most teams that propose phased migrations get internal approval easily; teams that propose all-at-once migrations face more resistance even when the numbers are good.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where this leaves you
&lt;/h2&gt;

&lt;p&gt;The operational cost of multi-provider AI work is real, large, and structurally invisible. Most teams pay $35,000 to $60,000 per year for a setup they assume is free because none of the cost appears on any line item. Once you start counting it, the case for consolidation moves out of "engineering preference" territory and into "defensible financial decision" territory. The numbers are the lever; the case is just letting them speak.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The practical next step:&lt;/em&gt; Run the calculation for your team. Use the structure from this article, adapt the hours to your actual setup, and produce the annual figure. The exercise takes less than an hour and produces a number that decides the question. CometAPI is one route for the single-endpoint consolidation; the practical case is the same regardless of which aggregator you choose.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Multi-provider AI doesn't cost what the API bill says it costs. The real cost includes 500+ hours of engineering time per year on integration overhead — credential rotation, billing reconciliation, dashboard navigation, daily context-switching. At realistic engineering rates, that's $35K–$60K of cost no system was built to capture. Naming it in finance language is what brings it into the conversation; running the calculation for your team is what wins the argument.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ready to integrate reliably? Head to&amp;nbsp;&lt;a href="https://cometapi.com/" rel="noopener noreferrer"&gt;CometAPI&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="https://apidoc.cometapi.com/" rel="noopener noreferrer"&gt;API doc&lt;/a&gt;&amp;nbsp;for seamless Claude Fable 5 access alongside other frontier models, unified billing, and enterprise-grade reliability. Sign up today and get started with generous credits for new users—your next breakthrough project awaits.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/the-hidden-cost-of-juggling-openai-anthropic-and-google-credentials/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=the-hidden-cost-of-juggling-openai-anthropic-and-google-credentials"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Seedance 2.5: What Developers Should Know Before Launch</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 03:40:37 +0000</pubDate>
      <link>https://dev.to/masonreed1/seedance-25-what-developers-should-know-before-launch-3mo3</link>
      <guid>https://dev.to/masonreed1/seedance-25-what-developers-should-know-before-launch-3mo3</guid>
      <description>&lt;h2&gt;
  
  
  Current Status
&lt;/h2&gt;

&lt;p&gt;Seedance 2.5 is ByteDance’s next-generation video generation model in the Seedance family. ByteDance announced it on June 23, 2026, at the Volcano Engine FORCE conference. As of June 30, 2026, it was reportedly in global enterprise beta, with a public launch targeted for early July 2026.&lt;/p&gt;

&lt;p&gt;The main changes from Seedance 2.0 are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native single-segment generation up to 30 seconds&lt;/li&gt;
&lt;li&gt;Support for up to 50 multimodal reference assets&lt;/li&gt;
&lt;li&gt;More precise local editing and continuation&lt;/li&gt;
&lt;li&gt;Improved control over motion, camera work, consistency, and pacing&lt;/li&gt;
&lt;li&gt;Native audio-video synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seedance 2.5 accepts text alongside images, video clips, audio, and other reference material. The model is aimed at workflows that currently require stitching together several short generations and repairing inconsistencies in post-production.&lt;/p&gt;

&lt;p&gt;Independent benchmarks for 2.5 are not yet available. Seedance 2.0, however, already performs strongly in evaluations such as the Artificial Analysis Video Arena, where its text-to-video-with-audio score was approximately 1,219 Elo.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Model Adds
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Longer Native Clips
&lt;/h3&gt;

&lt;p&gt;Most video generation systems produce native clips in the 5-15 second range. Seedance 2.5 extends that to 30 seconds in one continuous generation.&lt;/p&gt;

&lt;p&gt;That matters for scenes with a setup, action, camera movement, and resolution. Keeping those elements in one pass should reduce stitching and preserve narrative rhythm. ByteDance demonstrations reportedly include multi-character interactions and spacecraft previsualization using 100k+ polygon models while maintaining structural integrity across the clip.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Reference Material
&lt;/h3&gt;

&lt;p&gt;Seedance 2.5 supports up to 50 multimodal references, compared with approximately 12 in Seedance 2.0.&lt;/p&gt;

&lt;p&gt;References can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Character sheets and style guides&lt;/li&gt;
&lt;li&gt;Images and product assets&lt;/li&gt;
&lt;li&gt;Motion-reference video&lt;/li&gt;
&lt;li&gt;Audio and music&lt;/li&gt;
&lt;li&gt;3D greybox or pre-production material&lt;/li&gt;
&lt;li&gt;Text instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical benefit is tighter control over characters, environments, lighting, branding, and object identity. This is particularly relevant to teams with established asset libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Motion and Cinematic Control
&lt;/h3&gt;

&lt;p&gt;The model is designed for more stable motion, physical interactions, lighting, and character consistency. Its control surface is intended to cover camera behavior such as dolly, tracking, and POV shots, along with performance and pacing.&lt;/p&gt;

&lt;p&gt;Seedance 2.0 already emphasized “exceptional motion stability” and “director-level control” over performance, lighting, shadows, and camera movement. Version 2.5 appears to extend those capabilities to longer and more complex scenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Editing and Continuation
&lt;/h3&gt;

&lt;p&gt;Local or region-based editing allows a team to change part of a frame without regenerating the entire video. High-quality continuation is intended to extend an existing clip while preserving its style and rhythm.&lt;/p&gt;

&lt;p&gt;For e-commerce, this could mean generating a strong lifestyle video once and creating variants for different SKUs, backgrounds, languages, and promotions without rebuilding every scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Output Options
&lt;/h3&gt;

&lt;p&gt;Seedance 2.5 is expected to support resolutions up to 4K, building on Seedance 2.0’s capabilities. It also supports multiple aspect ratios, including &lt;code&gt;16:9&lt;/code&gt; and &lt;code&gt;9:16&lt;/code&gt;, for social, web, and broadcast-oriented outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seedance 2.5 Compared with 2.0
&lt;/h2&gt;

&lt;p&gt;Seedance 2.0 already supports text, image, audio, and video inputs through a unified audio-video generation architecture. The newer model mainly addresses duration, reference capacity, editing, and production control.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Seedance 2.0&lt;/th&gt;
&lt;th&gt;Seedance 2.5&lt;/th&gt;
&lt;th&gt;Practical effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Native clip length&lt;/td&gt;
&lt;td&gt;Approximately 5-15 seconds&lt;/td&gt;
&lt;td&gt;Up to 30 seconds in one pass&lt;/td&gt;
&lt;td&gt;Fewer stitches and better continuity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum references&lt;/td&gt;
&lt;td&gt;Up to approximately 12 multimodal inputs&lt;/td&gt;
&lt;td&gt;Up to 50 multimodal inputs&lt;/td&gt;
&lt;td&gt;More control over identity, style, and branding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Editing&lt;/td&gt;
&lt;td&gt;Basic refinement&lt;/td&gt;
&lt;td&gt;Local or region editing with improved consistency&lt;/td&gt;
&lt;td&gt;More targeted iteration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;Up to 1080p/4K options&lt;/td&gt;
&lt;td&gt;Enhanced native 4K support&lt;/td&gt;
&lt;td&gt;Sharper production output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continuation&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Higher-quality continuation with rhythmic consistency&lt;/td&gt;
&lt;td&gt;Easier longer-form work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt adherence&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;td&gt;Approximately 20% better, as reported&lt;/td&gt;
&lt;td&gt;Potentially fewer retries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use&lt;/td&gt;
&lt;td&gt;Short clips and basic multimodal work&lt;/td&gt;
&lt;td&gt;Cinematic scenes, previsualization, and branded long-form content&lt;/td&gt;
&lt;td&gt;Broader professional use&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reported improvement figures are vendor-reported. Generation speed, failure rates, and independent quality metrics still need to be validated after public release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release Timeline
&lt;/h2&gt;

&lt;p&gt;ByteDance previewed Seedance 2.5 in late June 2026 at the Volcano Engine conference. The expected public launch window is early July 2026, following an enterprise beta and expansion through platforms such as Dreamina, CapCut, and API providers.&lt;/p&gt;

&lt;p&gt;As of late June 2026, access remained limited. Developers should verify model availability, pricing, and exact output specifications before committing to a production workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling the Video Endpoint
&lt;/h2&gt;

&lt;p&gt;For an OpenAI-compatible video workflow, the request can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/v1/videos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A slow cinematic camera push across a coastal landscape at sunrise&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;doubao-seedance-2-0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16:9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A unified multi-model API such as CometAPI is useful here when the application needs one integration point for text, image, and video models, or when it needs to switch between Seedance versions during evaluation and rollout.&lt;/p&gt;

&lt;p&gt;For multimodal references, add an &lt;code&gt;input_reference&lt;/code&gt; file for image-guided generation. Advanced multi-reference requests can repeat the same multipart fields in upload order. The uploaded files can then be referenced sequentially as &lt;code&gt;[Image 1]&lt;/code&gt;, &lt;code&gt;[Image 2]&lt;/code&gt;, and &lt;code&gt;[Image 3]&lt;/code&gt;, with a specific role assigned to each image in the prompt.&lt;/p&gt;

&lt;p&gt;Video generation is asynchronous. Submit the task, retain its ID, and poll the video status endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /v1/videos/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Seedance query endpoint returns the current task status, progress, and the signed video URL after completion. The documented polling flow works for Seedance 1.0 Pro, 1.5 Pro, and 2.0. Node.js and cURL clients use the same request shape with the appropriate base URL and credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Workloads
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Social Advertising
&lt;/h3&gt;

&lt;p&gt;A 30-second clip can contain the hook, problem, product reveal, proof point, lifestyle shot, and call to action in one generation. Teams can then create variants by audience, region, aspect ratio, product, or visual style.&lt;/p&gt;

&lt;h3&gt;
  
  
  Product and E-Commerce Video
&lt;/h3&gt;

&lt;p&gt;Reference-driven generation can turn catalog images into lifestyle scenes for seasonal campaigns, marketplace listings, product pages, and localized promotions. Human review remains necessary, but the approach can reduce the time needed for initial concepts and variant production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storyboards and Previsualization
&lt;/h3&gt;

&lt;p&gt;Film, animation, and agency teams can explore camera movement, blocking, lighting, pacing, and visual style before committing to a shoot or full production. A 30-second draft can also support pitches and client approvals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Training and Education
&lt;/h3&gt;

&lt;p&gt;Short generated videos fit onboarding, safety explanations, product walkthroughs, classroom examples, and internal training. Multimodal references make it possible to match a company’s equipment, environment, or product rather than relying on generic stock footage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creative Localization
&lt;/h3&gt;

&lt;p&gt;Reference consistency and local editing are important for producing variants across languages, climates, packaging versions, and audience segments. The goal is to modify the relevant creative elements without regenerating the entire campaign from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Notes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Build an Evaluation Set
&lt;/h3&gt;

&lt;p&gt;I would start with evaluation rather than direct customer-facing automation. Include product ads, character scenes, motion-heavy prompts, brand-safe requests, rejected prompts, and edge cases.&lt;/p&gt;

&lt;p&gt;Score at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt adherence&lt;/li&gt;
&lt;li&gt;Identity and reference consistency&lt;/li&gt;
&lt;li&gt;Motion quality&lt;/li&gt;
&lt;li&gt;Visual artifacts&lt;/li&gt;
&lt;li&gt;Audio quality&lt;/li&gt;
&lt;li&gt;Moderation behavior&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;Failure and retry rates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Keep Generation Asynchronous
&lt;/h3&gt;

&lt;p&gt;A 30-second video can take substantially longer than a chat completion or image request. Use a queue, persist task IDs, poll status, and notify users when the signed output is ready. This avoids request timeouts and makes retries explicit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version Everything
&lt;/h3&gt;

&lt;p&gt;Store the prompt, model ID, parameters, reference IDs, output URL, reviewer score, and final decision. Prompt and output versioning makes comparisons between Seedance 2.5, Seedance 2.0, Veo, Kling, Runway, and other models reproducible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retain Human Review
&lt;/h3&gt;

&lt;p&gt;Commercial video introduces brand, legal, likeness, and copyright concerns. Human review is appropriate for public advertising, realistic people, influencer-like content, regulated industries, and outputs using third-party references.&lt;/p&gt;

&lt;p&gt;Avoid requests involving copyrighted characters, real people without permission, or misleading depictions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Fallbacks
&lt;/h3&gt;

&lt;p&gt;Do not assume one model should serve every workload. Short drafts may be better handled by Seedance 2.0 or a faster video model, while Seedance 2.5 can be reserved for final, high-value generations. Availability, latency, and cost should all be part of routing decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Seedance 2.5 available?
&lt;/h3&gt;

&lt;p&gt;As of June 30, 2026, it was reportedly in global enterprise beta, with public availability expected in early July 2026. Developers should check the live model catalog before using it in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long can it generate?
&lt;/h3&gt;

&lt;p&gt;The headline capability is native video generation up to 30 seconds. Seedance 2.0’s documented generation range is 4-15 seconds, so the newer model substantially increases single-pass duration.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the main difference from Seedance 2.0?
&lt;/h3&gt;

&lt;p&gt;Seedance 2.5 adds native 30-second generation, up to 50 multimodal references, and improved local editing control. Seedance 2.0 already provides text, image, audio, and video inputs, native audio-video generation, and strong motion stability.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is it best suited for?
&lt;/h3&gt;

&lt;p&gt;The strongest target workloads are 30-second social ads, product videos, cinematic storyboards, previsualization, brand-consistent creative variants, e-commerce demonstrations, training clips, and other reference-heavy generation tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should developers verify before production?
&lt;/h3&gt;

&lt;p&gt;Confirm the live model ID, access status, pricing, exact resolution and duration limits, output formats, generation latency, failure behavior, moderation rules, and signed URL lifetime. These details may change as the model moves from beta to public release.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/what-is-seedance-2-5/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=what-is-seedance-2-5"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Calling Claude Through a Gateway: SDK Choices and Production Trade-offs</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 02:39:29 +0000</pubDate>
      <link>https://dev.to/masonreed1/calling-claude-through-a-gateway-sdk-choices-and-production-trade-offs-3g6f</link>
      <guid>https://dev.to/masonreed1/calling-claude-through-a-gateway-sdk-choices-and-production-trade-offs-3g6f</guid>
      <description>&lt;p&gt;I reach for a unified gateway when an application needs several model providers but does not need several separate account, billing, and SDK integrations. It is also a way to call Claude without maintaining a direct Anthropic developer account: the application authenticates with the gateway, which routes requests upstream.&lt;/p&gt;

&lt;p&gt;CometAPI is one example, advertising Claude, GPT, and 500+ other generative AI models behind a single key and an OpenAI-compatible endpoint. Its mid-2026 model listings include Claude Opus 4.8 and Claude Sonnet 5. Those are catalog claims, so I would confirm current availability before choosing a production model.&lt;/p&gt;

&lt;p&gt;The important decision is not just which provider handles billing. It is whether the application needs a portable chat interface or Claude-specific request semantics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the API Contract First
&lt;/h2&gt;

&lt;p&gt;The gateway exposes two integration paths:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;OpenAI-compatible API&lt;/th&gt;
&lt;th&gt;Native Anthropic Messages API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Endpoint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/v1/chat/completions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/v1/messages&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK base URL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://api.cometapi.com/v1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://api.cometapi.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model scope&lt;/td&gt;
&lt;td&gt;Multiple providers, including GPT, Claude, and Gemini&lt;/td&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;Bearer&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;x-api-key&lt;/code&gt; or Bearer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response structure&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;choices&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Content blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude-specific controls&lt;/td&gt;
&lt;td&gt;Not exposed through this compatibility path&lt;/td&gt;
&lt;td&gt;Thinking, caching, effort, server-side tools&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I would use chat completions for shared application code across providers. I would choose Messages when extended thinking, prompt caching, or server-side tools are part of the actual workflow. A common interface is useful, but it is not a promise that every model has identical capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reuse an OpenAI Client
&lt;/h2&gt;

&lt;p&gt;Install the SDK with &lt;code&gt;pip install openai&lt;/code&gt;. Generate a gateway key, then change the client’s &lt;code&gt;base_url&lt;/code&gt; and &lt;code&gt;api_key&lt;/code&gt;. This request retains the source example’s model, temperature, and output limit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_gateway_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4.8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What are the primary structural benefits of a unified API gateway?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For streaming, the gateway translates Claude’s native server-sent events into OpenAI-compatible chunks. Using the same client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4.8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain the concept of latency overhead in unified APIs.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changing &lt;code&gt;model&lt;/code&gt; lets this integration address another supported model without replacing the client or streaming loop. I would still test parameter support, tool behavior, structured output, and error handling for each target. Request compatibility reduces integration work; it does not eliminate model-specific validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Claude-Specific Features on the Messages Path
&lt;/h2&gt;

&lt;p&gt;The native route uses the official Anthropic SDK, but the key comes from the gateway. Set &lt;code&gt;COMETAPI_KEY&lt;/code&gt; in the environment before running this example. Notice that the base URL does &lt;strong&gt;not&lt;/strong&gt; include &lt;code&gt;/v1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, world&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK sends &lt;code&gt;x-api-key&lt;/code&gt; by default; the endpoint also accepts &lt;code&gt;Authorization: Bearer&lt;/code&gt;. The documented Claude-specific controls include &lt;code&gt;thinking&lt;/code&gt; with a minimum &lt;code&gt;budget_tokens&lt;/code&gt; of 1,024, &lt;code&gt;cache_control&lt;/code&gt; on content blocks, &lt;code&gt;output_config.effort&lt;/code&gt;, and server-side &lt;code&gt;web_fetch&lt;/code&gt; and &lt;code&gt;web_search&lt;/code&gt; tools. Check support against the selected model rather than assuming every Claude version accepts every control. The native example uses &lt;code&gt;claude-sonnet-4-6&lt;/code&gt;, not the Sonnet 5 model mentioned in the catalog.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Verify Before Shipping
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Latency and Compatibility
&lt;/h3&gt;

&lt;p&gt;Every gateway introduces another network hop plus authentication, routing, and potentially schema translation. The source reports typical overhead below 400 ms; I would treat that as a claim to benchmark, not a latency guarantee. Background summarization can tolerate a different budget from real-time voice or tightly timed agent workflows. Streaming does not remove the need to measure initial response latency.&lt;/p&gt;

&lt;p&gt;System prompts, temperature, structured JSON output, and tool/function calling are described as supported through the compatibility layer. Newly released or proprietary features may arrive later. For a workflow that depends on a particular feature, I would check the compatibility documentation and test the exact request. The native endpoint avoids some translation constraints, but its availability still needs verification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Handling and Access
&lt;/h3&gt;

&lt;p&gt;The gateway describes encrypted transit, including TLS 1.3, minimized persistent logging, and enterprise zero data retention configurations. “Minimized logging” is not the same commitment as ZDR. I would review retention, zero-data-training policies, logging configuration, and contractual scope before sending sensitive inputs.&lt;/p&gt;

&lt;p&gt;Inference still happens at the upstream provider. Both the gateway’s handling and the model host’s data processing agreements matter. Likewise, using a gateway does not automatically remove regional compliance obligations, payment restrictions, or upstream access rules. A single account may simplify access, but it is not a universal compliance exemption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quotas, Cost, and Governance
&lt;/h3&gt;

&lt;p&gt;Consolidated billing is the clearest operational benefit: fewer prepaid balances, invoices, credentials, and usage dashboards to maintain. Gateway quotas can simplify capacity management, but I would verify actual limits and throttling behavior rather than assume there is no upstream constraint or production approval process.&lt;/p&gt;

&lt;p&gt;The source advertises pay-as-you-go pricing with no monthly fee, rates 20–40% below official pricing, and 1 million free signup tokens. These are commercial terms to confirm during evaluation, not architectural guarantees. Compare the price of the actual models and features the workload uses.&lt;/p&gt;

&lt;p&gt;A shared interface also makes task-based routing easier. I would reserve a flagship model such as Claude Opus 4.8 for complex reasoning or long-context analysis, then evaluate cheaper models for classification, extraction, and formatting. Switching a model identifier is easy; proving acceptable output quality is the work.&lt;/p&gt;

&lt;p&gt;The documented dashboard supports usage monitoring, project spending limits, access-token management, and budgets assigned to individual API keys. Those controls are worth testing: centralized billing only helps governance if an experimental project cannot consume the organization’s entire allocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Decision Rule
&lt;/h2&gt;

&lt;p&gt;I would choose a gateway when multi-model routing, A/B testing, consolidated procurement, and reduced SDK maintenance justify another dependency in the request path. I would use the OpenAI-compatible endpoint for portable chat workflows and the native Messages endpoint for Claude-specific behavior.&lt;/p&gt;

&lt;p&gt;Before rollout, I would validate model availability, feature support, latency, quotas, current pricing, and both layers of data handling. Avoiding a direct Anthropic account simplifies administration. It does not remove the engineering responsibility to understand where requests go and what contract the application relies on.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/how-to-access-the-claude-api-without-an-anthropic-account/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=how-to-access-the-claude-api-without-an-anthropic-account"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>GPT-6 Astra Access: Verify the Route, Then Make One Small Call</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Mon, 21 Sep 2026 01:53:33 +0000</pubDate>
      <link>https://dev.to/masonreed1/gpt-6-astra-access-verify-the-route-then-make-one-small-call-24h9</link>
      <guid>https://dev.to/masonreed1/gpt-6-astra-access-verify-the-route-then-make-one-small-call-24h9</guid>
      <description>&lt;p&gt;I treat API access as three separate checks: the gateway lists the model, the credential works, and an authenticated request completes. Creating a key only covers part of that.&lt;/p&gt;

&lt;p&gt;For a unified multi-model API such as CometAPI, the credential must belong to the gateway receiving the request. An OpenAI SDK client can target that gateway, but it still needs the gateway’s key and base URL.&lt;/p&gt;

&lt;p&gt;Here’s the sequence I’d use to verify &lt;code&gt;gpt-6-astra&lt;/code&gt; access before wiring it into an application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the model catalog first
&lt;/h2&gt;

&lt;p&gt;The source guide reported &lt;code&gt;gpt-6-astra&lt;/code&gt; as available, with &lt;code&gt;upcoming: false&lt;/code&gt; and support for both &lt;code&gt;/v1/responses&lt;/code&gt; and &lt;code&gt;/v1/chat/completions&lt;/code&gt;. Treat that as a dated observation: check the live catalog before integration.&lt;/p&gt;

&lt;p&gt;The public catalog endpoint requires no Authorization header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://api.cometapi.com/api/models &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="s1"&gt;'.data[] | select(.id == "gpt-6-astra") | {
      id,
      provider,
      upcoming,
      endpoints
    }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for the exact ID, &lt;code&gt;upcoming&lt;/code&gt; set to &lt;code&gt;false&lt;/code&gt;, and the route you intend to use in &lt;code&gt;endpoints&lt;/code&gt;. That establishes public routing availability; it does not validate your account or key.&lt;/p&gt;

&lt;p&gt;If the command prints nothing, check the spelling and the &lt;a href="https://www.cometapi.com/models/openai/gpt-6-astra/" rel="noopener noreferrer"&gt;live model page&lt;/a&gt;. Don’t substitute a display name, prepend a provider name, or borrow an alias from another gateway.&lt;/p&gt;

&lt;p&gt;I’d start with &lt;code&gt;/v1/responses&lt;/code&gt; for the reasoning workflow described here. Use &lt;code&gt;/v1/chat/completions&lt;/code&gt; when the application specifically needs the messages-based interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a credential with a limited quota
&lt;/h2&gt;

&lt;p&gt;Create an account, sign in, and open the &lt;a href="https://www.cometapi.com/console/token" rel="noopener noreferrer"&gt;API Keys page&lt;/a&gt;. Select &lt;strong&gt;Create API Key&lt;/strong&gt;, name it something recognizable such as &lt;code&gt;astra-dev&lt;/code&gt;, choose an appropriate quota, and copy the value.&lt;/p&gt;

&lt;p&gt;You also need sufficient account credit or quota and a server-side environment for storing the credential. For a local Bash session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-rsp&lt;/span&gt; &lt;span class="s2"&gt;"Gateway API key: "&lt;/span&gt; COMETAPI_KEY
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;COMETAPI_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep development, staging, and production keys separate. Explicit quotas limit the damage from accidental loops or leaked credentials, while descriptive names make rotation easier.&lt;/p&gt;

&lt;p&gt;Store deployed credentials in a secrets manager or server-side environment variable. Keep them out of browser JavaScript, mobile bundles, repositories, screenshots, and support tickets. Store any direct OpenAI credentials separately so configuration changes cannot silently mix providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the smallest useful request
&lt;/h2&gt;

&lt;p&gt;My first request would contain no tools, files, streaming, or long context. A small payload makes authentication and routing failures easier to isolate.&lt;/p&gt;

&lt;p&gt;Send the gateway key to the gateway endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--fail-with-body&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://api.cometapi.com/v1/responses &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$COMETAPI_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "gpt-6-astra",
    "input": "Reply with exactly: GPT-6 Astra access confirmed.",
    "reasoning": {"effort": "low"},
    "max_output_tokens": 40
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The target is HTTP 200 with a response object containing an &lt;code&gt;id&lt;/code&gt;, a completed status, the expected model, output content, and usage data. Keep the response ID during testing; it helps investigate routing or platform problems.&lt;/p&gt;

&lt;p&gt;An HTML page or redirect does not establish API access. Check the hostname and path before changing the payload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the same configuration in Python
&lt;/h3&gt;

&lt;p&gt;The OpenAI Python SDK can make the same request with an explicit &lt;code&gt;api_key&lt;/code&gt;, &lt;code&gt;base_url&lt;/code&gt;, and model selection. A separate gateway SDK is unnecessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMETAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.cometapi.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-6-astra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reply with exactly: GPT-6 Astra access confirmed.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;max_output_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;https://api.cometapi.com/v1&lt;/code&gt; as the SDK base URL and &lt;code&gt;https://api.cometapi.com/v1/responses&lt;/code&gt; for the direct request. Neither URL has a trailing period. Don’t substitute &lt;code&gt;api.openai.com&lt;/code&gt; while retaining the gateway credential.&lt;/p&gt;

&lt;p&gt;Once the minimal call succeeds, add application instructions and features individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide what counts as a successful access test
&lt;/h2&gt;

&lt;p&gt;I’d keep four checks in the integration notes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;What it establishes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Catalog returns &lt;code&gt;gpt-6-astra&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The public catalog recognizes the model and lists its routes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authenticated endpoint returns JSON&lt;/td&gt;
&lt;td&gt;The request reaches an API endpoint rather than a login page or redirect.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response completes with the expected model&lt;/td&gt;
&lt;td&gt;The key, account, route, payload, and model routing worked together for that request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usage appears in the dashboard&lt;/td&gt;
&lt;td&gt;The request is recorded against the intended account.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A successful catalog lookup cannot prove private access. Likewise, a key’s existence cannot guarantee sufficient quota, current availability, a valid payload, or acceptance under rate limits.&lt;/p&gt;

&lt;p&gt;Check usage or billing records after the first call. This also gives you a starting point for cost monitoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnose failures before retrying
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication and access: 401 or 403
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;401 Unauthorized&lt;/strong&gt;, check for a missing, malformed, or expired key and verify the destination host. The header should be exactly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authorization: Bearer $COMETAPI_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload the environment variable or rotate the credential if needed. Repeating the same invalid credential will not help.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;403 Forbidden&lt;/strong&gt;, return to the minimal payload, remove optional fields, and check account status, quota, and model access. Treat it as an access or request problem before assuming a temporary outage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Routing: HTML, redirects, or model-not-found errors
&lt;/h3&gt;

&lt;p&gt;Recheck the base URL and endpoint path. During debugging, avoid silently following redirects on the authenticated request: a wrong path can otherwise appear to be a successful connection.&lt;/p&gt;

&lt;p&gt;For a model-not-found response, query the catalog again and compare the exact &lt;code&gt;gpt-6-astra&lt;/code&gt; identifier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate limits and server failures
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;429 Too Many Requests&lt;/strong&gt;, inspect the error body and account limits. Reduce burst concurrency and use exponential backoff with jitter for rate-limit retries. Monitor usage by model and route.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;500, 503, 504, or 524&lt;/strong&gt;, retain any request or response ID and use bounded backoff for temporary platform or timeout failures. Inspect the body first: if it reports &lt;code&gt;invalid_request&lt;/code&gt;, fix the payload before retrying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put production controls around the working call
&lt;/h2&gt;

&lt;p&gt;After access is confirmed, issue a production-specific key with the smallest practical quota. Store it in a secrets manager, restrict who can view or rotate it, and document rotation.&lt;/p&gt;

&lt;p&gt;Keep model calls on your server. Browser and mobile clients should call your authenticated backend, where you can enforce user permissions, rate limits, and spending controls.&lt;/p&gt;

&lt;p&gt;Log the route, model ID, HTTP status, latency, response ID, and token usage. Redact credentials and sensitive prompt data. Track development and production separately so test traffic does not obscure production failures.&lt;/p&gt;

&lt;p&gt;For payload changes, consult the &lt;a href="https://apidoc.cometapi.com/api/text/responses" rel="noopener noreferrer"&gt;Responses API documentation&lt;/a&gt;. The source also links a &lt;a href="https://developers.openai.com/api/docs/models/gpt-6-astra" rel="noopener noreferrer"&gt;first-party model reference&lt;/a&gt;; check current documentation and the live catalog before relying on a capability or endpoint.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/get-gpt-6-astra-api-access-cometapi/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=get-gpt-6-astra-api-access-cometapi"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>GPT-5.6 API Costs: What I’d Budget Beyond the Token Price</title>
      <dc:creator>Mason Reed</dc:creator>
      <pubDate>Fri, 18 Sep 2026 17:10:24 +0000</pubDate>
      <link>https://dev.to/masonreed1/gpt-56-api-costs-what-id-budget-beyond-the-token-price-1m7e</link>
      <guid>https://dev.to/masonreed1/gpt-56-api-costs-what-id-budget-beyond-the-token-price-1m7e</guid>
      <description>&lt;h2&gt;
  
  
  Start with the route, not the family name
&lt;/h2&gt;

&lt;p&gt;The first thing I’d check in a GPT-5.6 integration is the model ID. According to OpenAI’s &lt;a href="https://developers.openai.com/api/docs/guides/latest-model" rel="noopener noreferrer"&gt;model guidance&lt;/a&gt;, &lt;code&gt;gpt-5.6&lt;/code&gt; routes to &lt;code&gt;gpt-5.6-sol&lt;/code&gt;. It does not automatically select the cheapest tier that can handle a request.&lt;/p&gt;

&lt;p&gt;If I want Terra or Luna pricing, I’d use &lt;code&gt;gpt-5.6-terra&lt;/code&gt; or &lt;code&gt;gpt-5.6-luna&lt;/code&gt; explicitly.&lt;/p&gt;

&lt;p&gt;The July 30, 2026 pricing update reduced Terra rates by &lt;strong&gt;20%&lt;/strong&gt; and Luna rates by &lt;strong&gt;80%&lt;/strong&gt;, while leaving Sol unchanged. Here are the updated Standard rates for requests with &lt;strong&gt;at most 272,000 input tokens&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;All token prices below are USD per 1 million tokens.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Cached input&lt;/th&gt;
&lt;th&gt;Cache write&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.6-sol&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;$6.25&lt;/td&gt;
&lt;td&gt;$30.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.6-terra&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$2.00&lt;/td&gt;
&lt;td&gt;$0.20&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$12.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.6-luna&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.20&lt;/td&gt;
&lt;td&gt;$0.02&lt;/td&gt;
&lt;td&gt;$0.25&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Source: &lt;a href="https://developers.openai.com/api/docs/pricing" rel="noopener noreferrer"&gt;OpenAI API pricing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenAI positions Sol as the flagship, Terra as the balanced option, and Luna as the low-cost tier for high-volume work. I’d treat those descriptions as evaluation starting points, not routing rules.&lt;/p&gt;

&lt;p&gt;The number that matters most for ordinary short-context traffic: &lt;strong&gt;output costs 6× as much as uncached input&lt;/strong&gt; across all three tiers. Trimming unnecessary response text can matter more than shaving a few tokens off a system prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the rates through an actual workload
&lt;/h2&gt;

&lt;p&gt;A rate table is useful, but I prefer turning it into request costs immediately. The examples here use the updated July rates consistently, without caching, tools, retries, or regional adjustments.&lt;/p&gt;

&lt;h3&gt;
  
  
  A 1,000-input, 500-output request
&lt;/h3&gt;

&lt;p&gt;For Sol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input:  1,000 / 1,000,000 × $5  = $0.005
Output:   500 / 1,000,000 × $30 = $0.015
Total:                           $0.020
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying the same request shape to each model:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input cost&lt;/th&gt;
&lt;th&gt;Output cost&lt;/th&gt;
&lt;th&gt;Total per request&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sol&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;$0.015&lt;/td&gt;
&lt;td&gt;$0.020&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terra&lt;/td&gt;
&lt;td&gt;$0.002&lt;/td&gt;
&lt;td&gt;$0.006&lt;/td&gt;
&lt;td&gt;$0.008&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Luna&lt;/td&gt;
&lt;td&gt;$0.0002&lt;/td&gt;
&lt;td&gt;$0.0006&lt;/td&gt;
&lt;td&gt;$0.0008&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Output accounts for &lt;strong&gt;75%&lt;/strong&gt; of the token bill even though the request contains twice as many input tokens as output tokens.&lt;/p&gt;

&lt;p&gt;For chat, code generation, and agents, I’d look for unnecessary verbosity before spending much time optimizing a small prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  One million requests per month
&lt;/h3&gt;

&lt;p&gt;Now change the workload to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 million requests per month&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2,000 input tokens per request&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;500 output tokens per request&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That produces &lt;strong&gt;2 billion input tokens&lt;/strong&gt; and &lt;strong&gt;500 million output tokens&lt;/strong&gt; monthly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Monthly input&lt;/th&gt;
&lt;th&gt;Monthly output&lt;/th&gt;
&lt;th&gt;Monthly total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sol&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;td&gt;$15,000&lt;/td&gt;
&lt;td&gt;$25,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terra&lt;/td&gt;
&lt;td&gt;$4,000&lt;/td&gt;
&lt;td&gt;$6,000&lt;/td&gt;
&lt;td&gt;$10,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Luna&lt;/td&gt;
&lt;td&gt;$400&lt;/td&gt;
&lt;td&gt;$600&lt;/td&gt;
&lt;td&gt;$1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For this workload, the price cuts move Terra from &lt;strong&gt;$12,500 to $10,000&lt;/strong&gt; and Luna from &lt;strong&gt;$5,000 to $1,000&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Those differences justify routing experiments. They do not prove that Luna is the cheapest way to complete the work. More retries, failed tool calls, or manual review can consume the apparent savings.&lt;/p&gt;

&lt;p&gt;My preferred metric is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cost per successful task = total workflow cost / successful tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’d track human review alongside that metric, rather than pretending it disappears because it is absent from the API invoice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat 272K input tokens as a billing boundary
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 supports a &lt;strong&gt;1.05M-token context window&lt;/strong&gt;, but context capacity and short-context pricing are different limits.&lt;/p&gt;

&lt;p&gt;When input exceeds &lt;strong&gt;272,000 tokens&lt;/strong&gt;, the higher rates apply to the &lt;strong&gt;entire request&lt;/strong&gt;, not just the excess tokens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input: &lt;strong&gt;2×&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Cached input: &lt;strong&gt;2×&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Cache writes: &lt;strong&gt;2×&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Output: &lt;strong&gt;1.5×&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Long input&lt;/th&gt;
&lt;th&gt;Long cached input&lt;/th&gt;
&lt;th&gt;Long cache write&lt;/th&gt;
&lt;th&gt;Long output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sol&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$12.50&lt;/td&gt;
&lt;td&gt;$45.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terra&lt;/td&gt;
&lt;td&gt;$4.00&lt;/td&gt;
&lt;td&gt;$0.40&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$18.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Luna&lt;/td&gt;
&lt;td&gt;$0.40&lt;/td&gt;
&lt;td&gt;$0.04&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;$1.80&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is a pricing cliff, not a gradual overage charge. It also means the &lt;strong&gt;6× output-to-input ratio applies to short-context Standard pricing&lt;/strong&gt;; long-context pricing has a different ratio because the multipliers differ.&lt;/p&gt;

&lt;p&gt;Near the boundary, I’d inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate retrieval chunks&lt;/li&gt;
&lt;li&gt;Stale conversation history&lt;/li&gt;
&lt;li&gt;Repository files unrelated to the task&lt;/li&gt;
&lt;li&gt;Tool output that could be reduced before the next model call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That cleanup can do more than reduce token count: it can keep the whole request in the lower pricing band. OpenAI’s &lt;a href="https://developers.openai.com/api/docs/guides/cost-optimization" rel="noopener noreferrer"&gt;cost optimization guide&lt;/a&gt; covers additional approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a processing tier separately from the model
&lt;/h2&gt;

&lt;p&gt;Model selection is only one pricing decision. Eligible GPT-5.6 text workloads also have different processing options.&lt;/p&gt;

&lt;p&gt;These are short-context input/output rates per 1 million tokens:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Processing option&lt;/th&gt;
&lt;th&gt;Sol&lt;/th&gt;
&lt;th&gt;Terra&lt;/th&gt;
&lt;th&gt;Luna&lt;/th&gt;
&lt;th&gt;Where I’d consider it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;$5 / $30&lt;/td&gt;
&lt;td&gt;$2 / $12&lt;/td&gt;
&lt;td&gt;$0.20 / $1.20&lt;/td&gt;
&lt;td&gt;Normal synchronous traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch&lt;/td&gt;
&lt;td&gt;$2.50 / $15&lt;/td&gt;
&lt;td&gt;$1 / $6&lt;/td&gt;
&lt;td&gt;$0.10 / $0.60&lt;/td&gt;
&lt;td&gt;Offline asynchronous jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flex&lt;/td&gt;
&lt;td&gt;$2.50 / $15&lt;/td&gt;
&lt;td&gt;$1 / $6&lt;/td&gt;
&lt;td&gt;$0.10 / $0.60&lt;/td&gt;
&lt;td&gt;Work that tolerates slower processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fast mode&lt;/td&gt;
&lt;td&gt;$10 / $60&lt;/td&gt;
&lt;td&gt;$4 / $24&lt;/td&gt;
&lt;td&gt;$0.40 / $2.40&lt;/td&gt;
&lt;td&gt;Latency-sensitive traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The listed Batch and Flex rates are &lt;strong&gt;50% below Standard&lt;/strong&gt;. I’d check their operational constraints before moving any production workload, rather than treating them as interchangeable discounts.&lt;/p&gt;

&lt;p&gt;Priority Processing was renamed &lt;strong&gt;Fast mode on July 30, 2026&lt;/strong&gt;. Existing requests using &lt;code&gt;service_tier: "priority"&lt;/code&gt; remain compatible.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Sol&lt;/strong&gt;, Fast mode offers &lt;strong&gt;up to 2.5× faster processing&lt;/strong&gt; at &lt;strong&gt;2× the Standard token price&lt;/strong&gt;, without changing model intelligence. That is a latency trade-off, not a quality upgrade. I’d pay for it only where the user-facing benefit justifies the premium.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache reuse, not merely long prompts
&lt;/h2&gt;

&lt;p&gt;Cache writes cost &lt;strong&gt;1.25× normal input&lt;/strong&gt;, while matching cached reads use the discounted cached-input rate.&lt;/p&gt;

&lt;p&gt;For a reusable &lt;strong&gt;100,000-token prefix&lt;/strong&gt; on short-context Sol:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Prefix input cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;One uncached use&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One cache write&lt;/td&gt;
&lt;td&gt;$0.625, approximately $0.63&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One matching cached read&lt;/td&gt;
&lt;td&gt;$0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two uncached uses cost &lt;strong&gt;$1.00&lt;/strong&gt;. A cache write followed by one matching read costs &lt;strong&gt;$0.675&lt;/strong&gt;, saving &lt;strong&gt;$0.325&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That comparison covers only the reusable prefix. It excludes output, other uncached input, tools, and retries.&lt;/p&gt;

&lt;p&gt;The practical distinction is between a long prefix and a &lt;strong&gt;long, stable, reused prefix&lt;/strong&gt;. A write that never gets reused costs more than ordinary input processing.&lt;/p&gt;

&lt;p&gt;I’d measure actual cache hits and read the &lt;a href="https://developers.openai.com/api/docs/guides/prompt-caching" rel="noopener noreferrer"&gt;prompt caching documentation&lt;/a&gt; for matching requirements, explicit breakpoints, and TTL behavior before building savings into a forecast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Budget for tokens you don’t see and calls outside the model
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reasoning is billed output
&lt;/h3&gt;

&lt;p&gt;Reasoning tokens are charged as output tokens even when they do not appear in the visible response. A concise answer does not necessarily imply a small output-token bill.&lt;/p&gt;

&lt;p&gt;Where supported, &lt;code&gt;reasoning.mode = "pro"&lt;/code&gt; is a setting I’d benchmark rather than enable by default. OpenAI does not list a separate fixed Pro surcharge; its cost impact comes from resulting token usage.&lt;/p&gt;

&lt;p&gt;The comparison should include task success, total output tokens, latency, and retries—not just whether one response looks better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Search has its own bill
&lt;/h3&gt;

&lt;p&gt;Standard web search is listed at &lt;strong&gt;$10 per 1,000 calls&lt;/strong&gt;, plus search-content tokens billed at the selected model rate.&lt;/p&gt;

&lt;p&gt;At that price, two searches can cost more than the model tokens for a small Luna request.&lt;/p&gt;

&lt;p&gt;There is also a separate &lt;strong&gt;web search preview&lt;/strong&gt; rate for non-reasoning models: &lt;strong&gt;$25 per 1,000 calls&lt;/strong&gt;, with search-content tokens free. I would not apply one search rate across every tool and endpoint. Check the exact combination on the &lt;a href="https://developers.openai.com/api/docs/pricing" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Residency can add an uplift
&lt;/h3&gt;

&lt;p&gt;Eligible regional processing or data-residency endpoints for models released on or after &lt;strong&gt;March 5, 2026&lt;/strong&gt; carry a &lt;strong&gt;10% uplift&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If residency is a requirement, that belongs in the initial estimate—not in an explanation for why the first invoice exceeded it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the older models in the comparison
&lt;/h2&gt;

&lt;p&gt;A new family does not make previous routes irrelevant. These are the listed Standard short-context rates for several other OpenAI text models:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Cached input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;$30.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$0.25&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.4-mini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.75&lt;/td&gt;
&lt;td&gt;$0.075&lt;/td&gt;
&lt;td&gt;$4.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.4-nano&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.20&lt;/td&gt;
&lt;td&gt;$0.02&lt;/td&gt;
&lt;td&gt;$1.25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Luna now matches GPT-5.4 nano’s &lt;strong&gt;$0.20 input rate&lt;/strong&gt;, with slightly cheaper output: &lt;strong&gt;$1.20 versus $1.25&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is a useful pricing comparison, not evidence that the models behave identically. I’d keep existing routes in the evaluation set until the replacement earns its place.&lt;/p&gt;

&lt;p&gt;Also, ChatGPT subscriptions and API billing are separate products. “ChatGPT API pricing” does not identify a rate; the model and usage type do.&lt;/p&gt;

&lt;h2&gt;
  
  
  My production cost checklist
&lt;/h2&gt;

&lt;p&gt;For a basic uncached request, the arithmetic is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Token cost =
    (input tokens / 1,000,000 × input rate)
  + (output tokens / 1,000,000 × output rate)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, I’d expand that into a workflow estimate covering uncached input, cached reads, cache writes, output and reasoning tokens, tool fees, applicable processing-tier rates, regional uplift, retries, and fallbacks.&lt;/p&gt;

&lt;p&gt;Then I’d run the same representative tasks through candidate routes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use explicit model IDs.&lt;/strong&gt; Avoid paying Sol rates accidentally through &lt;code&gt;gpt-5.6&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with the cheapest plausible model.&lt;/strong&gt; Promote difficult tasks based on measured results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record billed output, not just visible text.&lt;/strong&gt; Include reasoning usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor the 272K boundary.&lt;/strong&gt; Aggregate averages can hide expensive individual requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Batch or Flex for non-urgent work.&lt;/strong&gt; Verify operational fit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure cache reuse, tool calls, and retries.&lt;/strong&gt; Do not assume their costs cancel out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compare cost per successful task against latency and reliability.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For cross-provider evaluations, a unified API such as CometAPI can be useful for running the same workload through multiple OpenAI-compatible routes.&lt;/p&gt;

&lt;p&gt;The cheapest token rate is a starting hypothesis. The route I’d ship is the one that meets the quality and latency requirements at the lowest measured workflow cost.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.cometapi.com/gpt-5-6-pricing/?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=content&amp;amp;utm_content=gpt-5-6-pricing"&gt;cometapi.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
