> Version notice: This site documents BAML v0, the legacy DSL. BAML v1 is a separate, fully featured programming language in public beta. If the user intends to use BAML v1, ignore this site's content and use the BAML v1 documentation instead. If the intended version is unclear, clarify it before using this page. > For clean Markdown of any page, append .md to the page URL. For the complete documentation index, see https://docs.boundaryml.com/llms.txt. For MCP access, connect to https://docs.boundaryml.com/_mcp/server. # with_options > **Info** > > Added in 0.79.0 The `with_options` function creates a new client with default configuration options for logging, client registry, and type builders. These options are automatically applied to all function calls made through this client, but can be overridden on a per-call basis when needed. ## Quick Start #### Python ```python from baml_client import b from baml_py import ClientRegistry, Collector # Simple: just set the client name my_b = b.with_options(client="openai/gpt-5-mini") # Or with full options for advanced use cases collector = Collector(name="my-collector") client_registry = ClientRegistry() client_registry.set_primary("openai/gpt-5-mini") env = {"BAML_LOG": "DEBUG", "OPENAI_API_KEY": "key-123"} # Create client with default options my_b = b.with_options(collector=collector, client_registry=client_registry, env=env) # Uses the default options result = my_b.ExtractResume("...") # Override options for a specific call other_collector = Collector(name="other-collector") result2 = my_b.ExtractResume("...", baml_options={"collector": other_collector}) ``` #### TypeScript ```typescript import { b } from "baml_client" import { Collector, ClientRegistry } from "@boundaryml/baml" // Simple: just set the client name const myB = b.withOptions({ client: "openai/gpt-5-mini" }) // Or with full options for advanced use cases const collector = new Collector("my-collector") const clientRegistry = new ClientRegistry() clientRegistry.setPrimary("openai/gpt-5-mini") const env = {"BAML_LOG": "DEBUG", "OPENAI_API_KEY": "key-123"} // Create client with default options const myBAdvanced = b.withOptions({ collector, clientRegistry, env }) // Uses the default options const result = await myBAdvanced.ExtractResume("...") // Override options for a specific call const otherCollector = new Collector("other-collector") const result2 = await myBAdvanced.ExtractResume("...", { collector: otherCollector }) ``` #### Go > **Note** > > Go doesn't have a `with_options` method like Python/TypeScript. Instead, use individual option functions like `WithClient`, `WithCollector`, `WithClientRegistry`, and `WithEnv` directly in function calls. ```go package main import ( "context" b "example.com/myproject/baml_client" ) func run() { ctx := context.Background() // Simple: just set the client name result, err := b.ExtractResume(ctx, "...", b.WithClient("openai/gpt-5-mini")) if err != nil { panic(err) } // Or with full options for advanced use cases collector, err := b.NewCollector("my-collector") if err != nil { panic(err) } env := map[string]string{ "BAML_LOG": "DEBUG", "OPENAI_API_KEY": "key-123", } // Make function call with multiple options result, err = b.ExtractResume(ctx, "...", b.WithClient("openai/gpt-5-mini"), b.WithCollector(collector), b.WithEnv(env)) if err != nil { panic(err) } // Override options for a specific call otherCollector, err := b.NewCollector("other-collector") if err != nil { panic(err) } result2, err := b.ExtractResume(ctx, "...", b.WithCollector(otherCollector)) if err != nil { panic(err) } } ``` #### Ruby ```ruby require 'baml_client' # Set up default options for this client collector = Baml::Collector.new(name: "my-collector") client_registry = Baml::ClientRegistry.new client_registry.set_primary("openai/gpt-5-mini") env = {"BAML_LOG": "DEBUG", "OPENAI_API_KEY": "key-123"} # Create client with default options my_b = Baml.Client.with_options(collector: collector, client_registry: client_registry, env: env) # Uses the default options result = my_b.ExtractResume(input: "...") # Override options for a specific call other_collector = Baml::Collector.new(name: "other-collector") result2 = my_b.ExtractResume(input: "...", baml_options: { collector: other_collector }) ``` #### Rust > **Note** > > Rust doesn't have a `with_options` method. Instead, use builder methods like `.with_client()`, `.with_collector()`, `.with_client_registry()`, and `.with_env_var()` directly on function calls. ```rust use myproject::baml_client::sync_client::B; use myproject::baml_client::new_collector; use baml::ClientRegistry; use std::collections::HashMap; fn main() { let collector = new_collector("my-collector"); let mut registry = ClientRegistry::new(); registry.set_primary_client("openai/gpt-5-mini"); // Pass options per call using builder methods let result = B.ExtractResume .with_collector(&collector) .with_client_registry(®istry) .with_env_var("BAML_LOG", "DEBUG") .call("...") .unwrap(); } ``` ## Common Use Cases ### Basic Configuration Use `with_options` to create a client with default settings that will be applied to all function calls made through this client. These defaults can be overridden when needed. #### Python ```python from baml_client import b from baml_py import ClientRegistry, Collector def run(): # Configure options collector = Collector(name="my-collector") client_registry = ClientRegistry() client_registry.set_primary("openai/gpt-5-mini") # Create configured client my_b = b.with_options(collector=collector, client_registry=client_registry) # All calls will use the configured options res = my_b.ExtractResume("...") invoice = my_b.ExtractInvoice("...") # Access configuration print(my_b.client_registry) # Access logs from the collector print(collector.logs) print(collector.last) ``` #### TypeScript ```typescript import { b } from "baml_client" import { Collector, ClientRegistry } from "@boundaryml/baml" const collector = new Collector("my-collector") const clientRegistry = new ClientRegistry() clientRegistry.setPrimary("openai/gpt-5-mini") const myB = b.withOptions({ collector, clientRegistry }) // All calls will use the configured options const res = await myB.ExtractResume("...") const invoice = await myB.ExtractInvoice("...") // Access configuration console.log(myB.clientRegistry) console.log(collector.logs) console.log(collector.last?.usage) ``` #### Go > **Note** > > Go doesn't support client pre-configuration with `with_options`. Each function call requires options to be passed individually. ```go package main import ( "context" "fmt" b "example.com/myproject/baml_client" ) func run() { ctx := context.Background() // Configure options for reuse collector, err := b.NewCollector("my-collector") if err != nil { panic(err) } clientRegistry, err := b.NewClientRegistry() if err != nil { panic(err) } err = clientRegistry.SetPrimary("openai/gpt-5-mini") if err != nil { panic(err) } // All calls must explicitly pass options res, err := b.ExtractResume(ctx, "...", nil, b.WithCollector(collector), b.WithClientRegistry(clientRegistry)) if err != nil { panic(err) } invoice, err := b.ExtractInvoice(ctx, "...", b.WithCollector(collector), b.WithClientRegistry(clientRegistry)) if err != nil { panic(err) } // Access logs from collector logs, err := collector.Logs() if err != nil { panic(err) } fmt.Printf("Logs: %+v\n", logs) } ``` #### Ruby ```ruby require 'baml_client' collector = Baml::Collector.new(name: "my-collector") client_registry = Baml::ClientRegistry.new client_registry.set_primary("openai/gpt-5-mini") my_b = Baml.Client.with_options(collector: collector, client_registry: client_registry) # All calls will use the configured options res = my_b.ExtractResume(input: "...") invoice = my_b.ExtractInvoice(input: "...") # Access configuration print(my_b.client_registry) print(collector.logs) print(collector.last.usage) ``` #### Rust ```rust use myproject::baml_client::sync_client::B; use myproject::baml_client::new_collector; use baml::ClientRegistry; fn main() { let collector = new_collector("my-collector"); let mut registry = ClientRegistry::new(); registry.set_primary_client("openai/gpt-5-mini"); // Pass options per call using builder methods let res = B.ExtractResume .with_collector(&collector) .with_client_registry(®istry) .call("...") .unwrap(); let invoice = B.ExtractInvoice .with_collector(&collector) .with_client_registry(®istry) .call("...") .unwrap(); // Access logs from collector let logs = collector.logs(); println!("{:?}", logs); } ``` ### Per-call Tags Add tags to a specific BAML function call. Tags are useful for correlating requests, A/B versions, user IDs, etc. #### Python ```python from baml_client import b from baml_py import Collector collector = Collector(name="tags-collector") res = b.TestOpenAIGPT4oMini( "hello", baml_options={ "collector": collector, "tags": {"call_id": "first", "version": "v1"}, }, ) print(collector.last.tags) ``` #### TypeScript ```typescript import { b } from "baml_client"; import { Collector } from "@boundaryml/baml"; const collector = new Collector("tags-collector"); await b.TestOpenAIGPT4oMini("hello", { collector, tags: { callId: "first", version: "v1" } }); console.log(collector.last!.tags); ``` #### Go ```go ctx := context.Background() collector, _ := b.NewCollector("tags-collector") tags := map[string]string{"callId": "first", "version": "v1"} _, _ = b.TestOpenAIGPT4oMini(ctx, "hello", b.WithCollector(collector), b.WithTags(tags)) logs, _ := collector.Logs() if len(logs) > 0 { t, _ := logs[0].Tags() fmt.Println(t) } ``` #### Rust ```rust use myproject::baml_client::sync_client::B; use myproject::baml_client::new_collector; let collector = new_collector("tags-collector"); let result = B.TestOpenAIGPT4oMini .with_collector(&collector) .with_tag("call_id", "first") .with_tag("version", "v1") .call("hello") .unwrap(); let logs = collector.logs(); if let Some(log) = logs.last() { println!("{:?}", log.tags()); } ``` ### Parallel Execution When running functions in parallel, `with_options` helps maintain consistent configuration across all calls. This works seamlessly with the [`Collector`](./collector) functionality. #### Python ```python from baml_client.async_client import b from baml_py import ClientRegistry, Collector import asyncio async def run(): collector = Collector(name="my-collector") my_b = b.with_options(collector=collector, client_registry=client_registry) # Run multiple functions in parallel res, invoice = await asyncio.gather( my_b.ExtractResume("..."), my_b.ExtractInvoice("...") ) # Access results and logs print(res) print(invoice) # Use tags or iterate logs to correlate specific calls for log in collector.logs: print(log.usage) ``` #### TypeScript ```typescript import { Collector, ClientRegistry } from "@boundaryml/baml" const collector = new Collector("my-collector") const myB = b.withOptions({ collector, clientRegistry }) // Run multiple functions in parallel const [ {data: res, id: resumeId}, {data: invoice, id: invoiceId} ] = await Promise.all([ myB.raw.ExtractResume("..."), myB.raw.ExtractInvoice("...") ]) // Access results and logs console.log(res) console.log(invoice) // Use tags or iterate logs to correlate specific calls for (const log of collector.logs) { console.log(log.usage) } ``` #### Ruby BAML Ruby (beta) does not currently support async/concurrent calls. Reach out to us if it's something you need! ### Streaming Mode `with_options` can be used with streaming functions while maintaining all configured options. #### Python ```python from baml_client.async_client import b from baml_py import Collector async def run(): collector = Collector(name="my-collector") my_b = b.with_options(collector=collector, client_registry=client_registry) stream = my_b.stream.ExtractResume("...") async for chunk in stream: print(chunk) result = await stream.get_final_result() # Use tags or collector.last / collector.logs for usage print(collector.last.usage) ``` #### TypeScript ```typescript import { Collector } from "@boundaryml/baml" const collector = new Collector("my-collector") const myB = b.withOptions({ collector, clientRegistry }) const stream = myB.stream.ExtractResume("...") for await (const chunk of stream) { console.log(chunk) } const result = await stream.getFinalResult() // Use tags or collector.last / collector.logs for usage console.log(collector.last?.usage) ``` #### Ruby ```ruby require 'baml_client' collector = Baml::Collector.new(name: "my-collector") my_b = Baml.Client.with_options(collector: collector, client_registry: client_registry) stream = my_b.stream.ExtractResume(input: "...") stream.each do |chunk| print(chunk) end result = stream.get_final_result # Use tags or collector.last / collector.logs for usage print(collector.last.usage) ``` #### Rust ```rust use myproject::baml_client::sync_client::B; use myproject::baml_client::new_collector; let collector = new_collector("my-collector"); let mut stream = B.ExtractResume .with_collector(&collector) .stream("...")?; for partial in stream.partials() { println!("{:?}", partial?); } let result = stream.get_final_response()?; // Access usage from collector println!("{:?}", collector.usage()); ``` ## API Reference ### with\_options Parameters > **Note** > > These can always be overridden on a per-call basis with the `baml_options` parameter in any function call. | Parameter | Type | Description | | ----------------- | ---------------------------------------------- | -------------------------------------------------------------------------------- | | `client` | `string` | Client name to use for all calls (shorthand for `client_registry.set_primary()`) | | `collector` | [`Collector`](/ref/baml_client/collector) | Collector instance for tracking function calls and usage metrics | | `client_registry` | `ClientRegistry` | Registry for managing LLM clients and their configurations | | `type_builder` | [`TypeBuilder`](/ref/baml_client/type-builder) | Custom type builder for function inputs and outputs | | `env` | `Dict/Object` | Environment variables to set for the client | | `tags` (per-call) | `Dict/Object` | Arbitrary metadata for this call; merged with parent trace tags | ### Configured Client Properties > **Info** > > The configured client maintains the same interface as the base `baml_client`, so you can use all the same functions and methods. ## Related Topics * [Collector](/ref/baml_client/collector) - Track function calls and usage metrics * [TypeBuilder](/ref/baml_client/type-builder) - Build custom types for your functions * [Client Registry](/ref/baml_client/client-registry) - Manage LLM clients and their configurations * [Environment Variables](/ref/baml/general-baml-syntax/environment-variables) - Set environment variables * [AbortController](/ref/baml_client/abort-signal) - Cancel in-flight operations > **Info** > > The configured client maintains the same interface as the base client, so you can use all the same functions and methods.