pub fn wire_schema<T>() -> Valuewhere
T: JsonSchema + ?Sized,Expand description
Derive a JSON Schema in the shape the Gemini API will actually enforce.
This is the one way a Rust type becomes a schema on the wire: #[tool]
parameters, TypedTool arguments, typed agent output
and turn extraction all go through it. Derive JsonSchema on the type
(doc comments on fields become descriptions) and call this instead of
schemars::schema_for!, whose output the API misreads in the ways below.
use gemini_adk_rs::tool::wire_schema;
#[derive(schemars::JsonSchema)]
#[allow(dead_code)]
struct Lookup {
/// The city to look up.
city: String,
units: Option<String>,
}
let schema = wire_schema::<Lookup>();
assert_eq!(schema["properties"]["city"]["description"], "The city to look up.");
assert_eq!(schema["properties"]["units"]["type"], "string"); // not ["string", "null"]
assert_eq!(schema["required"], serde_json::json!(["city"]));schemars::schema_for! hoists every nested type into definitions and
points at it with $ref. The API does not resolve those references — it
ignores them, silently. A declaration carrying $ref therefore degrades to
“send some JSON”: enum constraints stop applying and the model invents
variants the type cannot deserialize. On the Live endpoint the failure is
harsher still — the server closes the connection during setup rather than
accepting the declaration.
So subschemas are inlined and $schema/definitions are stripped, leaving
nothing that points outside the document. A schema that is ignored is worse
than one that is absent: it reads as a constraint and behaves like free-form
generation.
The result is then narrowed to the API’s schema subset, which draft-07 is
broader than in ways that matter: a nullable union collapses to its one
type, and a oneOf over single-variant enums flattens into one enum.