{"slug": "running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode", "title": "Running Qwen3 Coder 30B as a cheap subagent for Claude Code, Codex and opencode", "summary": "A developer demonstrated running Qwen3 Coder 30B, a 30B mixture-of-experts coding model with tool calling, as a low-cost subagent behind Claude Code, Codex CLI and opencode via an OpenAI-compatible endpoint on Synap. In a Codex test, fixing a one-character bug in is_even() consumed 49,245 input tokens and 722 output tokens, costing roughly $0.0035 per task at $0.0675 per 1M input and $0.27 per 1M output, with the developer noting that agent system prompts and tool definitions dominate token use. The writeup also documents a Claude Code run that fixed a bug in six turns and 11.3 seconds, and a free tier of 100,000 tokens and 50 requests per day.", "body_md": "Big frontier models are great at planning a change across a codebase. They are expensive overkill for \"add type hints to this file\", \"fix the off-by-one in `is_even`\" or \"write two doctests\". This post shows how to hand that second kind of work to **Qwen3 Coder 30B** (a 30B mixture-of-experts coding model with tool calling) through an OpenAI-compatible endpoint. It covers three agents, Claude Code, Codex CLI and opencode, plus a 40-line Python \"subagent\" you can call from any of them.\n\nEverything below was run on 2026-11-11 against `https://synap402.com/v1` ([Synap](https://synap402.com), the API we build). The token counts and prices are copied from those runs.\n\nFrom `curl -s https://synap402.com/v1/models` today:\n\n| model | input / 1M tokens | output / 1M tokens | batch (24h) in / out | context | \n|---|---|---|---|---|\n| `qwen3-coder-30b` | $0.0675 | $0.27 | $0.03375 / $0.135 | 98,304 | \n\nIt supports `tools`, `tool_choice` (`auto`, `required`), `response_format` with `json_schema`, and streaming.\n\nThere is also a free tier on this model: 100,000 tokens and 50 requests a day per account (Google sign-in, no card). It allows 10 requests a minute per key and 4,096 output tokens per answer. As you'll see below, one coding-agent task can use half of that, so it's for trying things out, not daily work.\n\nClaude Code speaks Anthropic's Messages API, and the endpoint serves `/v1/messages` too. Five environment variables:\n\n```\nexport ANTHROPIC_BASE_URL=https://synap402.com      # no /v1, Claude Code appends /v1/messages\nexport ANTHROPIC_AUTH_TOKEN=$SYNAP_API_KEY\nexport ANTHROPIC_MODEL=qwen3-coder-30b\nexport ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3-coder-30b  # its own background tasks\nexport CLAUDE_CODE_MAX_CONTEXT_TOKENS=98304          # otherwise it warns about an unknown model\n```\n\nI gave it a file with a deliberate bug:\n\n``` python\n# mathx.py\ndef add(a, b):\n    return a - b\nclaude -p \"mathx.py has a bug in add(). Fix it, then reply with one line saying what you changed.\" \\\n  --allowedTools \"Read,Edit\" --output-format json\n```\n\nResult on Claude Code 2.1.322: 6 turns, 11.3 seconds, `\"is_error\": false`, and the file now says `return a + b`. The model read the file, called Claude Code's own Edit tool and reported back. Claude Code also prints a `costUSD` estimate for a model it doesn't know. Ignore it and use the usage the API reports instead.\n\nCodex talks to the Responses API (`/v1/responses`). Add one provider block to `~/.codex/config.toml`:\n\n```\nmodel_provider = \"synap\"\nmodel = \"qwen3-coder-30b\"\n\n[model_providers.synap]\nname = \"Synap\"\nbase_url = \"https://synap402.com/v1\"\nenv_key = \"SYNAP_API_KEY\"\nwire_api = \"responses\"\n```\n\nThen:\n\n``` python\nprintf 'def is_even(n):\\n    return n %% 2 == 1\\n' > evens.py\ncodex exec --json --skip-git-repo-check -s workspace-write \\\n  \"evens.py has a bug in is_even(). Fix it.\" </dev/null | grep turn.completed\n```\n\nOn codex-cli 0.166.0 that printed:\n\n```\n{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":49245,\"cached_input_tokens\":0,\"output_tokens\":722,\"reasoning_output_tokens\":0}}\n```\n\nand `evens.py` now returns `n % 2 == 0`. (Without `</dev/null`, `codex exec` sits waiting on stdin.)\n\nLook at that input number: **49,245 tokens to fix one character**. Almost all of it is Codex's system prompt and tool definitions, not your code. At $0.0675 per 1M input and $0.27 per 1M output:\n\n```\n49,245 × $0.0675 / 1M = $0.003324\n   722 × $0.27   / 1M = $0.000195\n                  total ≈ $0.0035 per task\n```\n\nSo 200 small tasks like this a day comes to about $0.70. The same overhead is why one Codex task uses half the free daily allowance. Agent prompts are large, so per-input-token price matters much more than it does in chat.\n\nopencode doesn't read `/v1/models` for a custom provider, so you list the model ids yourself. Put this in `opencode.json` in the project root. `{env:...}` keeps the key out of the file:\n\n```\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"provider\": {\n    \"synap\": {\n      \"npm\": \"@ai-sdk/openai-compatible\",\n      \"name\": \"Synap\",\n      \"options\": {\n        \"baseURL\": \"https://synap402.com/v1\",\n        \"apiKey\": \"{env:SYNAP_API_KEY}\"\n      },\n      \"models\": { \"qwen3-coder-30b\": { \"name\": \"Qwen3 Coder 30B\" } }\n    }\n  },\n  \"model\": \"synap/qwen3-coder-30b\"\n}\npython\nprintf 'def square(x):\\n    return x * 2\\n' > sq.py\nnpx -y opencode-ai@latest run \"sq.py: square() is wrong. Fix it.\" </dev/null\n```\n\nOn opencode 1.19.5 it changed the function to `x * x`, then ran its own check over eight inputs (` square(-3) = 9` …) before it answered. The first run is slow because opencode downloads the provider package then.\n\nRunning a whole session on a 30B model is fine for routine work. The more interesting setup is to keep your strong model as the planner and have it hand scoped edits to the small one. Every agent above can run a shell command, so the subagent can be a plain script:\n\n```\n# delegate.py: hand one scoped coding task to a small model, get JSON back, print the cost\nimport json, os, sys, urllib.request\nfrom openai import OpenAI\n\nBASE = \"https://synap402.com/v1\"\nMODEL = \"qwen3-coder-30b\"\nclient = OpenAI(base_url=BASE, api_key=os.environ[\"SYNAP_API_KEY\"])\n\ndef price(model_id):\n    \"\"\"Live USD per 1M tokens (input, output) from the public catalog.\"\"\"\n    with urllib.request.urlopen(f\"{BASE}/models\") as r:\n        models = json.load(r)[\"data\"]\n    p = next(m for m in models if m[\"id\"] == model_id)[\"pricing\"]\n    return p[\"prompt_per_million\"], p[\"completion_per_million\"]\n\ndef delegate(task, path):\n    source = open(path).read()\n    resp = client.chat.completions.create(\n        model=MODEL,\n        temperature=0.2,\n        messages=[\n            {\"role\": \"system\", \"content\": \"You are a careful Python engineer. Change only what the task asks.\"},\n            {\"role\": \"user\", \"content\": f\"Task: {task}\\n\\nFile {path}:\\n```\n\npython\\n{source}\\n\n\n```\"},\n        ],\n        response_format={\n            \"type\": \"json_schema\",\n            \"json_schema\": {\n                \"name\": \"edit\",\n                \"schema\": {\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"summary\": {\"type\": \"string\"},\n                        \"new_file\": {\"type\": \"string\"},\n                    },\n                    \"required\": [\"summary\", \"new_file\"],\n                },\n            },\n        },\n    )\n    out = json.loads(resp.choices[0].message.content)\n    p_in, p_out = price(MODEL)\n    u = resp.usage\n    cost = u.prompt_tokens * p_in / 1e6 + u.completion_tokens * p_out / 1e6\n    return out, u, cost\n\nif __name__ == \"__main__\":\n    out, u, cost = delegate(sys.argv[1], sys.argv[2])\n    with open(sys.argv[2], \"w\") as f:\n        f.write(out[\"new_file\"])\n    print(out[\"summary\"])\n    print(f\"{u.prompt_tokens} in / {u.completion_tokens} out -> ${cost:.6f}\")\n```\n\nInput file:\n\n``` python\nimport re\n\ndef slugify(title):\n    s = title.lower()\n    s = re.sub(r\"[^a-z0-9]+\", \"-\", s)\n    return s\npip install openai\npython delegate.py \"Strip leading/trailing dashes, add type hints and a docstring with two doctest examples.\" slugify.py\npython -m doctest -v slugify.py\n```\n\nOutput:\n\n```\nAdded type hints, docstring with doctest examples, and modified the function to strip leading/trailing dashes as requested.\n93 in / 202 out -> $0.000061\n...\n2 passed and 0 failed.\n```\n\nThe edit runs without an agent harness, so there's no 49k-token system prompt: 93 tokens in, 202 out, six thousandths of a cent. The structured output means the caller gets a file it can write, not prose it has to parse. And the doctests the model wrote pass.\n\nTo wire it in, put one line in `CLAUDE.md` / `AGENTS.md`: *\"For single-file mechanical edits (type hints, docstrings, renames, small bug fixes, test scaffolds), run `python delegate.py \"<task>\" <file>` and review the diff instead of editing yourself.\"*\n\nFrom these runs and day-to-day use:\n\nPaid keys start at $10, and top-ups don't expire. You can also pay in USDC through x402 with no account. Prompts and completions are not stored.\n\n*Synap by Linkrra: one OpenAI-compatible API for open models. [synap402.com](https://synap402.com)*", "url": "https://wpnews.pro/news/running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode", "canonical_source": "https://dev.to/synap402/running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode-2chh", "published_at": "2026-11-11 16:20:13+00:00", "updated_at": "2026-11-11 16:22:38.711311+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "large-language-models", "ai-infrastructure", "developer-tools"], "entities": ["Qwen3 Coder 30B", "Claude Code", "Codex CLI", "opencode", "Synap", "Anthropic", "OpenAI"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode", "markdown": "https://wpnews.pro/news/running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode.md", "text": "https://wpnews.pro/news/running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode.txt", "jsonld": "https://wpnews.pro/news/running-qwen3-coder-30b-as-a-cheap-subagent-for-claude-code-codex-and-opencode.jsonld"}}