cd /news/ai-agents/running-qwen3-coder-30b-as-a-cheap-s… · home › topics › ai-agents › article
[ARTICLE · art-167783] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Running Qwen3 Coder 30B as a cheap subagent for Claude Code, Codex and opencode

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.

read6 min views6 publishedNov 11, 2026

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.

Everything below was run on 2026-11-11 against https://synap402.com/v1 (Synap, the API we build). The token counts and prices are copied from those runs.

From curl -s https://synap402.com/v1/models today:

model input / 1M tokens output / 1M tokens batch (24h) in / out context
qwen3-coder-30b $0.0675 $0.27 $0.03375 / $0.135 98,304

It supports tools, tool_choice (auto, required), response_format with json_schema, and streaming.

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

Claude Code speaks Anthropic's Messages API, and the endpoint serves /v1/messages too. Five environment variables:

export ANTHROPIC_BASE_URL=https://synap402.com      # no /v1, Claude Code appends /v1/messages
export ANTHROPIC_AUTH_TOKEN=$SYNAP_API_KEY
export ANTHROPIC_MODEL=qwen3-coder-30b
export ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3-coder-30b  # its own background tasks
export CLAUDE_CODE_MAX_CONTEXT_TOKENS=98304          # otherwise it warns about an unknown model

I gave it a file with a deliberate bug:

def add(a, b):
    return a - b
claude -p "mathx.py has a bug in add(). Fix it, then reply with one line saying what you changed." \
  --allowedTools "Read,Edit" --output-format json

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

Codex talks to the Responses API (/v1/responses). Add one provider block to ~/.codex/config.toml:

model_provider = "synap"
model = "qwen3-coder-30b"

[model_providers.synap]
name = "Synap"
base_url = "https://synap402.com/v1"
env_key = "SYNAP_API_KEY"
wire_api = "responses"

Then:

printf 'def is_even(n):\n    return n %% 2 == 1\n' > evens.py
codex exec --json --skip-git-repo-check -s workspace-write \
  "evens.py has a bug in is_even(). Fix it." </dev/null | grep turn.completed

On codex-cli 0.166.0 that printed:

{"type":"turn.completed","usage":{"input_tokens":49245,"cached_input_tokens":0,"output_tokens":722,"reasoning_output_tokens":0}}

and evens.py now returns n % 2 == 0. (Without </dev/null, codex exec sits waiting on stdin.)

Look 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:

49,245 × $0.0675 / 1M = $0.003324
   722 × $0.27   / 1M = $0.000195
                  total ≈ $0.0035 per task

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

opencode 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:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "synap": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Synap",
      "options": {
        "baseURL": "https://synap402.com/v1",
        "apiKey": "{env:SYNAP_API_KEY}"
      },
      "models": { "qwen3-coder-30b": { "name": "Qwen3 Coder 30B" } }
    }
  },
  "model": "synap/qwen3-coder-30b"
}
python
printf 'def square(x):\n    return x * 2\n' > sq.py
npx -y opencode-ai@latest run "sq.py: square() is wrong. Fix it." </dev/null

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

Running 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:

import json, os, sys, urllib.request
from openai import OpenAI

BASE = "https://synap402.com/v1"
MODEL = "qwen3-coder-30b"
client = OpenAI(base_url=BASE, api_key=os.environ["SYNAP_API_KEY"])

def price(model_id):
    """Live USD per 1M tokens (input, output) from the public catalog."""
    with urllib.request.urlopen(f"{BASE}/models") as r:
        models = json.load(r)["data"]
    p = next(m for m in models if m["id"] == model_id)["pricing"]
    return p["prompt_per_million"], p["completion_per_million"]

def delegate(task, path):
    source = open(path).read()
    resp = client.chat.completions.create(
        model=MODEL,
        temperature=0.2,
        messages=[
            {"role": "system", "content": "You are a careful Python engineer. Change only what the task asks."},
            {"role": "user", "content": f"Task: {task}\n\nFile {path}:\n```

python\n{source}\n

```"},
        ],
        response_format={
            "type": "json_schema",
            "json_schema": {
                "name": "edit",
                "schema": {
                    "type": "object",
                    "properties": {
                        "summary": {"type": "string"},
                        "new_file": {"type": "string"},
                    },
                    "required": ["summary", "new_file"],
                },
            },
        },
    )
    out = json.loads(resp.choices[0].message.content)
    p_in, p_out = price(MODEL)
    u = resp.usage
    cost = u.prompt_tokens * p_in / 1e6 + u.completion_tokens * p_out / 1e6
    return out, u, cost

if __name__ == "__main__":
    out, u, cost = delegate(sys.argv[1], sys.argv[2])
    with open(sys.argv[2], "w") as f:
        f.write(out["new_file"])
    print(out["summary"])
    print(f"{u.prompt_tokens} in / {u.completion_tokens} out -> ${cost:.6f}")

Input file:

import re

def slugify(title):
    s = title.lower()
    s = re.sub(r"[^a-z0-9]+", "-", s)
    return s
pip install openai
python delegate.py "Strip leading/trailing dashes, add type hints and a docstring with two doctest examples." slugify.py
python -m doctest -v slugify.py

Output:

Added type hints, docstring with doctest examples, and modified the function to strip leading/trailing dashes as requested.
93 in / 202 out -> $0.000061
...
2 passed and 0 failed.

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

To 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."

From these runs and day-to-day use:

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

Synap by Linkrra: one OpenAI-compatible API for open models. synap402.com

── more in #ai-agents 4 stories · sorted by recency
── more on @qwen3 coder 30b 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/running-qwen3-coder-…] indexed:0 read:6min 2026-11-11 · —