Describe the bug
CreateMessageParams.Temperature and CreateMessageWithToolsParams.Temperature are declared as:
Temperature float64 `json:"temperature,omitempty"`
With omitempty, a float64 value of 0 is dropped from the marshaled JSON entirely. For sampling, temperature: 0 is a meaningful, distinct value (greedy/deterministic decoding) — not the same as "unspecified" (where a client applies its own default, typically ~0.7–1.0).
So a server that requests deterministic output:
json.Marshal(&CreateMessageParams{MaxTokens: 100, Messages: msgs, Temperature: 0})
// -> no "temperature" key in the output
produces JSON with no temperature field. A non-Go client (JS/Python) then samples at its own default temperature, contrary to the server's explicit request. (Go↔Go happens to round-trip because the receiver also decodes the absent field back to 0.0, which masks it in same-SDK tests.)
Scope / context
This is not an isolated slip — it's a consequence of the consistent convention in protocol.go, where every optional numeric field uses float64 ...,omitempty (Priority, CostPriority, IntelligencePriority, SpeedPriority, Total, Temperature). For the priority/total fields, 0 conventionally means "unspecified", so omitempty is fine. Temperature is the one where 0 is a distinct, commonly-used value, so the convention loses information there.
Possible directions (all have tradeoffs — hence an issue, not a PR)
Temperature *float64 (+ omitempty) — correct semantics (nil = unset, &0 = explicit 0), but a breaking API change on a stable v1.x type and inconsistent with the sibling fields.
- Drop
omitempty — non-breaking to the type, but then unset also serializes as "temperature":0, forcing deterministic sampling on clients for the common unset case (semantically wrong the other way).
- Custom
MarshalJSON — preserves the exported type and unset semantics, but adds a hand-written marshaler where the package currently has none.
Filing this so the maintainers can decide the preferred direction (and whether the same applies to the other numeric fields). Happy to send a PR once you indicate which approach you'd accept.
Version
main / v1.7.0.
Describe the bug
CreateMessageParams.TemperatureandCreateMessageWithToolsParams.Temperatureare declared as:With
omitempty, afloat64value of0is dropped from the marshaled JSON entirely. For sampling,temperature: 0is a meaningful, distinct value (greedy/deterministic decoding) — not the same as "unspecified" (where a client applies its own default, typically ~0.7–1.0).So a server that requests deterministic output:
produces JSON with no
temperaturefield. A non-Go client (JS/Python) then samples at its own default temperature, contrary to the server's explicit request. (Go↔Go happens to round-trip because the receiver also decodes the absent field back to0.0, which masks it in same-SDK tests.)Scope / context
This is not an isolated slip — it's a consequence of the consistent convention in
protocol.go, where every optional numeric field usesfloat64 ...,omitempty(Priority,CostPriority,IntelligencePriority,SpeedPriority,Total,Temperature). For the priority/total fields,0conventionally means "unspecified", soomitemptyis fine.Temperatureis the one where0is a distinct, commonly-used value, so the convention loses information there.Possible directions (all have tradeoffs — hence an issue, not a PR)
Temperature *float64(+omitempty) — correct semantics (nil= unset,&0= explicit 0), but a breaking API change on a stable v1.x type and inconsistent with the sibling fields.omitempty— non-breaking to the type, but then unset also serializes as"temperature":0, forcing deterministic sampling on clients for the common unset case (semantically wrong the other way).MarshalJSON— preserves the exported type and unset semantics, but adds a hand-written marshaler where the package currently has none.Filing this so the maintainers can decide the preferred direction (and whether the same applies to the other numeric fields). Happy to send a PR once you indicate which approach you'd accept.
Version
main/ v1.7.0.