cd /news/developer-tools/i-added-an-ai-helper-to-my-json-mock… · home topics developer-tools article
[ARTICLE · art-68866] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

I added an AI helper to my JSON mock-API tool — the hybrid design, and a Workers AI gotcha

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.

read4 min views1 publishedJul 22, 2026

I run TempTools — 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.

I 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.

Three buttons on the Temp API editor:

Here's the thing I didn't want: an AI silently rewriting my JSON while pretending to "format" it. If you paste {"id": 42}

and the tool hands back {"id": 43}

, that's not a fix — that's a bug you'll chase for an hour.

So repair and formatting are 100% deterministic. No AI. I use jsonrepair:

export function formatOrRepair(input: string) {
  try {
    return { ok: true, formatted: JSON.stringify(JSON.parse(input), null, 2), repaired: false };
  } catch {
    /* not valid — try to repair */
  }
  try {
    const repaired = jsonrepair(input);
    return { ok: true, formatted: JSON.stringify(JSON.parse(repaired), null, 2), repaired: true };
  } catch {
    return { ok: false };
  }
}

The AI is only used for things where being "approximately right" is fine and there's no source of truth to corrupt:

That 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.

The generation runs on Workers AI with an ai

binding — no external API keys, it just runs on the edge:

export const AI_MODEL = "@cf/qwen/qwen2.5-coder-32b-instruct";

async function runText(ai, messages, maxTokens) {
  const out = await ai.run(AI_MODEL, { messages, max_tokens: maxTokens, temperature: 0.2 });
  return out.response.trim(); // ← this line is a trap. more below.
}

generateSchema

and generateSample

are just runText

with a system prompt that says "output ONLY raw JSON, no markdown fences," and then I strip any stray fences/prose defensively before parsing.

response

isn't always a string Here's the bug that had me confused for a while. In production:

Same model. Same runText

. Same binding. So why did one of three AI calls work and two fail?

I temporarily surfaced the real error in the response and got this:

((intermediate value).response ?? "").trim is not a function

out.response

wasn't a string — so .trim()

didn't exist on it.

The pattern clicked once I saw which calls failed. The explanation prompt returns prose, so response

is a string. The schema and sample prompts return JSON — and when the model's output is JSON, Workers AI can hand you response

as an already-parsed object, not a string. Calling .trim()

on an object throws.

The fix is boring but worth knowing: don't assume response

is a string.

async function runText(ai, messages, maxTokens) {
  const out = await ai.run(AI_MODEL, { messages, max_tokens: maxTokens, temperature: 0.2 });
  const r = (out as { response?: unknown }).response;
  const text = typeof r === "string" ? r : r == null ? "" : JSON.stringify(r);
  return text.trim();
}

If response

is a string, use it. If it's an object (parsed JSON), JSON.stringify

it back — which is exactly what I want to hand to the schema/sample path anyway. null

/undefined

becomes an empty string instead of crashing.

Two debugging lessons I keep re-learning:

catch → 502

hides 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.

On 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.

It'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.

If you're building on Workers AI, keep that response

-type gotcha in your back pocket. And if you find a rough edge in Temp API, I'd genuinely love to hear it. 🛠️

── more in #developer-tools 4 stories · sorted by recency
── more on @temptools 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-added-an-ai-helper…] indexed:0 read:4min 2026-07-22 ·