Skip to main content

ClientConfig

Struct ClientConfig 

Source
pub struct ClientConfig {
    pub api_key: Option<SecretString>,
    pub base_url: Option<Url>,
    pub default_model: Option<String>,
    pub timeout: Duration,
    pub retry: RetryPolicy,
    pub default_headers: HeaderMap,
}
Expand description

Client configuration. Explicit values win over environment, then defaults.

Fields§

§api_key: Option<SecretString>

API key. Falls back to ENV_API_KEY.

§base_url: Option<Url>

API root. Falls back to ENV_BASE_URL, then DEFAULT_BASE_URL.

§default_model: Option<String>

Default model. Falls back to ENV_DEFAULT_MODEL, then DEFAULT_MODEL.

§timeout: Duration

Per-attempt timeout including the body. Default: 10 s.

§retry: RetryPolicy

Retry policy. Default matches the official SDKs.

§default_headers: HeaderMap

Extra headers. Cannot override Authorization, Accept, or SDK identification headers.

Implementations§

Source§

impl ClientConfig

Source

pub fn new() -> Self

Empty config that will read the process environment in crate::Client::new.

Examples found in repository?
examples/models.rs (line 22)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_models().respond(json!({
15        "models": [{
16            "name": "jev-latest",
17            "description": "TypeSafe flagship",
18            "release_date": "2026-01-01"
19        }]
20    }));
21
22    let client = ClientConfig::new()
23        .api_key("test")
24        .base_url(mock.url())
25        .build()?;
26
27    client.warm_up().await?;
28    for model in client.models().list().await? {
29        println!("{} — {}", model.name, model.description);
30    }
31    Ok(())
32}
More examples
Hide additional examples
examples/blocking.rs (line 20)
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    let rt = tokio::runtime::Builder::new_multi_thread()
13        .enable_all()
14        .build()?;
15    let mock = rt.block_on(MockServer::start());
16    mock.on_system_one().respond(json!({
17        "urgent": noul(0.91),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build_blocking()?;
24
25    let response = client.system_one(
26        "Help! My payouts have been failing for 3 days.",
27        questions! { "urgent" => Question::noul("Does this convey urgency?") },
28    )?;
29    println!("urgent noul = {:?}", response.noul("urgent"));
30
31    drop(client);
32    drop(mock);
33    drop(rt);
34    Ok(())
35}
examples/triage.rs (line 20)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_system_one().respond(json!({
15        "urgent": noul(0.97),
16        "team": choice("technical", 0.82),
17        "frustration": score(1.6, 0.78),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build()?;
24
25    let response = client
26        .system_one(
27            "Help! My payouts have been failing for 3 days.",
28            questions! {
29                "urgent" => Question::noul("Does this convey urgency?")
30                    .when_true("Explicitly time-sensitive")
31                    .when_false("No time pressure"),
32                "team" => Question::choice("Which team should handle this?")
33                    .option("billing", "Payments, invoicing, refunds")
34                    .option("technical", "Bugs, outages, integrations")
35                    .option("sales", "Pricing, upgrades, new accounts"),
36                "frustration" => Question::score("How frustrated is the customer?")
37                    .level("Calm")
38                    .level("Frustrated")
39                    .level("Very angry"),
40            },
41        )
42        .await?;
43
44    println!("urgent      = {:?}", response.noul("urgent"));
45    println!(
46        "team        = {:?}",
47        response.choice("team").map(|c| c.choice)
48    );
49    println!(
50        "frustration = {:?}",
51        response.score("frustration").map(|s| s.score)
52    );
53    Ok(())
54}
Source

pub fn api_key(self, key: impl Into<SecretString>) -> Self

Set the API key.

Examples found in repository?
examples/models.rs (line 23)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_models().respond(json!({
15        "models": [{
16            "name": "jev-latest",
17            "description": "TypeSafe flagship",
18            "release_date": "2026-01-01"
19        }]
20    }));
21
22    let client = ClientConfig::new()
23        .api_key("test")
24        .base_url(mock.url())
25        .build()?;
26
27    client.warm_up().await?;
28    for model in client.models().list().await? {
29        println!("{} — {}", model.name, model.description);
30    }
31    Ok(())
32}
More examples
Hide additional examples
examples/blocking.rs (line 21)
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    let rt = tokio::runtime::Builder::new_multi_thread()
13        .enable_all()
14        .build()?;
15    let mock = rt.block_on(MockServer::start());
16    mock.on_system_one().respond(json!({
17        "urgent": noul(0.91),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build_blocking()?;
24
25    let response = client.system_one(
26        "Help! My payouts have been failing for 3 days.",
27        questions! { "urgent" => Question::noul("Does this convey urgency?") },
28    )?;
29    println!("urgent noul = {:?}", response.noul("urgent"));
30
31    drop(client);
32    drop(mock);
33    drop(rt);
34    Ok(())
35}
examples/triage.rs (line 21)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_system_one().respond(json!({
15        "urgent": noul(0.97),
16        "team": choice("technical", 0.82),
17        "frustration": score(1.6, 0.78),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build()?;
24
25    let response = client
26        .system_one(
27            "Help! My payouts have been failing for 3 days.",
28            questions! {
29                "urgent" => Question::noul("Does this convey urgency?")
30                    .when_true("Explicitly time-sensitive")
31                    .when_false("No time pressure"),
32                "team" => Question::choice("Which team should handle this?")
33                    .option("billing", "Payments, invoicing, refunds")
34                    .option("technical", "Bugs, outages, integrations")
35                    .option("sales", "Pricing, upgrades, new accounts"),
36                "frustration" => Question::score("How frustrated is the customer?")
37                    .level("Calm")
38                    .level("Frustrated")
39                    .level("Very angry"),
40            },
41        )
42        .await?;
43
44    println!("urgent      = {:?}", response.noul("urgent"));
45    println!(
46        "team        = {:?}",
47        response.choice("team").map(|c| c.choice)
48    );
49    println!(
50        "frustration = {:?}",
51        response.score("frustration").map(|s| s.score)
52    );
53    Ok(())
54}
Source

pub fn base_url(self, url: Url) -> Self

Set the API root.

Examples found in repository?
examples/models.rs (line 24)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_models().respond(json!({
15        "models": [{
16            "name": "jev-latest",
17            "description": "TypeSafe flagship",
18            "release_date": "2026-01-01"
19        }]
20    }));
21
22    let client = ClientConfig::new()
23        .api_key("test")
24        .base_url(mock.url())
25        .build()?;
26
27    client.warm_up().await?;
28    for model in client.models().list().await? {
29        println!("{} — {}", model.name, model.description);
30    }
31    Ok(())
32}
More examples
Hide additional examples
examples/blocking.rs (line 22)
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    let rt = tokio::runtime::Builder::new_multi_thread()
13        .enable_all()
14        .build()?;
15    let mock = rt.block_on(MockServer::start());
16    mock.on_system_one().respond(json!({
17        "urgent": noul(0.91),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build_blocking()?;
24
25    let response = client.system_one(
26        "Help! My payouts have been failing for 3 days.",
27        questions! { "urgent" => Question::noul("Does this convey urgency?") },
28    )?;
29    println!("urgent noul = {:?}", response.noul("urgent"));
30
31    drop(client);
32    drop(mock);
33    drop(rt);
34    Ok(())
35}
examples/triage.rs (line 22)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_system_one().respond(json!({
15        "urgent": noul(0.97),
16        "team": choice("technical", 0.82),
17        "frustration": score(1.6, 0.78),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build()?;
24
25    let response = client
26        .system_one(
27            "Help! My payouts have been failing for 3 days.",
28            questions! {
29                "urgent" => Question::noul("Does this convey urgency?")
30                    .when_true("Explicitly time-sensitive")
31                    .when_false("No time pressure"),
32                "team" => Question::choice("Which team should handle this?")
33                    .option("billing", "Payments, invoicing, refunds")
34                    .option("technical", "Bugs, outages, integrations")
35                    .option("sales", "Pricing, upgrades, new accounts"),
36                "frustration" => Question::score("How frustrated is the customer?")
37                    .level("Calm")
38                    .level("Frustrated")
39                    .level("Very angry"),
40            },
41        )
42        .await?;
43
44    println!("urgent      = {:?}", response.noul("urgent"));
45    println!(
46        "team        = {:?}",
47        response.choice("team").map(|c| c.choice)
48    );
49    println!(
50        "frustration = {:?}",
51        response.score("frustration").map(|s| s.score)
52    );
53    Ok(())
54}
Source

pub fn try_base_url(self, url: &str) -> Result<Self, Error>

Parse and set the API root.

Source

pub fn default_model(self, model: impl Into<String>) -> Self

Set the default model.

Source

pub fn timeout(self, timeout: Duration) -> Self

Set the per-attempt timeout.

Source

pub fn retry(self, retry: RetryPolicy) -> Self

Set the retry policy.

Source

pub fn header( self, name: impl AsRef<str>, value: impl AsRef<str>, ) -> Result<Self, Error>

Insert a default header. Protected names (Authorization, Accept, User-Agent, SDK identification, retry-count) are ignored.

Source

pub fn default_headers(self, headers: HeaderMap) -> Self

Replace extra default headers. Protected names are ignored at send time.

Source

pub fn build(self) -> Result<Client, Error>

Build an async Client.

§Errors

Same as crate::Client::new.

Examples found in repository?
examples/models.rs (line 25)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_models().respond(json!({
15        "models": [{
16            "name": "jev-latest",
17            "description": "TypeSafe flagship",
18            "release_date": "2026-01-01"
19        }]
20    }));
21
22    let client = ClientConfig::new()
23        .api_key("test")
24        .base_url(mock.url())
25        .build()?;
26
27    client.warm_up().await?;
28    for model in client.models().list().await? {
29        println!("{} — {}", model.name, model.description);
30    }
31    Ok(())
32}
More examples
Hide additional examples
examples/triage.rs (line 23)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let mock = MockServer::start().await;
14    mock.on_system_one().respond(json!({
15        "urgent": noul(0.97),
16        "team": choice("technical", 0.82),
17        "frustration": score(1.6, 0.78),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build()?;
24
25    let response = client
26        .system_one(
27            "Help! My payouts have been failing for 3 days.",
28            questions! {
29                "urgent" => Question::noul("Does this convey urgency?")
30                    .when_true("Explicitly time-sensitive")
31                    .when_false("No time pressure"),
32                "team" => Question::choice("Which team should handle this?")
33                    .option("billing", "Payments, invoicing, refunds")
34                    .option("technical", "Bugs, outages, integrations")
35                    .option("sales", "Pricing, upgrades, new accounts"),
36                "frustration" => Question::score("How frustrated is the customer?")
37                    .level("Calm")
38                    .level("Frustrated")
39                    .level("Very angry"),
40            },
41        )
42        .await?;
43
44    println!("urgent      = {:?}", response.noul("urgent"));
45    println!(
46        "team        = {:?}",
47        response.choice("team").map(|c| c.choice)
48    );
49    println!(
50        "frustration = {:?}",
51        response.score("frustration").map(|s| s.score)
52    );
53    Ok(())
54}
Source

pub fn build_blocking(self) -> Result<BlockingClient, Error>

Available on crate feature blocking only.
Examples found in repository?
examples/blocking.rs (line 23)
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    let rt = tokio::runtime::Builder::new_multi_thread()
13        .enable_all()
14        .build()?;
15    let mock = rt.block_on(MockServer::start());
16    mock.on_system_one().respond(json!({
17        "urgent": noul(0.91),
18    }));
19
20    let client = ClientConfig::new()
21        .api_key("test")
22        .base_url(mock.url())
23        .build_blocking()?;
24
25    let response = client.system_one(
26        "Help! My payouts have been failing for 3 days.",
27        questions! { "urgent" => Question::noul("Does this convey urgency?") },
28    )?;
29    println!("urgent noul = {:?}", response.noul("urgent"));
30
31    drop(client);
32    drop(mock);
33    drop(rt);
34    Ok(())
35}
Source

pub fn overlay_env( &mut self, lookup: impl FnMut(&str) -> Option<String>, ) -> Result<(), Error>

Fill unset fields from lookup (typically the process environment).

Empty or whitespace-only values are ignored. Explicit fields are left unchanged.

Trait Implementations§

Source§

impl Clone for ClientConfig

Source§

fn clone(&self) -> ClientConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ClientConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ClientConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more