Skip to main content
The Rust SDK is in alpha. The API is stable, but some interfaces may change based on feedback.
The Answer API searches relevant sources and synthesizes a cited, factual answer in one call.

Wire up Valyu Answer (search-grounded answers) with the Rust SDK (alpha).

Open in Cursor

Basic usage

use valyu::ValyuClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = ValyuClient::new("your-api-key");

    let response = client.ask("What are the latest developments in quantum computing?").await?;

    if response.success {
        if let Some(contents) = &response.contents {
            println!("{}", contents);
        }
    }

    Ok(())
}

Common patterns

Use the AnswerRequest builder for anything beyond a plain question, then call client.answer(&request):
use serde_json::json;
use valyu::AnswerRequest;

// Steer tone and format
let req = AnswerRequest::new("Explain quantum computing")
    .with_system_instructions("Explain clearly with practical examples, no jargon.");

// Restrict to authoritative sources
let req = AnswerRequest::new("React performance best practices")
    .with_search_type("web")
    .with_included_sources(vec!["react.dev".to_string(), "developer.mozilla.org".to_string()]);

// Recent, location-specific answers
let req = AnswerRequest::new("Current renewable energy incentives")
    .with_country_code("US")
    .with_date_range("2024-01-01", "2024-12-31");

// Structured output - pass a JSON schema, get back a structured object
let req = AnswerRequest::new("What is the impact of AI on software development?")
    .with_structured_output(json!({
        "type": "object",
        "properties": {
            "summary": {"type": "string"},
            "key_impacts": {"type": "array", "items": {"type": "string"}}
        },
        "required": ["summary", "key_impacts"]
    }));

let response = client.answer(&req).await?;
// With a schema, `contents` comes back as a JSON object instead of a string.
if let Some(contents) = &response.contents {
    if contents.is_object() {
        println!("{}", serde_json::to_string_pretty(contents)?);
    }
}
For open-ended, multi-step work, reach for DeepResearch instead of Answer.

Reference

query (impl Into<String>, required) - the question to answer.
MethodTypeDescriptionDefault
with_structured_output()serde_json::ValueJSON schema for structured responseNone
with_system_instructions()impl Into<String>Custom AI instructions (max 2000 chars)None
with_search_type()"web" | "proprietary" | "all"Search type before generating the answer"all"
with_data_max_price()f64Max cost in USD for data retrieval1.0
with_country_code()impl Into<String>2-letter ISO country code to bias resultsNone
with_included_sources() / with_excluded_sources()Vec<String>Sources to search within / excludeNone
with_date_range()(start, end)Date filter (YYYY-MM-DD)None
with_fast_mode()boolReduced latencyfalse
pub struct AnswerResponse {
    pub success: bool,
    pub error: Option<String>,
    pub tx_id: Option<String>,
    pub original_query: Option<String>,
    pub contents: Option<serde_json::Value>,  // String, or a JSON object when structured_output is set
    pub search_results: Option<Vec<AnswerSearchResult>>,
    pub search_metadata: Option<AnswerSearchMetadata>,
    pub ai_usage: Option<AiUsage>,
    pub cost: Option<AnswerCost>,
}

pub struct AnswerCost {
    pub search_cost: Option<f64>,
    pub ai_cost: Option<f64>,
    pub total_deduction_dollars: Option<f64>,
}
use valyu::{AnswerRequest, ValyuError};

match client.answer(&AnswerRequest::new("test query")).await {
    Ok(response) => {
        if !response.success {
            eprintln!("Answer failed: {:?}", response.error);
            return;
        }
        if let Some(contents) = &response.contents {
            println!("{}", contents);
        }
    }
    Err(ValyuError::InvalidApiKey) => eprintln!("Invalid API key"),
    Err(ValyuError::RateLimitExceeded) => eprintln!("Rate limit exceeded"),
    Err(e) => eprintln!("Error: {}", e),
}