0.17.0: `baml.json.json` client option (`request_body`) rejects a map literal — only `baml.json.parse` of a hand-escaped string works
Summary
On 0.17.0, a client option typed baml.json.json | null (e.g. openai.GenericClient.new's request_body) rejects a map literal — the only accepted form we found is baml.json.parse("…") over a hand-escaped JSON string. Escaping JSON inside a BAML string literal is exactly the error-prone step a typed literal should replace.
Reproduce
client Sink = openai.GenericClient.new(
model = "m",
base_url = env.VLLM_QWEN_BASE_URL,
api_key = env.VLLM_API_KEY,
request_body = { chat_template_kwargs: { enable_thinking: false } },
);$ BAML_VERSION=0.17.0 baml check --from .
error: mismatched types — expected `baml.json.json`, found `map<string, map<string, bool>>`Working form:
request_body = baml.json.parse("{\"chat_template_kwargs\": {\"enable_thinking\": false}}"),— verified end-to-end against a local HTTP sink: the captured POST /v1/chat/completions body carries "chat_template_kwargs":{"enable_thinking":false} verbatim, merged beside model/temperature/max_tokens. So the feature (arbitrary provider body pass-through) works; only the literal ergonomics are the problem.
Why it matters to a real consumer
zenzy-atlas passes vLLM's chat_template_kwargs {enable_thinking: false} on every call of its Qwen clients (Qwen3.6's chat template defaults thinking ON, which on terse extraction tasks rambles to the token ceiling with empty content — the pass-through is load-bearing, baked into the client registration). On classic 0.15 syntax this was a plain nested map in options. On 0.17 the same intent needs a string-escaped JSON literal in every client that carries it; a typo inside the escaped string (say a missing brace) is only caught at json.parse time rather than by the BAML parser, and the literal is unreadable in review.
Ask
Coerce structurally-JSON-compatible literals (maps/lists/strings/numbers/bools/null) to baml.json.json at the type boundary, or provide a baml.json.of(<literal>) builder — either removes the stringly-typed escape step while keeping the json type distinct.
Environment: Linux x86_64, baml wrapper 0.2.0, toolchain 0.17.0.
Source: BoundaryML/baml