{"slug": "i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai", "title": "I added an AI helper to my JSON mock-API tool — the hybrid design, and a Workers AI gotcha", "summary": "TempTools, a suite of free web tools that expire and delete themselves, added an AI helper to its Temp API tool that generates JSON schemas, samples, and explanations. The AI is never allowed to touch correctness—repair and formatting are handled deterministically by the jsonrepair library. A Cloudflare Workers AI gotcha caused two of three AI features to fail because the model returned parsed JSON objects instead of strings, breaking the `.trim()` call.", "body_md": "I run [TempTools](https://temptools.webcli.jp) — a small suite of free, no-signup web tools that expire and delete themselves. The one I use most is **Temp API**: paste JSON or CSV, get a live mock endpoint in seconds.\n\nI just added an **AI helper** to it, and the design turned out more interesting than \"call an LLM.\" The rule I set for myself was: **AI is never allowed to touch correctness.** Here's how that shook out — plus a Cloudflare Workers AI gotcha that broke two of the three features while the third worked fine.\n\nThree buttons on the Temp API editor:\n\nHere's the thing I didn't want: an AI silently *rewriting* my JSON while pretending to \"format\" it. If you paste `{\"id\": 42}`\n\nand the tool hands back `{\"id\": 43}`\n\n, that's not a fix — that's a bug you'll chase for an hour.\n\nSo repair and formatting are **100% deterministic**. No AI. I use [ jsonrepair](https://www.npmjs.com/package/jsonrepair):\n\n```\nexport function formatOrRepair(input: string) {\n  try {\n    return { ok: true, formatted: JSON.stringify(JSON.parse(input), null, 2), repaired: false };\n  } catch {\n    /* not valid — try to repair */\n  }\n  try {\n    const repaired = jsonrepair(input);\n    return { ok: true, formatted: JSON.stringify(JSON.parse(repaired), null, 2), repaired: true };\n  } catch {\n    return { ok: false };\n  }\n}\n```\n\nThe AI is only used for things where being \"approximately right\" is fine and there's no source of truth to corrupt:\n\nThat split matters for the copy too. It would be tempting to market this as \"AI fixes your JSON!\" — but that's not true, and someone will call it out. The UI says the repair runs locally and reserves \"AI\" for the schema/sample/explanation. Honest *and* it dodges a whole class of complaints.\n\nThe generation runs on **Workers AI** with an `ai`\n\nbinding — no external API keys, it just runs on the edge:\n\n``` js\nexport const AI_MODEL = \"@cf/qwen/qwen2.5-coder-32b-instruct\";\n\nasync function runText(ai, messages, maxTokens) {\n  const out = await ai.run(AI_MODEL, { messages, max_tokens: maxTokens, temperature: 0.2 });\n  return out.response.trim(); // ← this line is a trap. more below.\n}\n```\n\n`generateSchema`\n\nand `generateSample`\n\nare just `runText`\n\nwith a system prompt that says \"output ONLY raw JSON, no markdown fences,\" and then I strip any stray fences/prose defensively before parsing.\n\n`response`\n\nisn't always a string\nHere's the bug that had me confused for a while. In production:\n\nSame model. Same `runText`\n\n. Same binding. So why did one of three AI calls work and two fail?\n\nI temporarily surfaced the real error in the response and got this:\n\n```\n((intermediate value).response ?? \"\").trim is not a function\n```\n\n`out.response`\n\nwasn't a string — so `.trim()`\n\ndidn't exist on it.\n\nThe pattern clicked once I saw *which* calls failed. The explanation prompt returns **prose**, so `response`\n\nis a string. The schema and sample prompts return **JSON** — and when the model's output is JSON, Workers AI can hand you `response`\n\nas an already-parsed **object**, not a string. Calling `.trim()`\n\non an object throws.\n\nThe fix is boring but worth knowing: don't assume `response`\n\nis a string.\n\n``` js\nasync function runText(ai, messages, maxTokens) {\n  const out = await ai.run(AI_MODEL, { messages, max_tokens: maxTokens, temperature: 0.2 });\n  const r = (out as { response?: unknown }).response;\n  const text = typeof r === \"string\" ? r : r == null ? \"\" : JSON.stringify(r);\n  return text.trim();\n}\n```\n\nIf `response`\n\nis a string, use it. If it's an object (parsed JSON), `JSON.stringify`\n\nit back — which is exactly what I want to hand to the schema/sample path anyway. `null`\n\n/`undefined`\n\nbecomes an empty string instead of crashing.\n\nTwo debugging lessons I keep re-learning:\n\n`catch → 502`\n\nhides the answer.Because repair/formatting never calls the model, the common case (paste valid-ish JSON, format it) costs **zero** AI. The model only runs when you ask for an explanation, schema, or sample.\n\nOn top of that, AI calls are rate-limited per IP with a tiny rolling log table (same trick I use for uploads), and the input is size-capped before it ever reaches the model. It all stays comfortably inside the Cloudflare free tier.\n\nIt's live at ** temptools.webcli.jp/tools/temp-api** — paste some rough JSON and hit the AI buttons. No signup, and the endpoint you create expires on its own.\n\nIf you're building on Workers AI, keep that `response`\n\n-type gotcha in your back pocket. And if you find a rough edge in Temp API, I'd genuinely love to hear it. 🛠️", "url": "https://wpnews.pro/news/i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai", "canonical_source": "https://dev.to/solca/i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai-gotcha-pb9", "published_at": "2026-07-22 16:28:27+00:00", "updated_at": "2026-07-22 16:32:06.781552+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-infrastructure"], "entities": ["TempTools", "Cloudflare Workers AI", "Qwen2.5-Coder-32B-Instruct"], "alternates": {"html": "https://wpnews.pro/news/i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai", "markdown": "https://wpnews.pro/news/i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai.md", "text": "https://wpnews.pro/news/i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai.txt", "jsonld": "https://wpnews.pro/news/i-added-an-ai-helper-to-my-json-mock-api-tool-the-hybrid-design-and-a-workers-ai.jsonld"}}