<?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: Runcrate</title>
    <description>The latest articles on DEV Community by Runcrate (@runcrate).</description>
    <link>https://dev.to/runcrate</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%2F4196817%2Fac60595c-4ddb-4983-9e0e-2ba9145a50b5.png</url>
      <title>DEV Community: Runcrate</title>
      <link>https://dev.to/runcrate</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/runcrate"/>
    <language>en</language>
    <item>
      <title>How to compare GPU cloud prices without fooling yourself</title>
      <dc:creator>Runcrate</dc:creator>
      <pubDate>Wed, 21 Oct 2026 00:55:46 +0000</pubDate>
      <link>https://dev.to/runcrate/how-to-compare-gpu-cloud-prices-without-fooling-yourself-4p1l</link>
      <guid>https://dev.to/runcrate/how-to-compare-gpu-cloud-prices-without-fooling-yourself-4p1l</guid>
      <description>&lt;p&gt;"H100 from $X an hour" is the least useful number in a GPU price list. Two offers with the same headline can differ by a factor of two in what you pay at the end of the month, and two offers with very different headlines can come out the same.&lt;/p&gt;

&lt;p&gt;We publish GPU prices at Runcrate, and other people's comparison sites read them, so I spend a lot of time looking at how a price turns into a bill. This is the checklist I use. It works for any provider, ours included. I'll use our public pricing endpoint for the examples because it's the data I can show you with a script, not because the method depends on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Get to one unit: dollars per GPU-hour
&lt;/h2&gt;

&lt;p&gt;Some lists quote the machine, some quote the GPU. An 8x H100 node at a per-machine price looks eight times worse than a 1x H100 at a per-GPU price. Divide by the GPU count first, always.&lt;/p&gt;

&lt;p&gt;Runcrate's endpoint already reports per GPU-hour and needs no API key:&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;requests&lt;/span&gt;

&lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.runcrate.ai/api/gpu-pricing&lt;/span&gt;&lt;span class="sh"&gt;"&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetched at&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="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetched_at&lt;/span&gt;&lt;span class="sh"&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;g&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;specs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;per_gpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;num_gpus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;1&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&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="mi"&gt;12&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vram&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="sh"&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;$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min_price_hr&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="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; to $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_price_hr&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="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; per GPU-hr  &lt;/span&gt;&lt;span class="sh"&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;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;available_options&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; configs  GPUs per machine &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpu_counts&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="s"&gt;  &lt;/span&gt;&lt;span class="sh"&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;~&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vcpus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;per_gpu&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; vCPU / &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;per_gpu&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; GB RAM per GPU&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;p&gt;Part of what it printed when I ran it (fetched at 2026-10-21T00:51 UTC):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H100 SXM       80GB  $3.38 to $7.79 per GPU-hr   7 configs  GPUs per machine [1, 8]  ~20 vCPU / 128 GB RAM per GPU
A100 80GB      80GB  $1.76 to $4.26 per GPU-hr  12 configs  GPUs per machine [1, 2, 8]  ~28 vCPU / 120 GB RAM per GPU
L40S           48GB  $1.14 to $1.95 per GPU-hr  10 configs  GPUs per machine [1, 2, 4, 8]  ~12 vCPU / 72 GB RAM per GPU
A6000          48GB  $0.65 to $2.51 per GPU-hr  18 configs  GPUs per machine [1, 2, 4]  ~28 vCPU / 58 GB RAM per GPU
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the ranges. One GPU model can have a dozen configurations with a 2x to 4x spread between them. A comparison that keeps only the minimum hides that the minimum might be one 8-GPU node in one region.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Compare the same GPU, not the same name
&lt;/h2&gt;

&lt;p&gt;"A100" is two products (40 GB and 80 GB). "H100" is SXM or PCIe, with different memory bandwidth and interconnect. A "4090" with 24 GB will not hold the model your 48 GB card holds. Before comparing prices, match:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VRAM (the endpoint has &lt;code&gt;vram&lt;/code&gt; per GPU type)&lt;/li&gt;
&lt;li&gt;form factor and interconnect for multi-GPU work (&lt;code&gt;interconnect&lt;/code&gt;, for example NVLink)&lt;/li&gt;
&lt;li&gt;GPU count per machine, because you can't split an 8-GPU node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your model needs 80 GB, the price of a 40 GB card is irrelevant, however low it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Count what comes with the GPU
&lt;/h2&gt;

&lt;p&gt;A GPU-hour also buys CPU cores, RAM and local disk, and those vary a lot. In the output above, an A6000 can come with about 28 vCPUs, an L40S with about 12. For data loading, tokenization or anything CPU-bound in your pipeline, the "slower" card with more cores can finish first.&lt;/p&gt;

&lt;p&gt;So note, per GPU: vCPUs, RAM, local disk, and whether persistent storage costs extra. Runcrate's volumes, for example, are billed separately at $0.03 per GB per month. Your other quotes will have their own line for it, or bundle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Billing granularity matters more than the rate for short work
&lt;/h2&gt;

&lt;p&gt;This is the one most comparisons skip. Take a 7-minute eval on a $1.14/hr GPU:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;billed per second: 1.14 x 7 / 60 = &lt;strong&gt;$0.13&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;billed per started hour: &lt;strong&gt;$1.14&lt;/strong&gt;, nearly 9x more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For long training runs granularity barely matters. For evals, CI jobs, agent experiments and anything bursty, it dominates. Check three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The billing increment (second, minute, hour). Runcrate bills most instances by the second and a few GPUs by the minute; the endpoint's &lt;code&gt;min_price_per_minute&lt;/code&gt; flag marks the latter.&lt;/li&gt;
&lt;li&gt;When the meter starts: at request, at boot, or once the machine is running. Runcrate starts it when the machine is running, so provisioning isn't billed.&lt;/li&gt;
&lt;li&gt;When it stops: only when you remember to delete the machine, or also on its own. Idle shutdown and maximum runtimes turn "I forgot it overnight" from a 12-hour bill into a 30-minute one, which is worth more than a few cents on the rate.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  5. Listed is not launchable
&lt;/h2&gt;

&lt;p&gt;A price only matters if you can get the machine. Availability moves by the minute: in the same hour I wrote this, a GPU type showed one configuration on the pricing endpoint while a live launch query showed none. When comparing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;try an actual launch, or at least a live availability query, in the region you need&lt;/li&gt;
&lt;li&gt;note the count of configurations and regions, not just the headline price&lt;/li&gt;
&lt;li&gt;separate on-demand from spot or interruptible capacity, which is cheaper because it can disappear&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Date every number
&lt;/h2&gt;

&lt;p&gt;GPU prices change weekly, sometimes daily. A comparison without a date is a guess. Put the fetch time next to every price (the endpoint returns &lt;code&gt;fetched_at&lt;/code&gt; for that reason), and re-run your script rather than reusing last month's table.&lt;/p&gt;

&lt;h2&gt;
  
  
  A template you can reuse
&lt;/h2&gt;

&lt;p&gt;For each offer, one row:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPU model, VRAM, form factor&lt;/td&gt;
&lt;td&gt;same product?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPUs per machine&lt;/td&gt;
&lt;td&gt;can you buy just one?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$/GPU-hour&lt;/td&gt;
&lt;td&gt;the normalized rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vCPU, RAM, disk per GPU&lt;/td&gt;
&lt;td&gt;the rest of the machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Billing increment, meter start&lt;/td&gt;
&lt;td&gt;cost of short jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto-stop options&lt;/td&gt;
&lt;td&gt;cost of mistakes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage and egress&lt;/td&gt;
&lt;td&gt;cost of data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Region, availability checked at&lt;/td&gt;
&lt;td&gt;can you launch it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fetched at&lt;/td&gt;
&lt;td&gt;how old the number is&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Then price your actual workload (hours per run, runs per month, data moved) against each row. The offer with the best headline wins less often than you'd think.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Live prices: &lt;a href="https://www.runcrate.ai/pricing?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=tutorials" rel="noopener noreferrer"&gt;runcrate.ai/pricing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The JSON endpoint used above: &lt;code&gt;https://www.runcrate.ai/api/gpu-pricing&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Billing details: &lt;a href="https://www.runcrate.ai/docs/billing/pricing?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=tutorials" rel="noopener noreferrer"&gt;runcrate.ai/docs/billing/pricing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your comparison method has a step I've missed, I'd like to hear it. Reply here or write to &lt;a href="mailto:hello@runcrate.ai"&gt;hello@runcrate.ai&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written with AI assistance. The script and prices above were run against the live endpoint on 2026-10-21.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gpu</category>
      <category>cloud</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>Switch from OpenAI to open models in two lines (streaming, tools and JSON mode still work)</title>
      <dc:creator>Runcrate</dc:creator>
      <pubDate>Wed, 21 Oct 2026 00:33:52 +0000</pubDate>
      <link>https://dev.to/runcrate/switch-from-openai-to-open-models-in-two-lines-streaming-tools-and-json-mode-still-work-10o7</link>
      <guid>https://dev.to/runcrate/switch-from-openai-to-open-models-in-two-lines-streaming-tools-and-json-mode-still-work-10o7</guid>
      <description>&lt;p&gt;Most LLM code I see calls the OpenAI SDK. That's fine, because the SDK doesn't care whose server is on the other end. If the server speaks the same API, you can move a whole app to open models by changing two lines, and keep everything else: streaming, tool calls, JSON mode, retries.&lt;/p&gt;

&lt;p&gt;This post shows the switch with Runcrate's inference API, which serves 223 models behind one OpenAI-compatible endpoint, with open-weight families like DeepSeek, Qwen, Llama, Kimi, GLM and gpt-oss among them. Every snippet below was run against the live API on 2026-10-21.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two lines
&lt;/h2&gt;

&lt;p&gt;Before:&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&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;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.runcrate.ai/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="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;RUNCRATE_API_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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pick a model name from the catalog:&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;r&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;deepseek-ai/DeepSeek-V3.2&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;Summarize this stack trace: ...&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;r&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;Keys start with &lt;code&gt;rc_live_&lt;/code&gt; and come from Dashboard &amp;gt; Keys &amp;gt; API Keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Or zero lines
&lt;/h2&gt;

&lt;p&gt;Both official SDKs read the base URL and key from the environment, so for code that already does &lt;code&gt;OpenAI()&lt;/code&gt; with no arguments you don't have to touch the code at all:&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;OPENAI_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.runcrate.ai/v1
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rc_live_...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I checked this with &lt;code&gt;openai&lt;/code&gt; for Python and for Node. Same for TypeScript if you prefer it explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.runcrate.ai/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RUNCRATE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meta-llama/Llama-3.3-70B-Instruct-Turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reply with the word ok.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;And plain curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.runcrate.ai/v1/chat/completions &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;$RUNCRATE_API_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": "openai/gpt-oss-120b", "messages": [{"role": "user", "content": "Reply with the word ok."}]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Picking a model, with its price
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;models.list()&lt;/code&gt; returns every model with its per-token price, so you can choose from code instead of a pricing page. This prints the text models and what they cost per million tokens:&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="c1"&gt;# OPENAI_BASE_URL and OPENAI_API_KEY set as above
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&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;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list&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;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_modalities&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;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pricing&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&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="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1e6&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in / $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1e6&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; out per 1M tokens&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;p&gt;On 2026-10-21 that printed 160 text models. A few of them:&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 per 1M tokens&lt;/th&gt;
&lt;th&gt;Output per 1M tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;openai/gpt-oss-120b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.037&lt;/td&gt;
&lt;td&gt;$0.17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meta-llama/Llama-3.3-70B-Instruct-Turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.10&lt;/td&gt;
&lt;td&gt;$0.32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deepseek-ai/DeepSeek-V3.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.26&lt;/td&gt;
&lt;td&gt;$0.38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Qwen/Qwen3-Coder-480B-A35B-Instruct-Turbo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.30&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;moonshotai/Kimi-K2.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.49&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Prices change, so read them from the endpoint rather than from this post. The rest of the catalog is image, video and speech models (FLUX, Whisper and others), on the same key.&lt;/p&gt;

&lt;h2&gt;
  
  
  What carries over
&lt;/h2&gt;

&lt;p&gt;I ran each of these against &lt;code&gt;deepseek-ai/DeepSeek-V3.2&lt;/code&gt; with the stock Python SDK, no changes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Streaming&lt;/strong&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="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;deepseek-ai/DeepSeek-V3.2&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;Count to five.&lt;/span&gt;&lt;span class="sh"&gt;"&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="ow"&gt;and&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="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;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="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;&lt;strong&gt;Tool calls.&lt;/strong&gt; With a &lt;code&gt;get_weather(city)&lt;/code&gt; tool and the prompt "What's the weather in Paris?", the response came back with &lt;code&gt;finish_reason="tool_calls"&lt;/code&gt; and arguments &lt;code&gt;{"city":"Paris"}&lt;/code&gt;, the same shape your existing tool loop already handles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON mode.&lt;/strong&gt; &lt;code&gt;response_format={"type": "json_object"}&lt;/code&gt; returned a parseable object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reasoning models.&lt;/strong&gt; Models that think out loud, such as &lt;code&gt;openai/gpt-oss-120b&lt;/code&gt;, put the reasoning in a separate &lt;code&gt;reasoning_content&lt;/code&gt; field next to &lt;code&gt;content&lt;/code&gt;, so your app still reads &lt;code&gt;content&lt;/code&gt; as the answer.&lt;/p&gt;

&lt;p&gt;Support for tools and JSON mode depends on the model, as it does anywhere, so test the one you pick with your own prompts before you switch production traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doesn't carry over
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model names.&lt;/strong&gt; &lt;code&gt;gpt-4o&lt;/code&gt; doesn't exist here; an unknown name returns a 404 with &lt;code&gt;code: "model_not_found"&lt;/code&gt;. Keep the model name in config so the switch is one value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings.&lt;/strong&gt; There are no embedding models in the catalog right now, so leave your embedding calls where they are.&lt;/li&gt;
&lt;li&gt;This post only covers chat completions. If you rely on other OpenAI endpoints, check them first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A pattern I like: one env var per environment
&lt;/h2&gt;

&lt;p&gt;Because only the base URL, key and model change, I keep all three in env vars and switch per environment without code changes:&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;OPENAI_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.runcrate.ai/v1
&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rc_live_...
&lt;span class="nv"&gt;LLM_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek-ai/DeepSeek-V3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That also makes A/B tests between models a config change, which is how most people end up comparing cost and quality on their own data instead of on a leaderboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Model catalog and prices: &lt;a href="https://www.runcrate.ai/inference?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=tutorials" rel="noopener noreferrer"&gt;runcrate.ai/inference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chat completions reference: &lt;a href="https://www.runcrate.ai/docs/models/chat-completions?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=tutorials" rel="noopener noreferrer"&gt;runcrate.ai/docs/models/chat-completions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Getting an API key: &lt;a href="https://www.runcrate.ai/docs/models/authentication?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=tutorials" rel="noopener noreferrer"&gt;runcrate.ai/docs/models/authentication&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If something in your app breaks after the switch, tell me what it was. Reply here or write to &lt;a href="mailto:hello@runcrate.ai"&gt;hello@runcrate.ai&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written with AI assistance. Every command and output in this post was run against the live API on 2026-10-21.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>openai</category>
      <category>llm</category>
      <category>python</category>
    </item>
    <item>
      <title>Give your coding agent a GPU, and a budget: the Runcrate MCP server in Claude Code, Codex and Cursor</title>
      <dc:creator>Runcrate</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:38:02 +0000</pubDate>
      <link>https://dev.to/runcrate/give-your-coding-agent-a-gpu-and-a-budget-the-runcrate-mcp-server-in-claude-code-codex-and-cursor-8ic</link>
      <guid>https://dev.to/runcrate/give-your-coding-agent-a-gpu-and-a-budget-the-runcrate-mcp-server-in-claude-code-codex-and-cursor-8ic</guid>
      <description>&lt;p&gt;Coding agents are good at writing a training script. They are bad at the part that comes next: finding a GPU, getting a shell on it, running the script, and remembering to shut the machine down. That last step is where the surprise invoices come from.&lt;/p&gt;

&lt;p&gt;This post shows how to hand that whole loop to the agent you already use (Claude Code, Codex, Cursor or any MCP client) with the Runcrate MCP server, and how to keep it on a leash while it spends money.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agent gets
&lt;/h2&gt;

&lt;p&gt;The server lives at &lt;code&gt;https://mcp.runcrate.ai/mcp&lt;/code&gt; (Streamable HTTP). It exposes tools for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPU instances&lt;/strong&gt;: list GPU types with live prices, create an instance, check its status, run shell commands on it over SSH, upload and download files, delete it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs&lt;/strong&gt;: run one command on a fresh GPU machine that stops itself, and its billing, when the command exits. The agent follows the logs and reads the exit code and cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedules&lt;/strong&gt;: start an instance or a job later, once or on a cron.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage volumes&lt;/strong&gt;, SSH keys, firewall rules and HTTPS links for a port on an instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Billing&lt;/strong&gt;: balance, usage, and the monthly budget of the environment it works in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sign-in is OAuth in your browser. There is no API key to paste into a config file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http &lt;span class="nt"&gt;--scope&lt;/span&gt; user runcrate https://mcp.runcrate.ai/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;/mcp&lt;/code&gt; inside Claude Code and pick &lt;code&gt;runcrate&lt;/code&gt;. Your browser opens to sign in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex mcp add runcrate &lt;span class="nt"&gt;--url&lt;/span&gt; https://mcp.runcrate.ai/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt;: &lt;a href="https://cursor.com/en/install-mcp?name=runcrate&amp;amp;config=eyJ1cmwiOiJodHRwczovL21jcC5ydW5jcmF0ZS5haS9tY3AifQ==" rel="noopener noreferrer"&gt;one-click install&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VS Code&lt;/strong&gt;: &lt;a href="https://vscode.dev/redirect/mcp/install?name=runcrate&amp;amp;config=%7B%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.runcrate.ai%2Fmcp%22%7D" rel="noopener noreferrer"&gt;one-click install&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Any other MCP client&lt;/strong&gt;: follow the &lt;a href="https://www.runcrate.ai/docs/mcp/setup?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=mcp" rel="noopener noreferrer"&gt;setup page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The leash: one environment, one budget
&lt;/h2&gt;

&lt;p&gt;When you sign in, you pick a workspace and one &lt;strong&gt;environment&lt;/strong&gt;. The agent can act only inside that environment, and the environment's &lt;strong&gt;monthly budget&lt;/strong&gt; caps what it can spend. No MCP tool can create or switch environments or change a budget, so the agent cannot raise its own ceiling. Budgets are set in the dashboard by a workspace owner or admin.&lt;/p&gt;

&lt;p&gt;Two more guardrails sit on every instance the agent creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;max_runtime_minutes&lt;/code&gt; (5 minutes to 7 days): the instance is terminated that long after it starts running, with an alert 10 minutes before.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;idle_shutdown_minutes&lt;/code&gt; (5 minutes to 24 hours): the instance is terminated once GPU utilization stays under 5% with nobody connected for that long.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need to know the parameter names. Say it in the prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Launch an H100, stop it after 4 hours or after 30 idle minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Three prompts that work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Check the hardware before you commit&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What GPUs with at least 48 GB of VRAM are available right now, and what do they cost per hour?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent calls &lt;code&gt;list_gpu_types&lt;/code&gt; and answers from live prices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run a training script and come back with the number&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run python train.py on an A4000 for at most 2 hours with my volume training-data, then tell me the final loss.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What happens under the hood:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;list_volumes&lt;/code&gt; finds the id of &lt;code&gt;training-data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_job&lt;/code&gt; starts the command with &lt;code&gt;gpu: "A4000"&lt;/code&gt;, &lt;code&gt;max_runtime_minutes: 120&lt;/code&gt; and the volume attached at &lt;code&gt;/workspace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_job_logs&lt;/code&gt; follows the output until the job is done, and the agent reads the loss from it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_job&lt;/code&gt; returns the final status, exit code and cost.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The machine stops when the script exits, so there is nothing left running to forget about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep a box for interactive work&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Launch an RTX 4090, install vllm, serve Qwen/Qwen2.5-7B-Instruct on port 8000, and give me an HTTPS link only my workspace can open. Stop it after 3 hours.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here the agent uses &lt;code&gt;create_instance&lt;/code&gt; with a max runtime, &lt;code&gt;ssh_execute&lt;/code&gt; to install and start the server, and &lt;code&gt;create_instance_link&lt;/code&gt; to expose port 8000 at an &lt;code&gt;https://8000-&amp;lt;instance&amp;gt;.runcrate.app&lt;/code&gt; address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prices, so you know what you are asking for
&lt;/h2&gt;

&lt;p&gt;From the live pricing endpoint on 2026-10-20: RTX 4090 from $0.52/hr, A100 80GB from $1.76/hr, H100 from $3.55/hr, H200 from $4.24/hr. Booting is never billed, and the balance is prepaid, so there is no monthly fee. The current numbers are at &lt;a href="https://www.runcrate.ai/pricing?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=mcp" rel="noopener noreferrer"&gt;runcrate.ai/pricing&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not every task needs a GPU of its own
&lt;/h2&gt;

&lt;p&gt;If the agent only needs a model, not a machine, the same account has 200+ open models behind an OpenAI-compatible API. The client you already use works:&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.runcrate.ai/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;rc_live_...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&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;deepseek-ai/DeepSeek-V3&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;Summarize this stack trace: ...&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;r&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;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MCP setup for every client: &lt;a href="https://www.runcrate.ai/docs/mcp/setup?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=mcp" rel="noopener noreferrer"&gt;runcrate.ai/docs/mcp/setup&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full tool reference: &lt;a href="https://www.runcrate.ai/docs/mcp/tools?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=mcp" rel="noopener noreferrer"&gt;runcrate.ai/docs/mcp/tools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source and client configs: &lt;a href="https://github.com/aeonmindai/runcrate-mcp" rel="noopener noreferrer"&gt;github.com/aeonmindai/runcrate-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you wire this into an agent workflow, I would like to hear what broke first. Reply here or write to &lt;a href="mailto:hello@runcrate.ai"&gt;hello@runcrate.ai&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>machinelearning</category>
      <category>claude</category>
    </item>
  </channel>
</rss>
