将生产环境 AI 智能体迁移至 GPT-5.6:速度提升 2.2 倍,成本降低 27%
Migrating a production AI agent to GPT-5.6: 2.2x faster, 27% cheaper

原始链接: https://ploy.ai/blog/migrating-a-production-ai-agent-to-gpt-5-6

Ploy 已正式将其默认代理模型从 Claude Opus 4.8 切换为 OpenAI 的新款 GPT-5.6 Sol。经过严格测试,Ploy 发现 GPT-5.6 表现更为出色,在保持更高视觉质量评分的同时,构建时间缩短了 50% 以上,成本降低了 27%。 此次迁移对 Ploy 的基础设施进行了重大技术调整: * **评估严谨性:** 团队发现其评估工具原本是针对 Claude 的行为进行“调优”的。在纠正了工具调用参数不一致和阈值设定等偏差后,他们准确验证了 GPT-5.6 的效率。 * **模式转换:** 为防止 GPT-5.6 为可选参数虚构数值(这曾导致读取空文件),Ploy 实施了一个模式封装器,将可选字段映射为 `null`,确保模型能在不干扰现有工具的情况下清晰表达意图。 * **提示词缓存:** Ploy 重新构建了缓存策略,以适配 OpenAI 的工作区作用域密钥系统。通过优化提示词的分层和缓存方式,他们将首次调用的缓存命中率提升至近 84%,抵消了初始成本差异。 尽管存在这些复杂性,GPT-5.6 生成精简且高质量代码的能力,使其成为 Ploy 自动化营销网站构建器的新标准。用户可前往 [ploy.ai](http://ploy.ai) 体验提升后的速度。

这篇文章详细介绍了 Ploy.ai 公司成功将其生产环境中的 AI 智能体迁移至“GPT-5.6”模型的过程。该公司利用 AI 自动构建和编辑营销网站,据报告,新模型实现了 2.2 倍的速度提升,并将成本降低了 27%。 Ploy 对其智能体保持着严格的测试标准,这些智能体负责处理代码库导航、组件编写和图像生成等复杂任务。虽然他们之前的默认模型 Opus 在过去四个月里一直是行业标杆,但此次升级展示了显著的性能提升。 在讨论区中,读者称赞了这篇文章在 LLM(大语言模型)流水线设计方面提供的实用见解。另一些人指出,尽管 Opus 此前在网站创建方面占据领先地位,但像“Fable”这样的新模型正在成为幻灯片生成等专业任务的潜在竞争对手。
相关文章

原文

Colorful Ploy inflatable forms connected by a translucent tube, representing a production AI agent migrating between model systems

As of today, Ploy’s agent runs on GPT-5.6 Sol, the flagship tier of the model family OpenAI released this morning. For months, we couldn’t find a model that challenges Claude Opus given our incredibly high bar for quality. That changed with GPT 5.6 Sol. After running it head-to-head against Claude Opus, we’ve made GPT 5.6 Sol the default model powering every Ploy workspace.

That’s a bigger switch than it sounds. Ploy’s agent builds and edits real marketing websites. It plans a page, reads the codebase, writes components, generates imagery, screenshots its own work, and decides when it’s done. That job description sets a very high bar for a model, and we test every frontier release against it. For the four months Opus held the default slot (first Opus 4.7, then 4.8), nothing we tested beat it. GPT-5.6 is the first model that did.

Not that the first eval run was perfect. It had real failure modes, which we’ll show you. But it did extremely well, and the promise was immediate and specific: builds finishing in less than half the wall-clock time, at 27% lower cost, scoring at or above our incumbent on completed work. Numbers like that buy a model a real migration effort.

Despite using Vercel’s AI SDK, a universal LLM SDK, switching from Claude Opus 4.8 to GPT 5.6 Sol required discovering, one eval failure at a time, that the things we think of as “the model” are provider-specific behaviors our whole stack has quietly specialized around: how it fills in tool arguments, how its prompt cache works, how it replays its own reasoning between turns.

Here’s what it took: fix the eval harness, then the tool schemas, then caching, then reasoning replay.

Step 0: Fix your harness before you trust a single number

Our eval suite runs the real agent against real fixture workspaces. Hundreds of cases, from “build a homepage from scratch” to “is this clone request safe to execute.” Build cases are scored by a visual judge running binary checks against a reference design, ten yes/no questions like “the hero is a full-bleed photographic scene” or “primary CTAs are rounded rectangles, not pills”, plus content checks, tool-trajectory checks, and file assertions. Every failed case gets triaged against its full trace: the actual tool calls and model text, not just the score.

Running that suite across two model families surprised us more than any individual result:

Your harness is tuned to your incumbent model, and you don’t know it. Our tool-call budgets were sized for Opus’s sequential style; GPT-5.6 fans out parallel calls and blew through them on cases it was solving correctly. Our eval executor didn’t support batched file reads, which Opus rarely used and GPT-5.6 uses constantly. Roughly a third of the raw failures in the first cross-model run traced back to harness assumptions, not model behavior, and they were not evenly distributed between the models. If you’re evaluating a challenger model against an incumbent, triage the traces before you trust the pass rate. Otherwise you’re grading the new model on how well it imitates the old one.

Make sure you’re grading models fairly in evals. A dataset that omitted its minScore threshold silently inherited a default of 1.0, so GPT-5.6 “failed” a hero it scored 0.98 on, and Opus “failed” a case while passing every individual check. Two defensible design directions; one invisible threshold.

Build-colorful-hero comparison: Opus's gradient hero passed at 1.0; GPT-5.6's color-block study scored 0.98 and failed only an implicit default threshold

With the harness cleaned up, here’s a sample from our redesign suite, where the agent rebuilds a brand’s homepage against a reference design:

Mean per completed buildClaude Opus 4.8 (n=11)GPT-5.6 (n=10)
Cost$3.06$2.22
Wall-clock time8m 00s3m 42s
Input tokens2.60M1.70M
Output tokens33.0K17.1K
Visual score0.9360.970

This is the shape of the promise: 2.2× faster to a finished page, 27% cheaper, and about half the output tokens. GPT-5.6 writes lean code. On one matched pair, Opus produced a 17,957-character globals.css with 174 CSS variables (full color ramps, mostly unused) where GPT-5.6 wrote 2,508 characters and 45 variables for a comparable (and sometimes better) rendered page.

Design: sharp, clean, but a little bit uniform

Our overall read on GPT-5.6’s design work: it is very good at clean, modern, tightly-gridded layouts, but it tends to converge towards that look unless you steer it well. With our older harness designed for Opus 4.8, GPT 5.6 Sol tends to ignore existing design systems and instead produces sharp, restrained, and visibly generic output.

Opus on the left reproduced the Clay brand system; GPT-5.6 on the right shipped a clean but generic page

The details of how we fixed this are worth a separate blog post of its own. With the expertise of our design and engineering teams, we are able to steer models to achieve world-class brand adherence that you can’t get out of the box.

Here’s the one that was silently corrupting results before we caught it.

Our agent’s code tool has 25 top-level parameters, one required (action) and the rest optional. Claude sends the two or three it’s using and omits the rest. GPT-5.6 sends all 25, every time, inventing plausible values for the ones it doesn’t need: offset: 0, timeout: 120000, siteId: "00000000-0000-0000-0000-000000000000".

Three days of production traces, code(read) calls carrying every property:

ModelCallsCarrying all 25 properties
gpt-5.66,6356,635 (100%)
claude-opus-4.82,8984 (0.1%)
claude-sonnet-51,9330

The problem isn’t verbosity. It’s that an invented value is indistinguishable from an intended one. offset: 0 looks like a real argument. Our file-read implementation treated it as one, and 52% to 64% of GPT-5.6’s file reads were coming back empty because of it. The tool returned success: true both ways, so the model had no way to know it was reading blank files. It just did the work worse, with more calls.

Prompting doesn’t fix this. A tool-description directive to “omit unused parameters”: still 25/25. Per-property “OPTIONAL, omit if unused” hints: still 25/25. OpenAI’s strict mode: identical behavior (we measured), and adopting it would have forced us to strip pattern, format, and array-bound validation from every schema. This is baked into how the model emits function calls. You don’t instruct it away; you design around it.

The fix that worked is a schema transform at the provider boundary. For OpenAI-family models only, we rewrite every optional property to be required but nullable, using anyOf: [T, null], which gives the model an explicit way to say “not using this.” Then, at the single seam every tool invocation passes through, we strip the nulls back out before validation, so no tool implementation changes at all. Round trip: the model sees a schema where honesty is expressible; the tools see the same inputs they always did.

// Before: 25 keys, every one carrying an invented value
{ "action": "read", "file_paths": [...], "offset": 0, "timeout": 120000, ... }

// After: 25 keys, 4 real values, 21 explicit nulls (stripped before the tool runs)
{ "action": "read", "file_paths": [...], "offset": null, "timeout": null, ... }

Results: empty file reads went from 52% to 0%, and the agent needed roughly 30% fewer tool calls for the same work, because it was no longer re-reading files that came back blank.

Step 2: Rebuild prompt caching

This was the most instructive engineering difference, because on the surface both providers offer “prompt caching” and the words hide two entirely different designs. If you migrate one thing carefully, make it this: before we did, GPT-5.6 looked about 50% more expensive than Opus. It wasn’t the model’s pricing; it was our cache configuration.

Our agent’s prompt opens with a static prefix of roughly 29K tokens (tool schemas plus the core system prompt) that’s identical for every conversation. On Claude, we mark cache breakpoints with cache_control and that prefix caches across the whole organization: any conversation, any workspace, one shared entry, no throughput budget to think about. Cache hit rates run 92% to 96% and caching fades into the background.

GPT-5.6 changed OpenAI’s caching model out from under us. Earlier GPT models cached implicitly on partial prefix matches, which gave decent hit rates for free. GPT-5.6 dropped partial-prefix matching: implicit caching now only creates whole-prompt entries keyed on the latest message. A new conversation sharing our 29K static prefix cached 0% of it. Every conversation re-billed the full prefix at the uncached rate, and on GPT-5.6 every uncached prompt also pays a 1.25× cache-write surcharge, whether or not you use caching.

The intended mechanism is explicit: prompt_cache_breakpoint markers plus a mandatory prompt_cache_key. And the key is where the design really diverges, because it’s part of cache identity. Identical prompt, different key: zero cache hits. Each key maps to a cache node that sustains roughly 15 requests per minute before OpenAI fans traffic to other nodes with independent, cold caches.

That turns “enable caching” into an actual design decision: what entity do you scope the key to?

  • Per-conversation key means a new conversation never hits the shared prefix. First-call hit rate: 0%. (We measured this mistake. It’s expensive.)
  • One global key means every request hashes to one cache node, and production traffic obliterates the 15 rpm budget; requests spill to cold nodes and you’re back to misses.
  • Per-workspace key is the sweet spot. All conversations in a customer workspace share entries; per-key traffic stays low.

We ship the workspace-scoped key and split the system prompt into breakpointed layers, mirroring the structure we already used for Anthropic:

request ──► hash(prompt head + prompt_cache_key) ──► cache node (~15 req/min per key)

   ┌──────────────────────────────────────────────────────┴───────────────┐
   │  entries on the node, all namespaced by key ws:{workspaceId}         │
   │                                                                      │
   │   [ tools + static prefix ]······················ A  every session   │
   │   [ tools + static prefix + workspace context ]·· B  same context    │
   │   [ ····················· + turn 1 + … + latest ] C  this session    │
   └──────────────────────────────────────────────────────────────────────┘

Entry A is what makes a session’s first call cheap. Entry B self-heals: when workspace memory changes, the request misses B but still hits A, then writes a fresh B. One context-sized write instead of a full 29K re-bill. Entry C is OpenAI’s implicit whole-prompt chain, which works fine within a session because our prompts are strictly append-only.

One consequence has no workaround: cross-workspace sharing of the static prefix is structurally impossible on OpenAI. Anthropic can share it because its cache is org-scoped without key partitioning. On GPT-5.6, every workspace pays one 29K cold write per idle window, about $0.18. A real cost, but bounded and predictable.

Results after the change: first-call cache hits went from roughly 0% to 83.7%, total uncached input tokens dropped 28%, and GPT-5.6’s per-suite cost landed below Opus’s. Every dollar of the gap we’d been staring at was cache misconfiguration, not model pricing. If you’re cost-comparing models and one of them has a cold cache, you are comparing your config, not the models.

Step 3: Make reasoning replay self-contained

Shorter, but it broke real conversations. GPT-5.6’s Responses API replays prior-turn reasoning as server-side item references by default; ours started intermittently failing mid-conversation with Item 'rs_...' not found. The fix is store: false, which makes the SDK request encrypted reasoning content and replay self-contained blobs instead of pointers to server state. A corollary that cost us a debugging afternoon: with server-side reasoning state in the loop, the effective prompt can change upstream of you even when the bytes you send are append-only.

GPT 5.6 Sol is ready to Ploy

Try it yourself. GPT-5.6 launched today, and it’s already live on Ploy. You can try it for free right now: give it a website to build and see what a sub-four-minute build looks like. Start free at ploy.ai.


Ploy is marketing run on autopilot: an AI layer that plans, builds, publishes, and optimizes your website and campaigns end-to-end. If debugging cache-node fan-out at 2am sounds like fun, we’re hiring.

联系我们 contact @ memedata.com