toGemini — emit Gemini tool schema
Rust · crate toolnexus · SPEC §4
pub fn to_gemini(tools: &[Tool]) -> Vec<Value>impl Toolkit { pub fn to_gemini(&self) -> Vec<Value> }Render the toolkit as Gemini function-declaration schema.
When to use it
Section titled “When to use it”When you call the provider yourself and need the tool schema in its shape: [\{functionDeclarations:[...]\}]. Schema only — the input schema is passed through verbatim.
Why this and not the alternative
Section titled “Why this and not the alternative”Use the adapter rather than hand-writing the JSON: names and schemas then always match what Toolkit::execute routes.
Examples
Section titled “Examples”1. One tool, and the wrapper that surprises everyone
Section titled “1. One tool, and the wrapper that surprises everyone”use serde_json::json;use toolnexus::{define_tool, to_gemini};
fn main() -> Result<(), Box<dyn std::error::Error>> { let weather = define_tool( "get_weather", "Current weather for a city", Some(json!({"type":"object","properties":{"city":{"type":"string"}},"required":["city"]})), |args, _ctx| async move { let city = args["city"].as_str().ok_or("city is required")?; Ok::<_, String>(format!("{city}: 21C, clear")) }, ); let now = define_tool("now", "Current time", None, |_a, _c| async { Ok::<_, String>("12:00".to_string()) }); let schema = to_gemini(&[weather, now]); // ONE element wrapping ALL declarations — not one element per tool. assert_eq!(schema.len(), 1); let decls = schema[0]["functionDeclarations"].as_array().unwrap(); assert_eq!(decls.len(), 2); assert_eq!(decls[0]["name"], "get_weather"); assert_eq!(decls[0]["parameters"]["required"][0], "city"); println!("{}", serde_json::to_string_pretty(&schema)?); println!("ok: 1 wrapper, {} declarations", decls.len()); Ok(())}2. Feeding it straight into a generateContent body
Section titled “2. Feeding it straight into a generateContent body”use serde_json::json;use toolnexus::{BuiltinsConfig, ToolkitOptions, create_toolkit, define_tool};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let now = define_tool("now", "Current time", None, |_a, _c| async { Ok::<_, String>("12:00".to_string()) }); let tk = create_toolkit(ToolkitOptions { extra_tools: vec![now], builtins: Some(BuiltinsConfig::off()), ..Default::default() }) .await?; let body = json!({ "contents": [{"role": "user", "parts": [{"text": "what time is it?"}]}], "tools": tk.to_gemini(), }); assert_eq!(body["tools"][0]["functionDeclarations"][0]["name"], "now"); println!("ok: {}", body["tools"][0]["functionDeclarations"][0]["name"]); Ok(())}3. Round-tripping a functionCall part back to the tool
Section titled “3. Round-tripping a functionCall part back to the tool”Gemini returns args as an object and has no call id — the reply functionResponse is matched by name.
use serde_json::json;use toolnexus::{BuiltinsConfig, ToolContext, ToolkitOptions, create_toolkit, define_tool};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let weather = define_tool( "get_weather", "Current weather for a city", Some(json!({"type":"object","properties":{"city":{"type":"string"}},"required":["city"]})), |args, _ctx| async move { let city = args["city"].as_str().ok_or("city is required")?; Ok::<_, String>(format!("{city}: 21C, clear")) }, ); let tk = create_toolkit(ToolkitOptions { extra_tools: vec![weather], builtins: Some(BuiltinsConfig::off()), ..Default::default() }) .await?;
// candidates[0].content.parts[0] of a generateContent response. let part = json!({"functionCall": {"name": "get_weather", "args": {"city": "Chennai"}}}); let call = &part["functionCall"]; let r = tk .execute(call["name"].as_str().unwrap(), call["args"].clone(), ToolContext::default()) .await; let reply = json!({"role": "user", "parts": [{"functionResponse": { "name": call["name"], "response": {"output": r.output}, }}]}); assert_eq!(reply["parts"][0]["functionResponse"]["response"]["output"], "Chennai: 21C, clear"); println!("ok: {}", reply["parts"][0]["functionResponse"]["name"]); Ok(())}See also
Section titled “See also”to_openai— Render the toolkit as OpenAI function-calling schema.to_anthropic— Render the toolkit as Anthropic tool-use schema.