# Table of Contents - [🏠 Welcome | Boundary Documentation](#-welcome-boundary-documentation) - [Interactive Examples | Boundary Documentation](#interactive-examples-boundary-documentation) - [Reduce Hallucinations | Boundary Documentation](#reduce-hallucinations-boundary-documentation) - [Classification | Boundary Documentation](#classification-boundary-documentation) - [Chat | Boundary Documentation](#chat-boundary-documentation) - [Creating a Classification Function with Symbol Tuning | Boundary Documentation](#creating-a-classification-function-with-symbol-tuning-boundary-documentation) - [Action Item Extraction | Boundary Documentation](#action-item-extraction-boundary-documentation) - [Retrieval-Augmented Generation (RAG) | Boundary Documentation](#retrieval-augmented-generation-rag-boundary-documentation) - [Token Optimization | Boundary Documentation](#token-optimization-boundary-documentation) - [Chain-of-Thought Prompting | Boundary Documentation](#chain-of-thought-prompting-boundary-documentation) - [PII Data Extraction / Scrubbing | Boundary Documentation](#pii-data-extraction-scrubbing-boundary-documentation) - [Tools / Function Calling | Boundary Documentation](#tools-function-calling-boundary-documentation) - [Changelog | Boundary Documentation](#changelog-boundary-documentation) - [generator | Boundary Documentation](#generator-boundary-documentation) - [Image / Audio / Pdf / Video | Boundary Documentation](#image-audio-pdf-video-boundary-documentation) - [Keywords AI | Boundary Documentation](#keywords-ai-boundary-documentation) - [@assert | Boundary Documentation](#-assert-boundary-documentation) - [Image | Boundary Documentation](#image-boundary-documentation) - [Audio | Boundary Documentation](#audio-boundary-documentation) - [Cerebras | Boundary Documentation](#cerebras-boundary-documentation) - [config (logging / environment variables) | Boundary Documentation](#config-logging-environment-variables-boundary-documentation) - [@skip | Boundary Documentation](#-skip-boundary-documentation) - [litellm | Boundary Documentation](#litellm-boundary-documentation) - [client Option | Boundary Documentation](#client-option-boundary-documentation) - [@check | Boundary Documentation](#-check-boundary-documentation) - [@description / @@description | Boundary Documentation](#-description-description-boundary-documentation) - [Jinja in Attributes | Boundary Documentation](#jinja-in-attributes-boundary-documentation) - [AsyncClient / SyncClient | Boundary Documentation](#asyncclient-syncclient-boundary-documentation) - [@alias / @@alias | Boundary Documentation](#-alias-alias-boundary-documentation) - [Conditionals | Boundary Documentation](#conditionals-boundary-documentation) - [groq | Boundary Documentation](#groq-boundary-documentation) - [huggingface | Boundary Documentation](#huggingface-boundary-documentation) - [Variables | Boundary Documentation](#variables-boundary-documentation) - [LMStudio | Boundary Documentation](#lmstudio-boundary-documentation) - [Video | Boundary Documentation](#video-boundary-documentation) - [Microsoft Foundry / Azure AI Foundry | Boundary Documentation](#microsoft-foundry-azure-ai-foundry-boundary-documentation) - [Tinfoil | Boundary Documentation](#tinfoil-boundary-documentation) - [openrouter | Boundary Documentation](#openrouter-boundary-documentation) - [@@dynamic | Boundary Documentation](#-dynamic-boundary-documentation) - [Pdf | Boundary Documentation](#pdf-boundary-documentation) - [retry_policy | Boundary Documentation](#retry-policy-boundary-documentation) - [ctx (accessing metadata) | Boundary Documentation](#ctx-accessing-metadata-boundary-documentation) - [fallback | Boundary Documentation](#fallback-boundary-documentation) - [_.role | Boundary Documentation](#-role-boundary-documentation) - [BamlValidationError | Boundary Documentation](#bamlvalidationerror-boundary-documentation) - [with_options | Boundary Documentation](#with-options-boundary-documentation) - [What are attributes? | Boundary Documentation](#what-are-attributes-boundary-documentation) - [Unify AI | Boundary Documentation](#unify-ai-boundary-documentation) - [vercel-ai-gateway | Boundary Documentation](#vercel-ai-gateway-boundary-documentation) - [Together AI | Boundary Documentation](#together-ai-boundary-documentation) - [Hook Data Type Reference | Boundary Documentation](#hook-data-type-reference-boundary-documentation) - [vLLM | Boundary Documentation](#vllm-boundary-documentation) - [Loops | Boundary Documentation](#loops-boundary-documentation) - [baml.generateCodeOnSave | Boundary Documentation](#baml-generatecodeonsave-boundary-documentation) - [baml.syncExtensionToGeneratorVersion | Boundary Documentation](#baml-syncextensiontogeneratorversion-boundary-documentation) - [baml.enablePlaygroundProxy | Boundary Documentation](#baml-enableplaygroundproxy-boundary-documentation) - [TypeBuilder | Boundary Documentation](#typebuilder-boundary-documentation) - [BamlClientFinishReasonError | Boundary Documentation](#bamlclientfinishreasonerror-boundary-documentation) - [What is Jinja / Cookbook | Boundary Documentation](#what-is-jinja-cookbook-boundary-documentation) - [Hook Input Type Reference | Boundary Documentation](#hook-input-type-reference-boundary-documentation) - [google-ai | Boundary Documentation](#google-ai-boundary-documentation) - [azure-openai | Boundary Documentation](#azure-openai-boundary-documentation) - [ollama | Boundary Documentation](#ollama-boundary-documentation) - [anthropic | Boundary Documentation](#anthropic-boundary-documentation) - [ctx.output_format | Boundary Documentation](#ctx-output-format-boundary-documentation) - [BAML Error Types | Boundary Documentation](#baml-error-types-boundary-documentation) - [Collector | Boundary Documentation](#collector-boundary-documentation) - [openai-responses | Boundary Documentation](#openai-responses-boundary-documentation) - [baml.cliPath | Boundary Documentation](#baml-clipath-boundary-documentation) - [Hook Output Type Reference | Boundary Documentation](#hook-output-type-reference-boundary-documentation) - [openai-generic | Boundary Documentation](#openai-generic-boundary-documentation) - [Generated Hooks Reference | Boundary Documentation](#generated-hooks-reference-boundary-documentation) - [Timeout Configuration | Boundary Documentation](#timeout-configuration-boundary-documentation) - [llama-api | Boundary Documentation](#llama-api-boundary-documentation) - [BamlAbortError | Boundary Documentation](#bamlaborterror-boundary-documentation) - [round-robin | Boundary Documentation](#round-robin-boundary-documentation) - [Jinja Filters | Boundary Documentation](#jinja-filters-boundary-documentation) - [OnTick | Boundary Documentation](#ontick-boundary-documentation) - [openai | Boundary Documentation](#openai-boundary-documentation) - [vertex-ai | Boundary Documentation](#vertex-ai-boundary-documentation) - [aws-bedrock | Boundary Documentation](#aws-bedrock-boundary-documentation) - [Claude Code | Boundary Documentation](#claude-code-boundary-documentation) - [Client Registry | Boundary Documentation](#client-registry-boundary-documentation) - [LLM Clients (client) | Boundary Documentation](#llm-clients-client-llm-boundary-documentation) --- # 🏠 Welcome | Boundary Documentation **BAML is a domain-specific language to generate structured outputs from LLMs — with the best developer experience.** With BAML you can build reliable Agents, Chatbots with RAG, extract data from Pdfs, and more. ### A small sample of features: 1. **An amazingly fast developer experience** for prompting in the BAML VSCode playground 2. **Fully type-safe outputs**, even when streaming structured data (that means autocomplete!) 3. **Flexibility** — it works with **any LLM**, **any language**, and **any schema**. 4. **State-of-the-art structured outputs** that even [outperform OpenAI with their own models](https://www.boundaryml.com/blog/sota-function-calling?q=0) — plus it works with OpenSource models. Products -------- [Guide\ \ Everything you need to know about how to get started with BAML. From installation to prompt engineering techniques.](https://docs.boundaryml.com/guide/introduction/what-is-baml) [Playground\ \ An online interactive playground to playaround with BAML without any installations.](https://promptfiddle.com/) [Examples\ \ Examples of prompts, projects, and more.](https://docs.boundaryml.com/examples) [Reference\ \ Language docs on all BAML syntax. Quickly learn syntax with simple examples and code snippets.](https://docs.boundaryml.com/ref) Motivation ---------- Prompts are more than just f-strings; they’re actual functions with logic that can quickly become complex to organize, maintain, and test. Currently, developers craft LLM prompts as if they’re writing raw HTML and CSS in text files, lacking: * Type safety * Hot-reloading or previews * Linting The situation worsens when dealing with structured outputs. Since most prompts rely on Python and Pydantic, developers must _execute_ their code and set up an entire Python environment just to test a minor prompt adjustment, or they have to setup a whole Python microservice just to call an LLM. BAML allows you to view and run prompts directly within your editor, similar to how Markdown Preview function — no additional setup necessary, that interoperates with all your favorite languages and frameworks. Just as TSX/JSX provided the ideal abstraction for web development, BAML offers the perfect abstraction for prompt engineering. Watch our [demo video](https://docs.boundaryml.com/guide/introduction/what-is-baml#demo-video) to see it in action. Comparisons ----------- Here’s our in-depth comparison with a couple of popular frameworks: * [BAML vs Pydantic](https://docs.boundaryml.com/guide/comparisons/baml-vs-pydantic) * [BAML vs Marvin](https://docs.boundaryml.com/guide/comparisons/baml-vs-marvin) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Interactive Examples | Boundary Documentation Check out the [live examples](https://baml-examples.vercel.app/) that use NextJS, and the [source code on Github](https://github.com/boundaryml/baml-examples) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Reduce Hallucinations | Boundary Documentation We recommend these simple ways to reduce hallucinations: ### 1\. Set temperature to 0.0 (especially if extracting data verbatim) This will make the model less creative and more likely to just extract the data that you want verbatim. clients.baml | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | temperature 0.0 | | 5 | } | | 6 | } | ### 2\. Reduce the number of input tokens Reduce the amount of data you’re giving the model to process to reduce confusion. Prune as much data as possible, or split your prompt into multiple prompts analyzing subsets of the data. If you’re processing `images`, try cropping the parts of the image that you don’t need. LLMs can only handle images of certain sizes, so every pixel counts. Make sure you resize images to the model’s input size (even if the provider does the resizing for you), so you can gauge how clear the image is at the model’s resolution. You’ll notice the blurrier the image is, the higher the hallucination rate. Let us know if you want more tips for processing images, we have some helper prompts we can share with you, or help debug your prompt. ### 2\. Use reasoning or reflection prompting Read our [chain-of-thought guide](https://docs.boundaryml.com/examples/prompt-engineering/chain-of-thought) for more. ### 3\. Watch out for contradictions and word associations Each word you add into the prompt will cause it to associate it with something it saw before in its training data. This is why we have techniques like [symbol tuning](https://docs.boundaryml.com/examples/prompt-engineering/symbol-tuning) to help control this bias. Let’s say you have a prompt that says: | | | --- | | Answer in this JSON schema: | | | | | | | | But when you answer, add some comments in the JSON indicating your reasoning for the field like this: | | | | Example: | | \--- | | { | | // I used the name "John" because it's the name of the person who wrote the prompt | | "name": "John" | | } | | | | JSON: | The LLM may not write the `// comment` inline, because it’s been trained to associate JSON with actual “valid” JSON. You can get around this with some more coaxing like: | | | --- | | Answer in this JSON schema: | | | | | | | | But when you answer, add some comments in the JSON indicating your reasoning for the field like this: | | \--- | | { | | // I used the name "John" because it's the name of the person who wrote the prompt | | "name": "John" | | } | | | | It's ok if this isn't fully valid JSON, | | we will fix it afterwards and remove the comments. | | | | JSON: | The LLM made an assumption that you want “JSON” — which doesn’t use comments — and our instructions were not explicit enough to override that bias originally. Keep on reading for more tips and tricks! Or reach out in our Discord [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Classification | Boundary Documentation Building a Spam Classifier with BAML ==================================== In this tutorial, you’ll learn how to create a simple but effective spam classifier using BAML and OpenAI’s GPT models. By the end, you’ll have a working classifier that can distinguish between spam and legitimate messages. Prerequisites ------------- * Basic understanding of BAML syntax * Access to OpenAI API (you’ll need an API key) Step 1: Define the Classification Schema ---------------------------------------- First, let’s define what our classification output should look like. Create a new file called `spam_classifier.baml` and add the following schema: | | | | --- | --- | | 1 | enum MessageType { | | 2 | SPAM | | 3 | NOT\_SPAM | | 4 | } | This schema defines a simple classification with two possible labels: `SPAM` or `NOT_SPAM`. Step 2: Create the Classification Function ------------------------------------------ Next, we’ll create a function that uses GPT-4 to classify text. Add this to your `spam_classifier.baml` file: | | | | --- | --- | | 1 | function ClassifyText(input: string) -> MessageType { | | 2 | client "openai/gpt-5-mini" | | 3 | prompt #" | | 4 | Classify the message. | | 5 | | | 6 | {{ ctx.output\_format }} | | 7 | | | 8 | {{ \_.role("user") }} | | 9 | | | 10 | {{ input }} | | 11 | "# | | 12 | } | Let’s break down what this function does: * Takes an input as a string * Uses the `gpt-5-mini` model * Provides clear guidelines for classification in the prompt * Returns a MessageType Step 3: Test the Classifier --------------------------- To ensure our classifier works correctly, let’s add some test cases: | | | | --- | --- | | 1 | test BasicSpamTest { | | 2 | functions \[ClassifyText\] | | 3 | args { | | 4 | input "Buy cheap watches now! Limited time offer!!!" | | 5 | } | | 6 | } | | 7 | | | 8 | test NonSpamTest { | | 9 | functions \[ClassifyText\] | | 10 | args { | | 11 | input "Hey Sarah, can we meet at 3 PM tomorrow to discuss the project?" | | 12 | } | | 13 | } | This is what it looks like in the BAML Playground: ![](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Fguide%2Fclassification-1_m.png&w=3840&q=75) Try it yourself in the Interactive Playground! ---------------------------------------------- Now that you have your classifier set up, try it with your own examples. Here are some messages you can test: 1. “Meeting at 2 PM in the conference room” 2. “CONGRATULATIONS! You’ve won $1,000,000!!!” 3. “Can you review the document I sent yesterday?” 4. “Make money fast! Work from home!!!” Next Steps ---------- * Experiment with different prompt templates to improve accuracy * Add more spam indicators to the classification criteria * Create a more complex classification schema with confidence scores * Try using different GPT models to compare performance Multi-Label Classification ========================== While the spam classifier demonstrates single-label classification (where each input belongs to exactly one category), many real-world problems require multiple labels. Let’s build a support ticket classifier that can assign multiple relevant categories to each ticket. Step 1: Define the Label Enum and Schema ---------------------------------------- Create a new file called `ticket_classifier.baml` and define the possible ticket categories as an enum: | | | | --- | --- | | 1 | enum TicketLabel { | | 2 | ACCOUNT | | 3 | BILLING | | 4 | GENERAL\_QUERY | | 5 | } | | 6 | | | 7 | class TicketClassification { | | 8 | labels TicketLabel\[\] | | 9 | } | Notice how this schema differs from our spam classifier: * We use an `enum` to define valid labels * The `labels` field is an array (`TicketLabel[]`), allowing multiple labels per ticket Step 2: Create the Multi-Label Classification Function ------------------------------------------------------ Add the classification function to your `ticket_classifier.baml` file: | | | | --- | --- | | 1 | function ClassifyTicket(ticket: string) -> TicketClassification { | | 2 | client "openai/gpt-5-mini" | | 3 | prompt #" | | 4 | You are a support agent at a tech company. Analyze the support ticket and select all applicable labels. | | 5 | | | 6 | {{ ctx.output\_format }} | | 7 | | | 8 | {{ \_.role("user") }} | | 9 | | | 10 | {{ ticket }} | | 11 | "# | | 12 | } | Key differences from the spam classifier: * The prompt includes examples showing both single and multiple labels * Examples demonstrate how labels can overlap * The model is instructed to consider all applicable labels Step 3: Test Multi-Label Classification --------------------------------------- Add test cases that cover both single-label and multi-label scenarios: | | | | --- | --- | | 1 | test ClassifyTicketSingleLabel { | | 2 | functions \[ClassifyTicket\] | | 3 | args { | | 4 | ticket "I need help resetting my password" | | 5 | } | | 6 | } | | 7 | | | 8 | test ClassifyTicketMultiLabel { | | 9 | functions \[ClassifyTicket\] | | 10 | args { | | 11 | ticket "My account is locked and I can't access my billing information" | | 12 | } | | 13 | } | This is what it looks like in the BAML Playground: ![](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Fguide%2Fclassification-2_m.png&w=3840&q=75) Try it yourself! ---------------- Test the multi-label classifier with these examples: 1. “How do I upgrade my subscription plan?” 2. “I forgot my password and need to update my payment method” 3. “What are the features included in the premium plan?” 4. “My account is showing incorrect billing history” Tips for Multi-Label Classification ----------------------------------- 1. **Balanced Examples**: Include examples in your prompt that show both single and multiple labels 2. **Clear Descriptions**: Add descriptive annotations to help the model understand each label 3. **Test Edge Cases**: Include test cases that verify the model can handle: * Single label cases * Multiple label cases * Edge cases where no labels apply [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Chat | Boundary Documentation In this guide we’ll build a small chatbot that takes in user messages and generates responses. chat-history.baml | | | | --- | --- | | 1 | class MyUserMessage { | | 2 | role "user" \| "assistant" | | 3 | content string | | 4 | } | | 5 | | | 6 | function ChatWithLLM(messages: MyUserMessage\[\]) -> string { | | 7 | client "openai/gpt-5" | | 8 | prompt #" | | 9 | Answer the user's questions based on the chat history: | | 10 | {% for message in messages %} | | 11 | {{ \_.role(message.role) }} | | 12 | {{ message.content }} | | 13 | {% endfor %} | | 14 | | | 15 | Answer: | | 16 | "# | | 17 | } | | 18 | | | 19 | test TestName { | | 20 | functions \[ChatWithLLM\] | | 21 | args { | | 22 | messages \[ |\ | 23 | { |\ | 24 | role "user" |\ | 25 | content "Hello!" |\ | 26 | } |\ | 27 | { |\ | 28 | role "assistant" |\ | 29 | content "Hi!" |\ | 30 | } |\ | 31 | \] | | 32 | } | | 33 | } | #### Code PythonTypescriptGo | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_client.types import MyUserMessage | | 3 | | | 4 | def main(): | | 5 | messages: list\[MyUserMessage\] = \[\] | | 6 | | | 7 | while True: | | 8 | content = input("Enter your message (or 'quit' to exit): ") | | 9 | if content.lower() == 'quit': | | 10 | break | | 11 | | | 12 | messages.append(MyUserMessage(role="user", content=content)) | | 13 | | | 14 | agent\_response = b.ChatWithLLM(messages=messages) | | 15 | print(f"AI: {agent\_response}") | | 16 | print() | | 17 | | | 18 | # Add the agent's response to the chat history | | 19 | messages.append(MyUserMessage(role="assistant", content=agent\_response)) | | 20 | | | 21 | if \_\_name\_\_ == "\_\_main\_\_": | | 22 | main() | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Creating a Classification Function with Symbol Tuning | Boundary Documentation Aliasing field names to abstract symbols like “k1”, “k2”, etc. can improve classification results. This technique, known as symbol tuning, helps the LLM focus on your descriptions rather than being biased by the enum or property names themselves. Why does this help in prompt engineering? ----------------------------------------- You might wonder: if I’m providing descriptions anyway, why would hiding the variable name matter? The key insight is that **LLMs have preconceived notions about what words like “Refund” or “CancelOrder” mean** based on their training data. When you use meaningful names like: | | | --- | | Refund: | | CancelOrder: | The model must reconcile its existing understanding of these terms with your custom descriptions. This can cause conflicts—especially when your definitions differ from common usage. With symbol tuning: | | | --- | | k1: | | k2: | The model’s attention is spent **100% on understanding your descriptions** rather than trying to forget or override its biases about what the category names mean. The abstract symbols have no semantic weight, so your descriptions become the sole source of meaning. The original [Symbol Tuning paper](https://arxiv.org/abs/2305.08298) demonstrated this technique in fine-tuning, but the same principle applies to prompt engineering: removing semantic bias from labels helps the model focus on what you actually want it to learn from context. Related: Using IDs in prompts ----------------------------- A similar principle applies when dealing with entity identifiers. Using long UUIDs like `550e8400-e29b-41d4-a716-446655440000` in prompts is inefficient—they consume many tokens and carry no semantic meaning. Instead, alias them to simple integers (1, 2, 3) within your prompt. See our blog post [Using UUIDs in prompts is bad](https://boundaryml.com/blog/uuid-swap) for detailed guidance. The general principle: **use the best representation for the model**, which may differ from the best representation in your code. Try it yourself --------------- As with all prompt engineering techniques, results vary by model and use case. We recommend testing with and without symbol tuning to see what works best for your specific task. Example ------- Here’s a complete classification function using symbol tuning: | | | | --- | --- | | 1 | enum MyClass { | | 2 | Refund @alias("k1") | | 3 | @description("Customer wants to refund a product") | | 4 | | | 5 | CancelOrder @alias("k2") | | 6 | @description("Customer wants to cancel an order") | | 7 | | | 8 | TechnicalSupport @alias("k3") | | 9 | @description("Customer needs help with a technical issue unrelated to account creation or login") | | 10 | | | 11 | AccountIssue @alias("k4") | | 12 | @description("Specifically relates to account-login or account-creation") | | 13 | | | 14 | Question @alias("k5") | | 15 | @description("Customer has a question") | | 16 | } | | 17 | | | 18 | function ClassifyMessageWithSymbol(input: string) -> MyClass { | | 19 | client GPT4o | | 20 | | | 21 | prompt #" | | 22 | Classify the following INPUT into ONE | | 23 | of the following categories: | | 24 | | | 25 | INPUT: {{ input }} | | 26 | | | 27 | {{ ctx.output\_format }} | | 28 | | | 29 | Response: | | 30 | "# | | 31 | } | | 32 | | | 33 | test Test1 { | | 34 | functions \[ClassifyMessageWithSymbol\] | | 35 | args { | | 36 | input "I can't access my account using my login credentials. I havent received the promised reset password email. Please help." | | 37 | } | | 38 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Action Item Extraction | Boundary Documentation In this tutorial, you’ll learn how to build a BAML function that automatically extracts structured action items from meeting transcripts. By the end, you’ll have a working system that can identify tasks, assignees, priorities, subtasks, and dependencies. Prerequisites ------------- * Basic understanding of BAML syntax * An OpenAI API key configured in your environment Step 1: Define the Data Models ------------------------------ First, let’s define the data structures for our tasks. Create a new BAML file called `action_items.baml` and add these class definitions: action\_items.baml | | | | --- | --- | | 1 | class Subtask { | | 2 | id int | | 3 | name string | | 4 | } | | 5 | | | 6 | enum Priority { | | 7 | HIGH | | 8 | MEDIUM | | 9 | LOW | | 10 | } | | 11 | | | 12 | class Ticket { | | 13 | id int | | 14 | name string | | 15 | description string | | 16 | priority Priority | | 17 | assignees string\[\] | | 18 | subtasks Subtask\[\] | | 19 | dependencies int\[\] | | 20 | } | These models define: * A `Subtask` class for breaking down larger tasks * A `Priority` enum for task urgency levels * A `Ticket` class that represents a complete task with all its metadata Step 2: Create the Task Extraction Function ------------------------------------------- Next, we’ll create a function that uses GPT-4 to analyze meeting transcripts and extract tasks: action\_items.baml | | | | --- | --- | | 1 | function ExtractTasks(transcript: string) -> Ticket\[\] { | | 2 | client "openai/gpt-4" | | 3 | prompt #" | | 4 | You are an expert at analyzing meeting transcripts and extracting structured action items and tasks. | | 5 | Extract all action items, tasks and subtasks from the meeting transcript below. | | 6 | For each task: | | 7 | - Generate a unique ID | | 8 | - Include who is assigned to it | | 9 | - Set appropriate priority level | | 10 | - Identify subtasks if any | | 11 | - Note any dependencies on other tasks | | 12 | | | 13 | {{ ctx.output\_format }} | | 14 | | | 15 | {{ \_.role("user") }} {{ transcript }} | | 16 | "# | | 17 | } | This function: * Takes a meeting transcript as input * Returns an array of `Ticket` objects * Uses GPT-4 to analyze the transcript * Includes clear instructions in the prompt for task extraction Step 3: Test the Implementation ------------------------------- Let’s add test cases to verify our implementation works correctly. Add these test cases to your BAML file: action\_items.baml | | | | --- | --- | | 1 | test SimpleTranscript { | | 2 | functions \[ExtractTasks\] | | 3 | args { | | 4 | transcript #" | | 5 | Alice: We need to update the website by next week. This is high priority. | | 6 | Bob: I can handle that. I'll need Carol's help with the design though. | | 7 | Carol: Sure, I can help with the design part. | | 8 | "# | | 9 | } | | 10 | } | | 11 | | | 12 | test ComplexTranscript { | | 13 | functions \[ExtractTasks\] | | 14 | args { | | 15 | transcript #" | | 16 | Alice: Hey team, we have several critical tasks we need to tackle for the upcoming release. First, we need to work on improving the authentication system. It's a top priority. | | 17 | Bob: Got it, Alice. I can take the lead on the authentication improvements. Are there any specific areas you want me to focus on? | | 18 | Alice: Good question, Bob. We need both a front-end revamp and back-end optimization. So basically, two sub-tasks. | | 19 | Carol: I can help with the front-end part of the authentication system. | | 20 | Bob: Great, Carol. I'll handle the back-end optimization then. | | 21 | Alice: Perfect. Now, after the authentication system is improved, we have to integrate it with our new billing system. That's a medium priority task. | | 22 | Carol: Is the new billing system already in place? | | 23 | Alice: No, it's actually another task. So it's a dependency for the integration task. Bob, can you also handle the billing system? | | 24 | Bob: Sure, but I'll need to complete the back-end optimization of the authentication system first, so it's dependent on that. | | 25 | Alice: Understood. Lastly, we also need to update our user documentation to reflect all these changes. It's a low-priority task but still important. | | 26 | Carol: I can take that on once the front-end changes for the authentication system are done. So, it would be dependent on that. | | 27 | Alice: Sounds like a plan. Let's get these tasks modeled out and get started. | | 28 | "# | | 29 | } | | 30 | } | These tests provide: * A simple case with a single task and subtask * A complex case with multiple tasks, priorities, dependencies, and assignees This is what you see in the BAML playground: ![](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Fguide%2Faction-items-simple.png&w=3840&q=75) This is the output from the complex test case: | | | | --- | --- | | 1 | \[ |\ | 2 | { |\ | 3 | "id": 1, |\ | 4 | "name": "Improve Authentication System", |\ | 5 | "description": "Overhaul the authentication system focusing on both front-end and back-end aspects.", |\ | 6 | "priority": "HIGH", |\ | 7 | "assignees": \["Bob", "Carol"\], |\ | 8 | "subtasks": \[ |\ | 9 | { |\ | 10 | "id": 2, |\ | 11 | "name": "Front-end Revamp" |\ | 12 | }, |\ | 13 | { |\ | 14 | "id": 3, |\ | 15 | "name": "Back-end Optimization" |\ | 16 | } |\ | 17 | \], |\ | 18 | "dependencies": \[\] |\ | 19 | }, |\ | 20 | { |\ | 21 | "id": 4, |\ | 22 | "name": "Develop Billing System", |\ | 23 | "description": "Create a new billing system which will be integrated with the authentication system.", |\ | 24 | "priority": "MEDIUM", |\ | 25 | "assignees": \["Bob"\], |\ | 26 | "subtasks": \[\], |\ | 27 | "dependencies": \[3\] |\ | 28 | }, |\ | 29 | { |\ | 30 | "id": 5, |\ | 31 | "name": "Integrate Authentication System with Billing System", |\ | 32 | "description": "Integrate the improved authentication system with the new billing system.", |\ | 33 | "priority": "MEDIUM", |\ | 34 | "assignees": \["Bob"\], |\ | 35 | "subtasks": \[\], |\ | 36 | "dependencies": \[3, 4\] |\ | 37 | }, |\ | 38 | { |\ | 39 | "id": 6, |\ | 40 | "name": "Update User Documentation", |\ | 41 | "description": "Update the user documentation to reflect changes in the authentication and billing systems.", |\ | 42 | "priority": "LOW", |\ | 43 | "assignees": \["Carol"\], |\ | 44 | "subtasks": \[\], |\ | 45 | "dependencies": \[2, 5\] |\ | 46 | } |\ | 47 | \] | What’s Next? ------------ You can enhance this implementation by: * Adding due dates to the `Ticket` class * Including status tracking for tasks * Adding validation for task dependencies * Implementing custom formatting for the extracted tasks Common Issues and Solutions --------------------------- * If tasks aren’t being properly identified, try adjusting the prompt to be more specific * If priorities aren’t being set correctly, consider adding examples in the prompt * For complex transcripts, you might need to adjust the model parameters for better results [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Retrieval-Augmented Generation (RAG) | Boundary Documentation RAG is a commonly used technique used to improve the quality of LLM-generated responses by grounding the model on external sources of knowledge. In this example, we’ll use BAML to manage the prompts for a RAG pipeline. ### Creating BAML functions The most common way to implement RAG is to use a vector store that contains embeddings of the data. First, let’s define our BAML model for RAG. #### BAML Code rag.baml | | | | --- | --- | | 1 | class Response { | | 2 | question string | | 3 | answer string | | 4 | } | | 5 | | | 6 | function RAG(question: string, context: string) -> Response { | | 7 | client "openai/gpt-5-mini" | | 8 | prompt #" | | 9 | Answer the question in full sentences using the provided context. | | 10 | Do not make up an answer. If the information is not provided in the context, say so clearly. | | 11 | | | 12 | QUESTION: {{ question }} | | 13 | RELEVANT CONTEXT: {{ context }} | | 14 | | | 15 | {{ ctx.output\_format }} | | 16 | | | 17 | RESPONSE: | | 18 | "# | | 19 | } | | 20 | | | 21 | test TestOne { | | 22 | functions \[RAG\] | | 23 | args { | | 24 | question "When was SpaceX founded?" | | 25 | context #" | | 26 | SpaceX is an American spacecraft manufacturer and space transportation company founded by Elon Musk in 2002. | | 27 | "# | | 28 | } | | 29 | } | | 30 | | | 31 | test TestTwo { | | 32 | functions \[RAG\] | | 33 | args { | | 34 | question "Where is Fiji located?" | | 35 | context #" | | 36 | Fiji is a country in the South Pacific known for its rugged landscapes, palm-lined beaches, and coral reefs with clear lagoons. | | 37 | "# | | 38 | } | | 39 | } | | 40 | | | 41 | test TestThree { | | 42 | functions \[RAG\] | | 43 | args { | | 44 | question "What is the primary product of BoundaryML?" | | 45 | context #" | | 46 | BoundaryML is the company that makes BAML, the best way to get structured outputs with LLMs. | | 47 | "# | | 48 | } | | 49 | } | | 50 | | | 51 | test TestMissingContext{ | | 52 | functions \[RAG\] | | 53 | args { | | 54 | question "Who founded SpaceX?" | | 55 | context #" | | 56 | BoundaryML is the company that makes BAML, the best way to get structured with LLMs. | | 57 | "# | | 58 | } | | 59 | } | Note how in the `TestMissingContext` test, the model correctly says that it doesn’t know the answer because it’s not provided in the context. The model doesn’t make up an answer, because of the way we’ve written the prompt. You can generate the BAML client code for this prompt by running `baml-cli generate`. ### Creating a VectorStore Next, let’s create our own minimal vector store and retriever using `scikit-learn`. #### Python Code rag.py | | | | --- | --- | | 1 | \# Install scikit-learn and use its TfidfVectorizer | | 2 | from sklearn.feature\_extraction.text import TfidfVectorizer | | 3 | from sklearn.metrics.pairwise import cosine\_similarity | | 4 | import numpy as np | | 5 | | | 6 | class VectorStore: | | 7 | """ | | 8 | Adapted from https://github.com/MadcowD/ell/blob/main/examples/rag/rag.py | | 9 | """ | | 10 | def \_\_init\_\_(self, vectorizer, tfidf\_matrix, documents): | | 11 | self.vectorizer = vectorizer | | 12 | self.tfidf\_matrix = tfidf\_matrix | | 13 | self.documents = documents | | 14 | | | 15 | @classmethod | | 16 | def from\_documents(cls, documents: list\[str\]) -> "VectorStore": | | 17 | vectorizer = TfidfVectorizer() | | 18 | tfidf\_matrix = vectorizer.fit\_transform(documents) | | 19 | return cls(vectorizer, tfidf\_matrix, documents) | | 20 | | | 21 | def retrieve\_with\_scores(self, query: str, k: int = 2) -> list\[dict\]: | | 22 | query\_vector = self.vectorizer.transform(\[query\]) | | 23 | similarities = cosine\_similarity(query\_vector, self.tfidf\_matrix).flatten() | | 24 | top\_k\_indices = np.argsort(similarities)\[-k:\]\[::-1\] | | 25 | return \[ |\ | 26 | {"document": self.documents\[i\], "relevance": float(similarities\[i\])} |\ | 27 | for i in top\_k\_indices |\ | 28 | \] | | 29 | | | 30 | def retrieve\_context(self, query: str, k: int = 2) -> str: | | 31 | documents = self.retrieve\_with\_scores(query, k) | | 32 | return "\\n".join(\[item\["document"\] for item in documents\]) | We can then build our RAG application in Python by calling the BAML client. rag.py | | | | --- | --- | | 1 | from baml\_client import b | | 2 | | | 3 | \# class VectorStore: | | 4 | \# ... | | 5 | | | 6 | if \_\_name\_\_ == "\_\_main\_\_": | | 7 | documents = \[ |\ | 8 | "SpaceX is an American spacecraft manufacturer and space transportation company founded by Elon Musk in 2002.", |\ | 9 | "Fiji is a country in the South Pacific known for its rugged landscapes, palm-lined beaches, and coral reefs with clear lagoons.", |\ | 10 | "Dunkirk is a 2017 war film depicting the Dunkirk evacuation of World War II, featuring intense aerial combat scenes with Spitfire aircraft.", |\ | 11 | "BoundaryML is the company that makes BAML, the best way to get structured outputs with LLMs." |\ | 12 | \] | | 13 | | | 14 | vector\_store = VectorStore.from\_documents(documents) | | 15 | | | 16 | questions = \[ |\ | 17 | "What is BAML?", |\ | 18 | "Which aircraft was featured in Dunkirk?", |\ | 19 | "When was SpaceX founded?", |\ | 20 | "Where is Fiji located?", |\ | 21 | "What is the capital of Fiji?" |\ | 22 | \] | | 23 | | | 24 | for question in questions: | | 25 | context = vector\_store.retrieve\_context(question) | | 26 | response = b.RAG(question, context) | | 27 | print(response) | | 28 | print("-" \* 10) | When you run the Python script, you should see output like the following: | | | --- | | question='What is BAML?' answer='BAML is a product made by BoundaryML, and it is described as the best way to get structured outputs with LLMs.' | | \---------- | | question='Which aircraft was featured in Dunkirk?' answer='The aircraft featured in Dunkirk were Spitfire aircraft.' | | \---------- | | question='When was SpaceX founded?' answer='SpaceX was founded in 2002.' | | \---------- | | question='Where is Fiji located?' answer='Fiji is located in the South Pacific.' | | \---------- | | question='What is the capital of Fiji?' answer='The information about the capital of Fiji is not provided in the context.' | | \---------- | Once again, in the last question, the model correctly says that it doesn’t know the answer because it’s not provided in the context. That’s it! You can now attempt such a RAG workflow with a vector database on a larger dataset. All you have to do is point BAML to the retriever class you’ve implemented. ### Creating Citations with LLM In this advanced section, we’ll explore how to enhance our RAG implementation to include citations for the generated responses. This is particularly useful when you need to track the source of information in the generated responses. First, let’s extend our BAML model to support citations. We’ll create a new response type and function that explicitly handles citations: rag.baml | | | | --- | --- | | 1 | class ResponseWithCitations { | | 2 | question string | | 3 | answer string | | 4 | citations string\[\] | | 5 | } | | 6 | | | 7 | function RAGWithCitations(question: string, context: string) -> ResponseWithCitations { | | 8 | client "openai/gpt-5-mini" | | 9 | prompt #" | | 10 | Answer the question in full sentences using the provided context. | | 11 | If the statement contains information from the context, put the exact cited quotes in complete sentences in the citations array. | | 12 | Do not make up an answer. If the information is not provided in the context, say so clearly. | | 13 | | | 14 | QUESTION: {{ question }} | | 15 | RELEVANT CONTEXT: {{ context }} | | 16 | {{ ctx.output\_format }} | | 17 | RESPONSE: | | 18 | "# | | 19 | } | Let’s add a test to verify our citation functionality: rag.baml | | | | --- | --- | | 1 | test TestCitations { | | 2 | functions \[RAGWithCitations\] | | 3 | args { | | 4 | question "What can you tell me about SpaceX and its founder?" | | 5 | context #" | | 6 | SpaceX is an American spacecraft manufacturer and space transportation company founded by Elon Musk in 2002. | | 7 | The company has developed several launch vehicles and spacecraft. | | 8 | Einstein was born on March 14, 1879. | | 9 | "# | | 10 | } | | 11 | } | This test will demonstrate how the model: 1. Provides relevant information about SpaceX and its founder 2. Includes the exact source quotes in the citations array 3. Only uses information that’s actually present in the context To use this enhanced RAG implementation in our Python code, we simply need to update our loop to use the new `RAGWithCitations` function: rag.py | | | | --- | --- | | 1 | for question in questions: | | 2 | context = vector\_store.retrieve\_context(question) | | 3 | response = b.RAGWithCitations(question, context) | | 4 | print(response) | | 5 | print("-" \* 10) | When you run this modified code, you’ll see responses that include both answers and their supporting citations. For example: | | | --- | | question='What is BAML?' answer='BAML is a product made by BoundaryML that provides the best way to get structured outputs with LLMs.' citations=\['BoundaryML is the company that makes BAML, the best way to get structured outputs with LLMs.'\] | | \---------- | | question='Which aircraft was featured in Dunkirk?' answer='The aircraft featured in Dunkirk were Spitfire aircraft.' citations=\['Dunkirk is a 2017 war film depicting the Dunkirk evacuation of World War II, featuring intense aerial combat scenes with Spitfire aircraft.'\] | | \---------- | | question='When was SpaceX founded?' answer='SpaceX was founded in 2002.' citations=\['SpaceX is an American spacecraft manufacturer and space transportation company founded by Elon Musk in 2002.'\] | | \---------- | | question='Where is Fiji located?' answer='Fiji is located in the South Pacific.' citations=\['Fiji is a country in the South Pacific.'\] | | \---------- | | question='What is the capital of Fiji?' answer='The capital of Fiji is not provided in the context.' citations=\[\] | | \---------- | Notice how each piece of information in the answer is backed by a specific citation from the source context. This makes the responses more transparent and verifiable, which is especially important in applications where the source of information matters. ### Using Pinecone as Vector Database Instead of using our custom vector store, we can use Pinecone, a production-ready vector database. Here’s how to implement the same RAG pipeline using Pinecone: First, install the required packages: | | | | --- | --- | | $ | pip install pinecone | Now, let’s modify our Python code to use Pinecone: rag\_pinecone.py | | | | --- | --- | | 1 | import pinecone as pc | | 2 | from sentence\_transformers import SentenceTransformer | | 3 | from pinecone import ServerlessSpec | | 4 | from baml\_client import b | | 5 | | | 6 | \# Initialize Pinecone | | 7 | pc = Pinecone(api\_key="YOUR\_API\_KEY") | | 8 | | | 9 | class PineconeStore: | | 10 | def \_\_init\_\_(self, index\_name: str): | | 11 | self.index\_name = index\_name | | 12 | self.encoder = SentenceTransformer('all-MiniLM-L6-v2') | | 13 | | | 14 | # Create index if it doesn't exist | | 15 | if index\_name not in pc.list\_indexes().names(): | | 16 | pc.create\_index( | | 17 | name=index\_name, | | 18 | dimension=self.encoder.get\_sentence\_embedding\_dimension(), | | 19 | metric='cosine', | | 20 | spec=ServerlessSpec( | | 21 | cloud='aws', | | 22 | region='us-east-1' | | 23 | ) | | 24 | ) | | 25 | self.index = pc.Index(index\_name) | | 26 | | | 27 | def add\_documents(self, documents: list\[str\], ids: list\[str\] = None): | | 28 | if ids is None: | | 29 | ids = \[str(i) for i in range(len(documents))\] | | 30 | | | 31 | # Create embeddings | | 32 | embeddings = self.encoder.encode(documents) | | 33 | | | 34 | # Create vector records | | 35 | vectors = \[(id, emb.tolist(), {"text": doc}) |\ | 36 | for id, emb, doc in zip(ids, embeddings, documents)\] | | 37 | | | 38 | # Upsert to Pinecone | | 39 | self.index.upsert(vectors=vectors) | | 40 | | | 41 | def retrieve\_context(self, query: str, k: int = 2) -> str: | | 42 | # Create query embedding | | 43 | query\_embedding = self.encoder.encode(query).tolist() | | 44 | | | 45 | # Query Pinecone | | 46 | results = self.index.query( | | 47 | vector=query\_embedding, | | 48 | top\_k=k, | | 49 | include\_metadata=True | | 50 | ) | | 51 | | | 52 | # Extract and join the document texts | | 53 | contexts = \[match.metadata\["text"\] for match in results.matches\] | | 54 | return "\\n".join(contexts) | | 55 | | | 56 | if \_\_name\_\_ == "\_\_main\_\_": | | 57 | # Initialize Pinecone store | | 58 | vector\_store = PineconeStore("baml-rag-demo") | | 59 | | | 60 | # Sample documents (same as before) | | 61 | documents = \[ |\ | 62 | "SpaceX is an American spacecraft manufacturer and space transportation company founded by Elon Musk in 2002.", |\ | 63 | "Fiji is a country in the South Pacific known for its rugged landscapes, palm-lined beaches, and coral reefs with clear lagoons.", |\ | 64 | "Dunkirk is a 2017 war film depicting the Dunkirk evacuation of World War II, featuring intense aerial combat scenes with Spitfire aircraft.", |\ | 65 | "BoundaryML is the company that makes BAML, the best way to get structured outputs with LLMs." |\ | 66 | \] | | 67 | | | 68 | # Add documents to Pinecone | | 69 | vector\_store.add\_documents(documents) | | 70 | | | 71 | # Test questions (same as before) | | 72 | questions = \[ |\ | 73 | "What is BAML?", |\ | 74 | "Which aircraft was featured in Dunkirk?", |\ | 75 | "When was SpaceX founded?", |\ | 76 | "Where is Fiji located?", |\ | 77 | "What is the capital of Fiji?" |\ | 78 | \] | | 79 | | | 80 | # Query using the same BAML functions | | 81 | for question in questions: | | 82 | context = vector\_store.retrieve\_context(question) | | 83 | response = b.RAGWithCitations(question, context) | | 84 | print(response) | | 85 | print("-" \* 10) | The key differences when using Pinecone are: 1. Documents are stored in Pinecone’s serverless infrastructure on AWS instead of in memory 2. We can persist our vector database across sessions Here is a snapshot of the entriies in our Pinecone database console: ![](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Fguide%2Fpinecone-rag-example.png&w=1200&q=75) Note that you’ll need to: 1. [Create a Pinecone account](https://www.pinecone.io/) 2. Get your API key from the Pinecone console 3. Replace `YOUR_API_KEY` with your actual Pinecone credentials 4. Make sure you have access to the serverless offering in your Pinecone account The BAML functions (`RAG` and `RAGWithCitations`) remain exactly the same, demonstrating how BAML cleanly separates the prompt engineering from the implementation details of your vector database. When you run this code, you’ll get the same type of responses as before, but now you’re using a production-ready serverless vector database that can scale automatically based on your usage. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Token Optimization | Boundary Documentation Experimenting with Data Format for Token Efficiency =================================================== When working with LLMs, token usage directly impacts both cost and latency. Different serialization formats can affect how many tokens are used to represent your data—but **the optimal format depends on your specific use case and LLM**. Important: Test Before Adopting ------------------------------- **Every optimization has trade-offs.** Reducing token count doesn’t automatically improve accuracy, and different LLMs may respond differently to different formats. You should: * **Test with your actual data and prompts** * **Measure accuracy alongside token savings** * **Compare multiple formats** (JSON, YAML, TOON, or custom) * **Validate with your specific LLM** What works for one use case may not work for another. Available Format Options ------------------------ BAML’s `format` filter lets you experiment with different serializations: | | | | --- | --- | | 1 | {{ data\|format(type="json") }} {# Standard JSON #} | | 2 | {{ data\|format(type="yaml") }} {# YAML format #} | | 3 | {{ data\|format(type="toon") }} {# TOON format #} | ### TOON Format TOON (Token-Oriented Object Notation) is a compact format that uses: * Indentation-based structure (like YAML) * Tabular format for arrays of objects (declare keys once, stream rows) * Minimal punctuation * Explicit array lengths and field headers (LLM-friendly guardrails) **What TOON is good for:** * Uniform arrays of objects with many similar items * Data that’s already highly structured and tabular * When LLM validation of structure matters (explicit lengths help) **When TOON may NOT help:** * Deeply nested or non-uniform structures (JSON-compact often uses fewer tokens) * Semi-uniform arrays (~40-60% tabular eligibility) where savings diminish * Pure flat tables (CSV is more compact) * Latency-critical applications (benchmark on your setup - some models process compact JSON faster despite higher token count) Learn more: [TOON specification and benchmarks](https://github.com/toon-format/toon) Understanding Data Structure ---------------------------- ### Tabular Eligibility TOON’s efficiency comes from its tabular format for arrays. Your data’s “tabular eligibility” affects how much TOON can help: * **High eligibility (80-100%)**: Mostly uniform arrays of objects with the same fields → TOON excels * **Medium eligibility (40-60%)**: Mix of uniform and non-uniform data → savings diminish, may not be worth it * **Low eligibility (0-20%)**: Deeply nested, varied structures → JSON-compact may use fewer tokens **Example - High eligibility:** | | | | --- | --- | | 1 | { "users": \[ |\ | 2 | {"id": 1, "name": "Alice", "role": "admin"}, |\ | 3 | {"id": 2, "name": "Bob", "role": "user"} |\ | 4 | \]} | All users have identical fields → 100% tabular → TOON helps **Example - Low eligibility:** | | | | --- | --- | | 1 | { "config": { | | 2 | "server": { "host": "localhost", "port": 8080 }, | | 3 | "database": { "name": "prod", "pool": { "min": 5, "max": 20 }} | | 4 | }} | Deeply nested with no arrays of uniform objects → 0% tabular → JSON-compact likely better Considerations for Format Selection ----------------------------------- ### When to Experiment with Compact Formats * Passing large datasets with high tabular eligibility * Token costs are significant * After you’ve validated accuracy with standard formats ### When to Stick with Standard Formats * Starting a new project (establish baseline first) * Your LLM performs poorly with alternative formats * Data structure is very small or deeply nested * Team familiarity matters more than token cost Experimentation Example ----------------------- Here’s how you might test different formats for a product analysis task: ### Baseline: Using JSON | | | | --- | --- | | 1 | class Product { | | 2 | id int | | 3 | name string | | 4 | price float | | 5 | in\_stock bool | | 6 | } | | 7 | | | 8 | function AnalyzeProducts(products: Product\[\]) -> string { | | 9 | client GPT4 | | 10 | prompt #" | | 11 | Analyze these products and provide insights: | | 12 | | | 13 | {{ products }} | | 14 | | | 15 | Focus on pricing trends and inventory status. | | 16 | "# | | 17 | } | When you pass products to this function, they’re serialized as JSON: | | | | --- | --- | | 1 | \[ |\ | 2 | { "id": 1, "name": "Widget", "price": 9.99, "in\_stock": true }, |\ | 3 | { "id": 2, "name": "Gadget", "price": 19.99, "in\_stock": false } |\ | 4 | \] | ### Experiment: Trying TOON To test if TOON works for your use case, try the `format(type="toon")` filter: | | | | --- | --- | | 1 | function AnalyzeProducts(products: Product\[\]) -> string { | | 2 | client GPT4 | | 3 | prompt #" | | 4 | Analyze these products and provide insights: | | 5 | | | 6 | {{ products\|format(type="toon") }} | | 7 | | | 8 | Focus on pricing trends and inventory status. | | 9 | "# | | 10 | } | The same data serialized as TOON: | | | --- | | \[2\]{id,name,price,in\_stock}: | | 1,Widget,9.99,true | | 2,Gadget,19.99,false | **Next steps:** Test with your actual prompts and measure both token usage and accuracy. TOON Options ------------ ### Custom Indentation Control spacing for better readability: | | | | --- | --- | | 1 | {{ products\|format(type="toon", indent=4) }} | ### Alternative Delimiters Choose the delimiter that works best for your data: | | | | --- | --- | | 1 | {# Comma-separated (default) #} | | 2 | {{ products\|format(type="toon", delimiter="comma") }} | | 3 | | | 4 | {# Tab-separated #} | | 5 | {{ products\|format(type="toon", delimiter="tab") }} | | 6 | | | 7 | {# Pipe-separated #} | | 8 | {{ products\|format(type="toon", delimiter="pipe") }} | **Delimiter trade-offs:** * **Tab (`\t`)**: Often tokenizes more efficiently than commas; tabs rarely appear in data (less quote-escaping needed); but some editors/terminals may display tabs inconsistently * **Pipe (`|`)**: Middle ground between comma and tab; explicit visual separator * **Comma (default)**: Most familiar, but may require more quoting if your data contains commas Test different delimiters with your actual data - the best choice depends on your content. ### Length Markers Add length indicators for clarity: | | | | --- | --- | | 1 | {{ products\|format(type="toon", length\_marker="#") }} | Output: | | | --- | | #2\[2\]{id,name,price,in\_stock}: | | 1,Widget,9.99,true | | 2,Gadget,19.99,false | Real-World Use Case: Transaction Analysis ----------------------------------------- Here’s a complete example analyzing financial transactions: | | | | --- | --- | | 1 | class Transaction { | | 2 | id string | | 3 | date string | | 4 | amount float | | 5 | category string | | 6 | merchant string | | 7 | status string | | 8 | } | | 9 | | | 10 | function AnalyzeTransactions( | | 11 | transactions: Transaction\[\], | | 12 | question: string | | 13 | ) -> string { | | 14 | client GPT4 | | 15 | prompt #" | | 16 | {{ \_.role("system") }} | | 17 | You are a financial analyst. Answer questions about transaction data. | | 18 | | | 19 | {{ \_.role("user") }} | | 20 | Transaction data: | | 21 | {{ transactions\|format(type="toon", delimiter="pipe") }} | | 22 | | | 23 | Question: {{ question }} | | 24 | "# | | 25 | } | | 26 | | | 27 | test AnalyzeSpending { | | 28 | functions \[AnalyzeTransactions\] | | 29 | args { | | 30 | transactions \[ |\ | 31 | { |\ | 32 | id: "tx\_001", |\ | 33 | date: "2025-01-15", |\ | 34 | amount: 45.99, |\ | 35 | category: "Dining", |\ | 36 | merchant: "Coffee Shop", |\ | 37 | status: "completed" |\ | 38 | }, |\ | 39 | { |\ | 40 | id: "tx\_002", |\ | 41 | date: "2025-01-16", |\ | 42 | amount: 120.00, |\ | 43 | category: "Shopping", |\ | 44 | merchant: "Electronics Store", |\ | 45 | status: "completed" |\ | 46 | } |\ | 47 | \] | | 48 | question "What's my largest expense category this week?" | | 49 | } | | 50 | } | Understanding Trade-offs ------------------------ Token reduction is only valuable if accuracy and reliability are maintained. Consider: ### What You Might Gain * Lower token costs per API call * Ability to fit more data in context windows * Validation benefits (TOON’s explicit array lengths can help LLMs detect truncated data) ### What You Might Lose * LLM comprehension (benchmark results show format performance varies by model and dataset type) * Latency (some models may process compact JSON faster despite higher token count - measure TTFT and total time) * Debugging ease (non-standard formats are harder to inspect) * Team velocity (custom formats require explanation and documentation) * Accuracy (format changes can affect model output quality) ### Real Benchmark Insights According to [TOON’s benchmarks](https://github.com/toon-format/toon) : * **TOON excels** with uniform employee records, e-commerce orders, GitHub repo lists * **JSON-compact wins** on semi-uniform event logs, some deeply nested configs * **Model-dependent**: GPT-5-nano showed 90.9% accuracy with both TOON and JSON-compact, while Claude Haiku showed 59.8% (TOON) vs 57.4% (JSON) * **Structure matters**: Tabular eligibility strongly predicts which format will be more efficient **Critical:** Lost accuracy, increased debugging time, or degraded user experience typically cost far more than token savings. Always measure end-to-end impact on your specific workload, not just token counts. Experimentation Guidelines -------------------------- ### 1\. Start with a Baseline Always establish a baseline with a standard format first: | | | | --- | --- | | 1 | function AnalyzeData(data: Dataset\[\]) -> Analysis { | | 2 | client GPT4 | | 3 | prompt #" | | 4 | {{ \_.role("user") }} | | 5 | Data: | | 6 | {{ data\|format(type="json") }} // Start with JSON baseline | | 7 | | | 8 | Provide analysis. | | 9 | "# | | 10 | } | **Measure:** Accuracy, token usage, latency, cost ### 2\. Test Alternative Formats Try different formats and compare results: | | | | --- | --- | | 1 | {# Experiment 1: YAML #} | | 2 | {{ data\|format(type="yaml") }} | | 3 | | | 4 | {# Experiment 2: TOON #} | | 5 | {{ data\|format(type="toon") }} | | 6 | | | 7 | {# Experiment 3: TOON with options #} | | 8 | {{ data\|format(type="toon", delimiter="pipe") }} | **Measure:** Do you maintain accuracy? How much do tokens reduce? ### 3\. Consider Your Data Structure Different formats work better for different structures. From TOON benchmarks: | | | | --- | --- | | 1 | {# High tabular eligibility: uniform arrays #} | | 2 | {{ products\|format(type="toon") }} // Try TOON | | 3 | {{ products\|format(type="json") }} // Compare vs JSON | | 4 | | | 5 | {# Low tabular eligibility: deeply nested config #} | | 6 | {{ config\|format(type="json") }} // JSON-compact often better | | 7 | {{ config\|format(type="yaml") }} // Or try YAML | | 8 | | | 9 | {# Medium eligibility: mixed structures #} | | 10 | {{ events\|format(type="json") }} // Test multiple formats | | 11 | {{ events\|format(type="toon") }} // Results vary | **Key insight:** For pure flat tables, CSV is more compact than TOON. For deeply nested data, compact JSON may win. TOON’s sweet spot is uniform arrays of objects with multiple fields. ### 4\. Test with Your LLM Different models may respond differently to format changes. Test with the specific LLM you’re using. **Tip from TOON documentation:** When using TOON, show the format instead of describing it. Models parse the structure naturally from examples - the indentation and headers are usually self-documenting. How to Measure Impact --------------------- ### Using BAML Playground 1. Write your function with your baseline format (usually JSON) 2. Run it in the playground and record: * Actual token count (shown in playground) * LLM response quality and accuracy * Time to first token (TTFT) and total latency * Any parsing errors * Response consistency across multiple runs 3. Change to an alternative format 4. Compare ALL metrics: tokens, accuracy, latency, error rates 5. Run multiple test cases with diverse inputs 6. Verify edge cases and error scenarios **Important:** Lower token count doesn’t guarantee lower latency. Some models may process familiar formats (like JSON) faster even if they use more tokens. Measure end-to-end response time. ### In Production * Use [BAML Studio](https://docs.boundaryml.com/guide/boundary-cloud/observability/tracking-usage) to monitor token usage AND accuracy * Track accuracy metrics alongside token/cost metrics * A/B test formats if possible (measure both cost and quality) * Monitor latency - cheaper formats that are slower may not be worth it * Be ready to roll back quickly if quality or performance degrades Next Steps ---------- * **Don’t assume, test:** Try different formats with your actual data * **Measure what matters:** Track accuracy, not just token counts * **Start small:** Test on non-critical workloads first * **Document results:** Note which formats work best for which use cases * **Consider alternatives:** Custom serialization, selective fields, or prompt redesign might also help See Also -------- * [Jinja Filters Reference](https://docs.boundaryml.com/ref/prompt-syntax/jinja-filters) - Complete filter documentation * [BAML Studio](https://docs.boundaryml.com/guide/boundary-cloud/observability/tracking-usage) - Monitor token usage in production * [Prompt Caching](https://docs.boundaryml.com/guide/baml-advanced/prompt-caching-message-role-metadata) - Additional cost optimization [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Chain-of-Thought Prompting | Boundary Documentation Chain-of-thought prompting is a technique that encourages the language model to think step by step, reasoning through the problem before providing an answer. This can improve the quality of the response and make it easier to understand. ![Chain-of-Thought Prompting](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Fguide%2Fcot.png&w=1920&q=75) Chain-of-Thought Prompting [Wei et al. (2022)](https://arxiv.org/abs/2201.11903) There are a few different ways to implement chain-of-thought prompting, especially for structured outputs. 1. Require the model to reason before outputting the structured object. * Bonus: Use a `template_string` to embed the reasoning into multiple functions. 2. Require the model to **flexibly** reason before outputting the structured object. 3. Embed reasoning in the structured object. 4. Ask the model to embed reasoning as comments in the structured object. Let’s look at an example of each of these. We recommend [Technique 2](https://docs.boundaryml.com/examples/prompt-engineering/chain-of-thought#technique-2-allowing-for-flexible-reasoning) for most use cases. But each technique has its own trade-offs, so please try them out and see which one works best for your use case. Since BAML leverages [Schema-Aligned Parsing (SAP)](https://www.boundaryml.com/blog/schema-aligned-parsing) instead of JSON.parse or LLM modification (like constrained generation or structured outputs), we can do all of the above techniques with any language model! Technique 1: Reasoning before outputting the structured object -------------------------------------------------------------- In the below example, we use chain of thought prompting to extract information from an email. | | | | --- | --- | | 1 | function GetOrderInfo(email: Email) -> OrderInfo { | | 2 | client "openai/gpt-5-mini" | | 3 | prompt #" | | 4 | extract everything from this email. | | 5 | | | 6 | | | 7 | {{ ctx.output\_format }} | | 8 | | | 9 | Before you answer, please explain your reasoning step-by-step. | | 10 | | | 11 | For example: | | 12 | If we think step by step we can see that ... | | 13 | | | 14 | Therefore the output is: | | 15 | { | | 16 | ... // schema | | 17 | } | | 18 | | | 19 | {{ \_.role('user') }} | | 20 | | | 21 | Sender: {{email.from\_address}} | | 22 | Email Subject: {{email.subject}} | | 23 | Email Body: {{email.body}} | | 24 | "# | | 25 | } | | 26 | | | 27 | class Email { | | 28 | subject string | | 29 | body string | | 30 | from\_address string | | 31 | } | | 32 | | | 33 | | | 34 | class OrderInfo { | | 35 | order\_status "ORDERED" \| "SHIPPED" \| "DELIVERED" \| "CANCELLED" | | 36 | tracking\_number string? | | 37 | estimated\_arrival\_date string? | | 38 | } | | 39 | | | 40 | test Test1 { | | 41 | functions \[GetOrderInfo\] | | 42 | args { | | 43 | email { | | 44 | from\_address "hello@amazon.com" | | 45 | subject "Your Amazon.com order of 'Wood Dowel Rods...' has shipped!" | | 46 | body #" | | 47 | Hi Sam, your package will arrive: | | 48 | Thurs, April 4 | | 49 | Track your package: | | 50 | www.amazon.com/gp/your-account/ship-track?ie=23&orderId123 | | 51 | | | 52 | On the way: | | 53 | Wood Dowel Rods... | | 54 | Order #113-7540940 | | 55 | Ship to: | | 56 | Sam | | 57 | SEATTLE, WA | | 58 | | | 59 | Shipment total: | | 60 | $0.00 | | 61 | "# | | 62 | | | 63 | } | | 64 | } | | 65 | } | ### Reusable Chain-of-Thought Snippets You may want to reuse the same technique for multiple functions. Consider [template\_string](https://docs.boundaryml.com/ref/baml/template-string) ! | | | | --- | --- | | 1 | template\_string ChainOfThought(action: string?) #" | | 2 | Before you answer, please explain your reasoning step-by-step. | | 3 | {% if action %}{{ action }}{% endif %} | | 4 | | | 5 | For example: | | 6 | If we think step by step we can see that ... | | 7 | | | 8 | Therefore the output is: | | 9 | { | | 10 | ... // schema | | 11 | } | | 12 | "# | | 13 | | | 14 | function GetOrderInfo(email: Email) -> OrderInfo { | | 15 | client "openai/gpt-" | | 16 | prompt #" | | 17 | Extract everything from this email. | | 18 | | | 19 | {{ ctx.output\_format }} | | 20 | | | 21 | {{ ChainOfThought("focus on things related to shipping") }} | | 22 | | | 23 | {{ \_.role('user') }} | | 24 | | | 25 | Sender: {{email.from\_address}} | | 26 | Email Subject: {{email.subject}} | | 27 | Email Body: {{email.body}} | | 28 | "# | | 29 | } | Technique 2: Allowing for flexible reasoning -------------------------------------------- This is one we recommend for most use cases. | | | | --- | --- | | 1 | function GetOrderInfo(email: Email) -> OrderInfo { | | 2 | client "openai/gpt-" | | 3 | prompt #" | | 4 | extract everything from this email. | | 5 | | | 6 | | | 7 | {{ ctx.output\_format }} | | 8 | | | 9 | Outline some relevant information before you answer. | | 10 | Example: | | 11 | - ... | | 12 | - ... | | 13 | ... | | 14 | { | | 15 | ... // schema | | 16 | } | | 17 | | | 18 | {{ \_.role('user') }} | | 19 | | | 20 | Sender: {{email.from\_address}} | | 21 | Email Subject: {{email.subject}} | | 22 | Email Body: {{email.body}} | | 23 | "# | | 24 | } | The benefit of using `- ...` is that we allow the model to know it needs to output some information, but we don’t limit it to a specific format or inject any bias by adding example text that may not be relevant. Similarly, we use `...` after two `- ...` to indicate that we don’t mean to limit the number of items to 2. ###### Reuseable snippet | | | | --- | --- | | 1 | template\_string ChainOfThought() #" | | 2 | Outline some relevant information before you answer. | | 3 | Example: | | 4 | - ... | | 5 | - ... | | 6 | ... | | 7 | { | | 8 | ... // schema | | 9 | } | | 10 | "# | | 11 | | | 12 | function GetOrderInfo(email: Email) -> OrderInfo { | | 13 | client "openai/gpt-" | | 14 | prompt #" | | 15 | extract everything from this email. | | 16 | | | 17 | {{ ctx.output\_format }} | | 18 | | | 19 | {{ ChainOfThought() }} | | 20 | | | 21 | {{ \_.role('user') }} | | 22 | | | 23 | Sender: {{email.from\_address}} | | 24 | Email Subject: {{email.subject}} | | 25 | Email Body: {{email.body}} | | 26 | "# | | 27 | } | Technique 3: Embed reasoning in the structured object ----------------------------------------------------- | | | | --- | --- | | 1 | class OrderInfo { | | 2 | clues string\[\] @description(#" | | 3 | relevant quotes from the email related to shipping | | 4 | "#) | | 5 | order\_status "ORDERED" \| "SHIPPED" \| "DELIVERED" \| "CANCELLED" | | 6 | tracking\_number string? | | 7 | estimated\_arrival\_date string? | | 8 | } | | 9 | | | 10 | function GetOrderInfo(email: Email) -> OrderInfo { | | 11 | client "openai/gpt-" | | 12 | prompt #" | | 13 | extract everything from this email. | | 14 | | | 15 | {{ ctx.output\_format }} | | 16 | | | 17 | {{ \_.role('user') }} | | 18 | | | 19 | Sender: {{email.from\_address}} | | 20 | Email Subject: {{email.subject}} | | 21 | Email Body: {{email.body}} | | 22 | "# | | 23 | } | Technique 4: Ask the model to embed reasoning as comments in the structured object ---------------------------------------------------------------------------------- | | | | --- | --- | | 1 | class OrderInfo { | | 2 | order\_status "ORDERED" \| "SHIPPED" \| "DELIVERED" \| "CANCELLED" | | 3 | @description(#" | | 4 | before fields, in comments list out any relevant clues from the email | | 5 | "#) | | 6 | tracking\_number string? | | 7 | estimated\_arrival\_date string? | | 8 | } | | 9 | | | 10 | function GetOrderInfo(email: Email) -> OrderInfo { | | 11 | client "openai/gpt-" | | 12 | prompt #" | | 13 | extract everything from this email. | | 14 | | | 15 | {{ ctx.output\_format }} | | 16 | | | 17 | {{ \_.role('user') }} | | 18 | | | 19 | Sender: {{email.from\_address}} | | 20 | Email Subject: {{email.subject}} | | 21 | Email Body: {{email.body}} | | 22 | "# | | 23 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # PII Data Extraction / Scrubbing | Boundary Documentation In this tutorial, you’ll learn how to create a robust PII (Personally Identifiable Information) data extraction and scrubbing system using BAML and GPT-4. By the end, you’ll have a working system that can identify, extract, and scrub various types of PII from text documents. Prerequisites ------------- * Basic understanding of BAML syntax * Access to OpenAI API (you’ll need an API key) Step 1: Define the Data Schema ------------------------------ First, let’s define what our PII data structure should look like. Create a new file called `pii_extractor.baml` and add the following schema: pii\_extractor.baml | | | | --- | --- | | 1 | class PIIData { | | 2 | index int | | 3 | dataType string | | 4 | value string | | 5 | } | | 6 | | | 7 | class PIIExtraction { | | 8 | privateData PIIData\[\] | | 9 | containsSensitivePII bool @description("E.g. SSN") | | 10 | } | This schema defines: * `PIIData`: A class representing a single piece of PII with its type and value * `PIIExtraction`: A container class that holds an array of PII data items and a sensitive data flag Step 2: Create the Extraction Function -------------------------------------- Next, let’s create the function that uses GPT-4 to extract PII. Add this to your `pii_extractor.baml` file: pii\_extractor.baml | | | | --- | --- | | 1 | function ExtractPII(document: string) -> PIIExtraction { | | 2 | client "openai/gpt-5-mini" | | 3 | prompt #" | | 4 | Extract all personally identifiable information (PII) from the given document. Look for items like: | | 5 | - Names | | 6 | - Email addresses | | 7 | - Phone numbers | | 8 | - Addresses | | 9 | - Social security numbers | | 10 | - Dates of birth | | 11 | - Any other personal data | | 12 | | | 13 | {{ ctx.output\_format }} | | 14 | | | 15 | {{ \_.role("user") }} | | 16 | | | 17 | {{ document }} | | 18 | "# | | 19 | } | Let’s break down what this function does: * Takes a `document` input as a string * Uses the `gpt-5-mini` model * Provides clear guidelines for PII extraction in the prompt * Returns a `PIIExtraction` object containing all found PII data Step 3: Test the Extractor -------------------------- To ensure our PII extractor works correctly, let’s add some test cases: pii\_extractor.baml | | | | --- | --- | | 1 | test BasicPIIExtraction { | | 2 | functions \[ExtractPII\] | | 3 | args { | | 4 | document #" | | 5 | John Doe was born on 01/02/1980. | | 6 | His email is john.doe@email.com and phone is 555-123-4567. | | 7 | He lives at 123 Main St, Springfield, IL 62704. | | 8 | "# | | 9 | } | | 10 | } | | 11 | | | 12 | test EmptyDocument { | | 13 | functions \[ExtractPII\] | | 14 | args { | | 15 | document "This document contains no PII data." | | 16 | } | | 17 | } | This is what it looks like in BAML playground after running the test: ![](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Fguide%2Fpii-scrubber.png&w=3840&q=75) You can try playing with the functions and tests online at [https://www.promptfiddle.com/Pii-data-O4PmJ](https://www.promptfiddle.com/Pii-data-O4PmJ) Step 4: Implementing PII Extraction and Scrubbing ------------------------------------------------- Now you can use the PII extractor to both identify and scrub sensitive information from your documents: pii\_scrubber.py | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_client.types import PIIExtraction | | 3 | from typing import Dict, Tuple | | 4 | | | 5 | def scrub\_document(text: str) -> Tuple\[str, Dict\[str, str\]\]: | | 6 | # Extract PII from the document | | 7 | result = b.ExtractPII(text) | | 8 | | | 9 | # Create a mapping of real values to scrubbed placeholders | | 10 | scrubbed\_text = text | | 11 | pii\_mapping = {} | | 12 | | | 13 | # Process each PII item and replace with a placeholder | | 14 | for pii\_item in result.privateData: | | 15 | pii\_type = pii\_item.dataType.upper() | | 16 | placeholder = f"\[{pii\_type}\_{pii\_item.index}\]" | | 17 | | | 18 | # Store the mapping for reference | | 19 | pii\_mapping\[placeholder\] = pii\_item.value | | 20 | | | 21 | # Replace the PII with the placeholder | | 22 | scrubbed\_text = scrubbed\_text.replace(pii\_item.value, placeholder) | | 23 | | | 24 | return scrubbed\_text, pii\_mapping | | 25 | | | 26 | def restore\_document(scrubbed\_text: str, pii\_mapping: Dict\[str, str\]) -> str: | | 27 | """Restore the original text using the PII mapping.""" | | 28 | restored\_text = scrubbed\_text | | 29 | for placeholder, original\_value in pii\_mapping.items(): | | 30 | restored\_text = restored\_text.replace(placeholder, original\_value) | | 31 | return restored\_text | | 32 | | | 33 | \# Example usage | | 34 | document = """ | | 35 | John Smith works at Tech Corp. | | 36 | You can reach him at john.smith@techcorp.com | | 37 | or call 555-0123 during business hours. | | 38 | His employee ID is TC-12345. | | 39 | """ | | 40 | | | 41 | \# Scrub the document | | 42 | scrubbed\_text, pii\_mapping = scrub\_document(document) | | 43 | | | 44 | print("Original Document:") | | 45 | print(document) | | 46 | print("\\nScrubbed Document:") | | 47 | print(scrubbed\_text) | | 48 | print("\\nPII Mapping:") | | 49 | for placeholder, original in pii\_mapping.items(): | | 50 | print(f"{placeholder}: {original}") | | 51 | | | 52 | \# If needed, restore the original document | | 53 | restored\_text = restore\_document(scrubbed\_text, pii\_mapping) | | 54 | print("\\nRestored Document:") | | 55 | print(restored\_text) | This implementation provides several key features: 1. **PII Detection**: Uses BAML’s ExtractPII function to identify PII 2. **Data Scrubbing**: Replaces PII with descriptive placeholders 3. **Mapping Preservation**: Maintains a mapping of placeholders to original values 4. **Restoration Capability**: Allows restoration of the original text when needed Example output: | | | | --- | --- | | 1 | Original Document: | | 2 | | | 3 | John Smith works at Tech Corp. | | 4 | You can reach him at john.smith@techcorp.com | | 5 | or call 555-0123 during business hours. | | 6 | His employee ID is TC-12345. | | 7 | | | 8 | | | 9 | Scrubbed Document: | | 10 | | | 11 | \[NAME\_1\] works at Tech Corp. | | 12 | You can reach him at \[EMAIL\_2\] | | 13 | or call \[PHONE\_3\] during business hours. | | 14 | His employee ID is \[EMPLOYEE ID\_4\]. | | 15 | | | 16 | | | 17 | PII Mapping: | | 18 | \[NAME\_1\]: John Smith | | 19 | \[EMAIL\_2\]: john.smith@techcorp.com | | 20 | \[PHONE\_3\]: 555-0123 | | 21 | \[EMPLOYEE ID\_4\]: TC-12345 | | 22 | | | 23 | Restored Document: | | 24 | | | 25 | John Smith works at Tech Corp. | | 26 | You can reach him at john.smith@techcorp.com | | 27 | or call 555-0123 during business hours. | | 28 | His employee ID is TC-12345. | Next Steps ---------- Now that you have a working PII extractor, you can: * Add more specific PII types to look for * Implement validation for extracted PII (e.g., email format checking) * Create a more sophisticated prompt to handle edge cases * Add error handling for malformed documents * Integrate with your data privacy compliance system Enhanced Security: Using Local Models ------------------------------------- For organizations handling sensitive data, using cloud-based LLMs like OpenAI’s GPT models might not be suitable due to data privacy concerns. BAML supports using local models, which keeps all PII processing within your infrastructure. In this example, we’re going to use a Ollama model. For more details on how to use Ollama with BAML, check out [this page](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic-ollama) . 1. First, define your local model client in `pii_extractor.baml`: | | | | --- | --- | | 1 | // Please ensure you've got ollama set up with llama:3.1 installed | | 2 | // | | 3 | // ollama pull llama:3.1 | | 4 | // ollama run llama:3.1 | | 5 | client SecureLocalLLM { | | 6 | provider "openai-generic" | | 7 | options { | | 8 | base\_url "http://localhost:11434/v1" | | 9 | model "llama3.1:latest" | | 10 | temperature 0 | | 11 | default\_role "user" | | 12 | } | | 13 | } | 2. Update the ExtractPII function to use your local model: | | | | --- | --- | | 1 | function ExtractPII(document: string) -> PIIExtraction { | | 2 | // use a local model instead of openai | | 3 | client SecureLocalLLM | | 4 | prompt #" | | 5 | Extract all personally identifiable information (PII) from the given document. Look for items like: | | 6 | - Names | | 7 | - Email addresses | | 8 | - Phone numbers | | 9 | - Addresses | | 10 | - Social security numbers | | 11 | - Dates of birth | | 12 | - Any other personal data | | 13 | | | 14 | {{ ctx.output\_format }} | | 15 | | | 16 | {{ \_.role("user") }} | | 17 | | | 18 | {{ document }} | | 19 | "# | | 20 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Tools / Function Calling | Boundary Documentation “Function calling” is a technique for getting an LLM to choose a function to call for you. The way it works is: 1. You define a task with certain function(s) 2. Ask the LLM to **choose which function to call** 3. **Get the function parameters from the LLM** for the appropriate function it choose 4. **Call the functions** in your code with those parameters It’s common for people to think of “function calling” or “tool use” separately from “structured outputs” (even OpenAI has separate parameters for them), but at BAML, we think it’s simpler and more impactful to think of them equivalently. This is because, at the end of the day, you are looking to get something processable back from your LLM. Whether it’s extracting data from a document or calling the Weather API, you need a standard representation of that output, which is where BAML lives. ![Tool-Calling](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Fguide%2Ftool-calling.png&w=3840&q=75) Baml Control Flow In BAML, you can get represent a `tool` or a `function` you want to call as a BAML `class`, and make the function output be that class definition. BAML | | | | --- | --- | | 1 | class WeatherAPI { | | 2 | // we can use literals to denote the name of the tool | | 3 | // the field can be named anything we want! "api\_name" "tool" "function\_name" | | 4 | // whatever you feel the LLM would understand best | | 5 | api\_name "weather\_request" | | 6 | city string @description("the user's city") | | 7 | timeOfDay string @description("As an ISO8601 timestamp") | | 8 | } | | 9 | | | 10 | function UseTool(user\_message: string) -> WeatherAPI { | | 11 | client "openai/gpt-5-mini" | | 12 | prompt #" | | 13 | Given a message, extract info. | | 14 | {# special macro to print the functions return type. #} | | 15 | {{ ctx.output\_format }} | | 16 | | | 17 | {{ \_.role('user') }} | | 18 | {{ user\_message }} | | 19 | "# | | 20 | } | Call the function like this: PythonTypeScriptGoRuby | | | | --- | --- | | 1 | import asyncio | | 2 | import datetime | | 3 | from baml\_client import b | | 4 | from baml\_client.types import WeatherAPI | | 5 | | | 6 | def get\_weather(city: str, time\_of\_day: datetime.date): | | 7 | ... | | 8 | | | 9 | def main(): | | 10 | weather\_info = b.UseTool("What's the weather like in San Francisco?") | | 11 | print(weather\_info) | | 12 | assert isinstance(weather\_info, WeatherAPI) | | 13 | print(f"City: {weather\_info.city}") | | 14 | print(f"Time of Day: {weather\_info.time\_of\_day}") | | 15 | weather = get\_weather(city=weather\_info.city, time\_of\_day=weather\_info.timeOfDay) | | 16 | | | 17 | if \_\_name\_\_ == '\_\_main\_\_': | | 18 | main() | Choosing multiple Tools ----------------------- To choose ONE tool out of many, you can use a union: BAML | | | | --- | --- | | 1 | function UseTool(user\_message: string) -> WeatherAPI \| MyOtherAPI { | | 2 | .... // same thing | | 3 | } | If you use [VSCode Playground](https://docs.boundaryml.com/guide/installation-editors/vs-code-extension) , you can see what we inject into the prompt, with full transparency. Call the function like this: PythonTypeScriptGoRuby | | | | --- | --- | | 1 | import asyncio | | 2 | from baml\_client import b | | 3 | from baml\_client.types import WeatherAPI, MyOtherAPI | | 4 | | | 5 | async def main(): | | 6 | tool = b.UseTool("What's the weather like in San Francisco?") | | 7 | print(tool) | | 8 | | | 9 | if isinstance(tool, WeatherAPI): | | 10 | print(f"Weather API called:") | | 11 | print(f"City: {tool.city}") | | 12 | print(f"Time of Day: {tool.timeOfDay}") | | 13 | elif isinstance(tool, MyOtherAPI): | | 14 | print(f"MyOtherAPI called:") | | 15 | # Handle MyOtherAPI specific attributes here | | 16 | | | 17 | if \_\_name\_\_ == '\_\_main\_\_': | | 18 | main() | Choosing N Tools ---------------- To choose many tools, you can use a union of a list: BAML | | | | --- | --- | | 1 | function UseTool(user\_message: string) -> (WeatherAPI \| MyOtherAPI)\[\] { | | 2 | client "openai/gpt-5-mini" | | 3 | prompt #" | | 4 | Given a message, extract info. | | 5 | {# special macro to print the functions return type. #} | | 6 | {{ ctx.output\_format }} | | 7 | | | 8 | {{ \_.role('user') }} | | 9 | {{ user\_message }} | | 10 | "# | | 11 | } | Call the function like this: PythonTypeScriptGoRuby | | | | --- | --- | | 1 | import asyncio | | 2 | from baml\_client import b | | 3 | from baml\_client.types import WeatherAPI, MyOtherAPI | | 4 | | | 5 | async def main(): | | 6 | tools = b.UseTool("What's the weather like in San Francisco and New York?") | | 7 | print(tools) | | 8 | | | 9 | for tool in tools: | | 10 | if isinstance(tool, WeatherAPI): | | 11 | print(f"Weather API called:") | | 12 | print(f"City: {tool.city}") | | 13 | print(f"Time of Day: {tool.timeOfDay}") | | 14 | elif isinstance(tool, MyOtherAPI): | | 15 | print(f"MyOtherAPI called:") | | 16 | # Handle MyOtherAPI specific attributes here | | 17 | | | 18 | if \_\_name\_\_ == '\_\_main\_\_': | | 19 | main() | Disambiguating Between Similar Tools ------------------------------------ When building functions that can call multiple tools (represented as BAML classes), you might encounter situations where different tools accept arguments with the same name. For instance, consider `GetWeather` and `GetTimezone` classes, both taking a `city: string` argument. How does the system determine whether a user query like “What’s the time in London?” corresponds to `GetTimezone` or potentially `GetWeather`? You can use string literals to solve this problem: BAML | | | | --- | --- | | 1 | class GetWeather { | | 2 | tool\_name "get\_weather" @description("Use this tool to get the current weather forecast for a specific city.") | | 3 | city string @description("The city for which to get the weather.") | | 4 | } | | 5 | | | 6 | class GetTimezone { | | 7 | tool\_name "get\_timezone" @description("Use this tool to find the current timezone of a specific city.") | | 8 | city string @description("The city for which to find the timezone.") | | 9 | } | | 10 | | | 11 | function ChooseTool(query: string) -> GetWeather \| GetTimezone { | | 12 | client "openai/gpt-5" | | 13 | prompt #" | | 14 | Given the user query, determine the primary intent and select the appropriate tool to call. | | 15 | | | 16 | {# special macro to add tool structures + descriptions here #} | | 17 | {{ ctx.output\_format }} | | 18 | | | 19 | {{ \_.role('user') }} | | 20 | {{ query }} | | 21 | "# | | 22 | } | Dynamically Generate the tool signature --------------------------------------- It might be cumbersome to define schemas in baml and code, so you can define them from code as well. Read more about dynamic types [here](https://docs.boundaryml.com/guide/baml-advanced/dynamic-runtime-types) BAML | | | | --- | --- | | 1 | class WeatherAPI { | | 2 | @@dynamic // params defined from code | | 3 | } | | 4 | | | 5 | function UseTool(user\_message: string) -> WeatherAPI { | | 6 | client "openai/gpt-5-mini" | | 7 | prompt #" | | 8 | Given a message, extract info. | | 9 | {# special macro to print the functions return type. #} | | 10 | {{ ctx.output\_format }} | | 11 | | | 12 | {{ \_.role('user') }} | | 13 | {{ user\_message }} | | 14 | "# | | 15 | } | Call the function like this: Python | | | | --- | --- | | 1 | import asyncio | | 2 | import inspect | | 3 | | | 4 | from baml\_client import b | | 5 | from baml\_client.type\_builder import TypeBuilder | | 6 | from baml\_client.types import WeatherAPI | | 7 | | | 8 | async def get\_weather(city: str, time\_of\_day: str): | | 9 | print(f"Getting weather for {city} at {time\_of\_day}") | | 10 | return 42 | | 11 | | | 12 | async def main(): | | 13 | tb = TypeBuilder() | | 14 | type\_map = {int: tb.int(), float: tb.float(), str: tb.string()} | | 15 | signature = inspect.signature(get\_weather) | | 16 | for param\_name, param in signature.parameters.items(): | | 17 | tb.WeatherAPI.add\_property(param\_name, type\_map\[param.annotation\]) | | 18 | tool = b.UseTool("What's the weather like in San Francisco this afternoon?", { "tb": tb }) | | 19 | print(tool) | | 20 | weather = await get\_weather(\*\*tool.model\_dump()) | | 21 | print(weather) | | 22 | | | 23 | if \_\_name\_\_ == '\_\_main\_\_': | | 24 | asyncio.run(main()) | Note that the above approach is not fully generic. Recommended you read: [Dynamic JSON Schema](https://www.boundaryml.com/blog/dynamic-json-schemas) Function-calling APIs vs Prompting ---------------------------------- Injecting your function schemas into the prompt, as BAML does, outperforms function-calling across all benchmarks for major providers ([see our Berkeley FC Benchmark results with BAML](https://www.boundaryml.com/blog/sota-function-calling?q=0) ). Amongst other limitations, function-calling APIs will at times: 1. Return a schema when you don’t want any (you want an error) 2. Not work for tools with more than 100 parameters. 3. Use [many more tokens than prompting](https://www.boundaryml.com/blog/type-definition-prompting-baml) . Keep in mind that “JSON mode” is nearly the same thing as “prompting”, but it enforces the LLM response is ONLY a JSON blob. BAML does not use JSON mode since it allows developers to use better prompting techniques like chain-of-thought, to allow the LLM to express its reasoning before printing out the actual schema. BAML’s parser can find the json schema(s) out of free-form text for you. Read more about different approaches to structured generation [here](https://www.boundaryml.com/blog/schema-aligned-parsing) BAML will still support native function-calling APIs in the future (please let us know more about your use-case so we can prioritize accordingly) Create an Agent that utilizes these Tools ----------------------------------------- We can create an Agent or an “agentic loop” that continuously uses tools in a program simply by adding a while loop in our code. In this example, we’ll have two tools: 1. An API that queries the weather. 2. An API that does basic calculations on numbers. This is what it looks in the BAML file: tools.baml | | | | --- | --- | | 1 | class WeatherAPI { | | 2 | intent "weather\_request" | | 3 | city string | | 4 | time string @description("Current time in ISO8601 format") | | 5 | } | | 6 | | | 7 | class CalculatorAPI { | | 8 | intent "basic\_calculator" | | 9 | operation "add" \| "subtract" \| "multiply" \| "divide" | | 10 | numbers float\[\] | | 11 | } | | 12 | | | 13 | function SelectTool(message: string) -> WeatherAPI \| CalculatorAPI { | | 14 | client "openai/gpt-5" | | 15 | prompt #" | | 16 | Given a message, extract info. | | 17 | | | 18 | {{ ctx.output\_format }} | | 19 | | | 20 | {{ \_.role("user") }} {{ message }} | | 21 | "# | | 22 | } | In our agent code, we’ll: 1. Implement our APIs 2. Implement our Agent that continuously will use different tools toolAgent.pytoolAgent.tstoolAgent.go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_client.types import WeatherAPI, CalculatorAPI | | 3 | | | 4 | def handle\_weather(weather: WeatherAPI): | | 5 | # Simulate weather API call, but you can implement this with a real API call | | 6 | return f"The weather in {weather.city} at {weather.time} is sunny." | | 7 | | | 8 | def handle\_calculator(calc: CalculatorAPI): | | 9 | numbers = calc.numbers | | 10 | if calc.operation == "add": | | 11 | result = sum(numbers) | | 12 | elif calc.operation == "subtract": | | 13 | result = numbers\[0\] - sum(numbers\[1:\]) | | 14 | elif calc.operation == "multiply": | | 15 | result = 1 | | 16 | for n in numbers: | | 17 | result \*= n | | 18 | elif calc.operation == "divide": | | 19 | result = numbers\[0\] | | 20 | for n in numbers\[1:\]: | | 21 | result /= n | | 22 | return f"The result is {result}" | | 23 | | | 24 | def main(): | | 25 | print("Agent started! Type 'exit' to quit.") | | 26 | | | 27 | while True: | | 28 | # Get user input | | 29 | user\_input = input("You: ") | | 30 | if user\_input.lower() == 'exit': | | 31 | break | | 32 | | | 33 | # Call the BAML function to select tool | | 34 | tool\_response = b.SelectTool(user\_input) | | 35 | | | 36 | # Handle the tool response | | 37 | if isinstance(tool\_response, WeatherAPI): | | 38 | result = handle\_weather(tool\_response) | | 39 | print(f"Agent (Weather): {result}") | | 40 | | | 41 | elif isinstance(tool\_response, CalculatorAPI): | | 42 | result = handle\_calculator(tool\_response) | | 43 | print(f"Agent (Calculator): {result}") | | 44 | | | 45 | if \_\_name\_\_ == "\_\_main\_\_": | | 46 | main() | We can test this by asking things like: 1. What is the weather in Seattle? 2. What’s 5+2? This is the output: | | | | --- | --- | | 1 | Agent started! Type 'exit' to quit. | | 2 | You: What's the weather in Seattle | | 3 | Agent (Weather): The weather in Seattle at 2023-10-02T12:00:00Z is sunny. | | 4 | You: What's 5+2 | | 5 | Agent (Calculator): The result is 7.0 | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Changelog | Boundary Documentation All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines. [0.219.0](https://github.com/boundaryml/baml/compare/0.218.1..0.219.0) - 2026-02-12 ------------------------------------------------------------------------------------ ### Bug Fixes * allow ‘baml-cli serv’ to handle big PDFs (#3046) - ([8cb8016](https://github.com/boundaryml/baml/commit/8cb8016413de3c14955b990b1556225831c654f1) ) - Sam Lijin * fix vercel build, show last known prompt if there’s errors (#3077) * fix template\_string rendering in test data (#3091) * Add cancel\_notify support and test for Ctrl+C in test executor (#3074) - ([065e40c](https://github.com/boundaryml/baml/commit/065e40cfe618664594f3cb2e35ed33e661096242) ) - hellovai * Add build\_request to CFFI, Go runtime/codegen, and Rust codegen (#3089) - ([a6c3995](https://github.com/boundaryml/baml/commit/a6c3995598bebc534a23f3bc326410b563cb9514) ) - hellovai * Lint jinja templates in baml\_language (#3086) - ([0728974](https://github.com/boundaryml/baml/commit/07289746eacc1571cdf905d6c849f27aa6b3d1a6) ) - Greg Hale * Bump version to 0.219.0 - ([8fe1083](https://github.com/boundaryml/baml/commit/8fe10832b61de002293efec577a514ffe5ff7be3) ) - Aaron Villalpando [0.218.1](https://github.com/boundaryml/baml/compare/0.218.0..0.218.1) - 2026-01-27 ------------------------------------------------------------------------------------ ### Bug Fixes * Fix streaming retries not working (#3025) - ([149a9ae](https://github.com/boundaryml/baml/commit/149a9ae5748664659888b4d2d53c3eb8df7c33d3) ) - Antonio Sarosi * **(zed)** get zed extension working again (#3024) - ([95934b7](https://github.com/boundaryml/baml/commit/95934b793455983e5e7d77a2c1d17ef6d5943906) ) - Sam Lijin * proxy toggling error message (#3026) - ([cc2a120](https://github.com/boundaryml/baml/commit/cc2a12044eadb561b15dfca1d6f48d4d66ec5e20) ) - Sam Lijin * make HMR test pass (#3029) - ([03e95d2](https://github.com/boundaryml/baml/commit/03e95d2de94640c55d34a1debdcaa1ffedf63319) ) - Sam Lijin * fix issue with vscode ‘unspecified error’ where CORS proxy wasnt enabled (#3034) * Fix Vertex AI credential parsing for double-quoted JSON (#3028) - ([68f4ad6](https://github.com/boundaryml/baml/commit/68f4ad6918c1d68c739718bb5940349575c73bd3) ) - Dave Laird ### Features * support —turbo build for Next.js (#2422) - ([9ef044b](https://github.com/boundaryml/baml/commit/9ef044b6bf8d2414ce959f28865732bd8f444549) ) - Chris Watts [0.218.0](https://github.com/boundaryml/baml/compare/0.217.0..0.218.0) - 2026-01-22 ------------------------------------------------------------------------------------ ### Bug Fixes * Fix Go serde decoding for dynamic types (#2978) - ([f3e48fd](https://github.com/boundaryml/baml/commit/f3e48fdc3f5f686b10ba6fa2638495ca7539fcee) ) - hellovai * Fix Go codegen for pure-dynamic classes (@@dynamic with no static fields) (#2995) - ([dcc2323](https://github.com/boundaryml/baml/commit/dcc2323639ac5b5ad777dd935f2527a3b6b97b41) ) - hellovai * **(cffi)** wrap result and error callbacks in block\_in\_place (#2989) - ([c31ae86](https://github.com/boundaryml/baml/commit/c31ae8666c3d1a4e26d046cd6aa5b58ffc37ca18) ) - Tsvetomir Bonev * **(go)** handle optional image encoding (\*types.Image) (#2996) - ([d3d76dc](https://github.com/boundaryml/baml/commit/d3d76dc7634472d3673ea88a3913b938c7ea99d0) ) - hellovai * **(react)** use NDJSON format for streaming to handle TCP chunk boundaries (#3000) - ([d4edca7](https://github.com/boundaryml/baml/commit/d4edca77c6bf7e9f2e7d898082adc4093ced7e01) ) - Antonio Sarosi * **(ts)** add BamlError base class and improve error hierarchy (#2993) (#3012) - ([807e702](https://github.com/boundaryml/baml/commit/807e702e8dfd8caff3acd23e4865e2b7701ced5d) ) - Antonio Sarosi * fix playground index on test history (#3005) * Fix API key dialog not showing for new users (#2999) - ([6cb3b60](https://github.com/boundaryml/baml/commit/6cb3b60efe8eb2b2fcb7a37cdf9e0a479ad41b42) ) - Paulo Rossi Rodrigues ### Documentation * Azure AI Foundary -> Foundry typo (#2965) - ([48da42a](https://github.com/boundaryml/baml/commit/48da42ae4ce611df50c38e541a8bd56025b9f014) ) - Sam Lijin [0.217.0](https://github.com/boundaryml/baml/compare/0.216.0..0.217.0) - 2026-01-10 ------------------------------------------------------------------------------------ ### Bug Fixes * **(zed)** Fix version (#2953) - ([a9c4d7b](https://github.com/boundaryml/baml/commit/a9c4d7b14fd8024a373c58768f4eb943ec662838) ) - Sam Lijin * fix TimeoutError and InvalidArgumentError getting raised as BamlError (#2954) ### Features * Add native Rust SDK (#2832) - ([0b4d81a](https://github.com/boundaryml/baml/commit/0b4d81a3861efe49fc41d58c7464c6ae7388ce8c) ) - hellovai * wire @description to pydantic models Field attribute (#2955) - ([ff4970a](https://github.com/boundaryml/baml/commit/ff4970ac911243ef0f8e314d1c5103391c39d278) ) - Sam Lijin ### Bugs * Fix media type matching in unions to use file extension heuristics (#2894) - ([cad717c](https://github.com/boundaryml/baml/commit/cad717cf310678fdad8dea38b708262211c764f6) ) - Antonio Sarosi * \[Studio\] Dont resend the prompt and raw output via BamlValidationError published events (#2914) - ([85a3b35](https://github.com/boundaryml/baml/commit/85a3b35a0ea99980ac0fc2d29b2a1b616bfb9a41) ) - aaronvg * add abort error details (#2921) - ([9172fbc](https://github.com/boundaryml/baml/commit/9172fbcea6405917fd751f519366ffd180d673c1) ) - aaronvg * Fix backwards type checking in Jinja filter validation (#2942) - ([e903222](https://github.com/boundaryml/baml/commit/e903222a92d5993af33e02fa41b518a50b94b4ab) ) - Kelvin * Add on\_tick callback tests and fix CFFI streaming callback handling (#2949) - ([db206db](https://github.com/boundaryml/baml/commit/db206dbb192bd1061438835173f2795a39c67de7) ) - hellovai * Fix @skip attribute panic with @@dynamic and non-dynamic classes (#2952) - ([ae13652](https://github.com/boundaryml/baml/commit/ae136524eff94bb364c0086e89569e3c47bc2e5d) ) - Antonio Sarosi [0.216.0](https://github.com/boundaryml/baml/compare/0.215.2..0.216.0) - 2025-12-31 ------------------------------------------------------------------------------------ ### Bug Fixes * **(aws-bedrock)** Pass region to DefaultCredentialsChain for IRSA support (#2856) - ([30ff957](https://github.com/boundaryml/baml/commit/30ff9577f52f69bc3861f8bdb0cf57180d94352e) ) - Benjamin Poile * Fix PDF viewer CSS preload bug (#2876) - ([fb0257b](https://github.com/boundaryml/baml/commit/fb0257bdf9ec0900be9f131a83d2e05d63c33458) ) - Antonio Sarosi * Fix issue where a request would timeout if there was no finish reason payload (#2881) - ([629c14e](https://github.com/boundaryml/baml/commit/629c14e88171f89240713598a156f0a7712d6b6f) ) - aaronvg * Typescript x86 alpine fix (#2887) - ([5c2c6d8](https://github.com/boundaryml/baml/commit/5c2c6d844aa8a4623601dd60c829b608ede771fe) ) - aaronvg * Fix Typescript arm64 linux issue with vertex credentials parsing (#2892) - ([6a97b69](https://github.com/boundaryml/baml/commit/6a97b69c489053ab0fe5ba84115063d31bd0a0cf) ) - aaronvg ### Features * **(codegen)** add `client` option to BamlCallOptions (#2870) - ([3aa56df](https://github.com/boundaryml/baml/commit/3aa56df16e0f68cba1bcc76ff8cb9a43491e29d1) ) - hellovai ### Docs * Documentation seniority format correction (#2857) - ([3bebb8c](https://github.com/boundaryml/baml/commit/3bebb8cdce0fa7efcf0e69ac3ca995615496de5b) ) - hellovai * Clarify how `ClientRegistry.set_primary` works in the docs (#2875) - ([4afec32](https://github.com/boundaryml/baml/commit/4afec32b95cf8c13ae1f895d64465a8ce3ef7a26) ) - Antonio Sarosi [0.215.2](https://github.com/boundaryml/baml/compare/0.215.1..0.215.2) - 2025-12-22 ------------------------------------------------------------------------------------ ### Features * added openrouter first-class support and updated fern docs (#2861) - ([f6de38e](https://github.com/boundaryml/baml/commit/f6de38e6fe29272cfc863d6466d38c086d93fcd5) ) - Paulo Rossi Rodrigues ### Fixes * 0.215.1 release automation broke [0.215.1](https://github.com/boundaryml/baml/compare/0.215.0..0.215.1) - 2025-12-20 ------------------------------------------------------------------------------------ WARNING: this release is incomplete. Release automation was broken for 0.215.1 and not all artifacts were correctly uploaded. ### Bug Fixes * Vertex ai model error (#2836) - ([8482c1d](https://github.com/boundaryml/baml/commit/8482c1d06135b35cbaf3715e7dec5e4a841c3d52) ) - aaronvg ### Miscellaneous Chores * fix win arm64 ts release (#2841) - ([19e7dd6](https://github.com/boundaryml/baml/commit/19e7dd662821635e2a182c8219ef8db13ece4c47) ) - Sam Lijin * fix jetbrains release for 2025.2+ (#2842) - ([1252528](https://github.com/boundaryml/baml/commit/12525286db748432b5b887567050ec118f55ad85) ) - Sam Lijin * make npm releases work with OIDC auth (#2843) - ([20d7bb1](https://github.com/boundaryml/baml/commit/20d7bb15c94548c82b769e1d52dd60b48e810246) ) - Sam Lijin [0.215.0](https://github.com/boundaryml/baml/compare/0.214.0..0.215.0) - 2025-12-18 ------------------------------------------------------------------------------------ ### Bug Fixes * golang type system fixes, CFFI refactor, and testing infrastructure (#2778) - ([1afa7e8](https://github.com/boundaryml/baml/commit/1afa7e8dea1d693034a2e54f239c9378f8e091d1) ) - hellovai * fix index bug (#2742) `merge_messages` previously used `foo.len() - 1`. Since `len` is a `USIZE` (unsigned int), size 0 was wrapping after decrement, cau - ([518dc61](https://github.com/boundaryml/baml/commit/518dc610525c8fb0633fa9f63e5c8e27b6e7a78c) ) - Greg Hale * undocumented null return for OpenAI reasoning content (#2803) - ([0012eb1](https://github.com/boundaryml/baml/commit/0012eb1a7515fc23fe7b7011060738bfaaa7c8df) ) - Patrick Wadström * fix variable shadowing bug in generated python/TS clients (#2810) - ([5ae0010](https://github.com/boundaryml/baml/commit/5ae001011559bc29997f6dd04cbbbf65d970b12d) ) - Antonio Sarosi * Fix `baml-cli test` panic when `BOUNDARY_API_KEY` is set (#2779) - ([220ad19](https://github.com/boundaryml/baml/commit/220ad1901fecab2fbe90d92e2306a42c6a10bb62) ) - Antonio Sarosi * Fix some docs about SSE chunks, anthropic not having SSE events in streams, adding comments in prmopt strings with command + / (#2802) - ([c17c93d](https://github.com/boundaryml/baml/commit/c17c93dbeabc3a61bd3de5a101d7f1b04df89fdb) ) - aaronvg ### Features * ts: add windows arm64 support; target glibc 2.17 on linux arm64 (#2771) - ([23f367f](https://github.com/boundaryml/baml/commit/23f367f23c7538ab73284df9e2d6bda744c2c3c4) ) - Sam Lijin * allow users to optimize BAML startup/footprint by trimming tests from inlined baml files (#2772) - ([fe72ecd](https://github.com/boundaryml/baml/commit/fe72ecd83639c36e2054569b0a2fba786948677e) ) - Greg Hale * add option to output\_format for quoting class keys in prompts (#2769) - ([969da89](https://github.com/boundaryml/baml/commit/969da89d38093afffd0abe8d30f14b70b70b9a32) ) - Greg Hale * Add search functionality to prompt (#2804) - ([4f7a46b](https://github.com/boundaryml/baml/commit/4f7a46bda53de992b6d3959779bf497e47f09e83) ) - aaronvg * Prompt optimization visualizer (#2807) - ([9d1bf87](https://github.com/boundaryml/baml/commit/9d1bf8734887c8c0bdd6f501498bd56a6229e8c7) ) - Greg Hale * parser performance improvements (#2806) - ([f44cd28](https://github.com/boundaryml/baml/commit/f44cd289e9347dd77bc06562af7e2ef4139689fa) ) - aaronvg ### Docs * how-to integrate with Microsoft Foundry (#2745) - ([83c85b4](https://github.com/boundaryml/baml/commit/83c85b46c9a8241b97e0f803845fa7ae94d3d5ac) ) - aaronvg * Document baml-cffi docker build caching (#2756) - ([fb4d00c](https://github.com/boundaryml/baml/commit/fb4d00c006f61d37e9f81938d91e79eb181a51d4) ) - hellovai * Add project URLs to Pypi (#2712) - ([9e8d731](https://github.com/boundaryml/baml/commit/9e8d731efcdeac2c43cb09ba7f8188812d7c9936) ) - Toundra * Fix react chatbot documentation and implementation (#2770) - ([d1f1842](https://github.com/boundaryml/baml/commit/d1f184291938cdadccccbc6eae649c41c1938de1) ) - hellovai * update prompt caching docs example as caching is now GA for Anthropic (#2790) - ([1811be6](https://github.com/boundaryml/baml/commit/1811be6a771752b8287eae0836dfa98a13ef9c7a) ) - Sanjan Das * Symbol tuning documentation clarification (#2808) - ([46cda11](https://github.com/boundaryml/baml/commit/46cda11033a1e9cc56a209952268176b8bc2b97c) ) - hellovai * optimization docs (#2809) - ([d2971b7](https://github.com/boundaryml/baml/commit/d2971b7f257ecb9c5bcdac64a76e230965fdf119) ) - Greg Hale * Prompt optimization documentation update (#2821) - ([eb82648](https://github.com/boundaryml/baml/commit/eb82648a1095a719d9c3df14ed257e0573badedc) ) - hellovai ### Miscellaneous Chores * switch npm publishing to use OIDC (#2829) - ([c439d98](https://github.com/boundaryml/baml/commit/c439d98fa734b587cc3790cf6da293e7925fe708) ) - mendral-app\[bot\] * Simplify how docs are generated. Only changes to fern/\*\* or typescript/sage\*/\* should trigger it. (#2757) - ([d1f3e3a](https://github.com/boundaryml/baml/commit/d1f3e3a1da475ae5c21e3f1f6ef37320ec7af1e4) ) - hellovai * Remove support for deprecated piece of syntax (#2744) - ([6992bd1](https://github.com/boundaryml/baml/commit/6992bd1d1f8f9e2dfbb07a2d088958b6153b6193) ) - Greg Hale * fix zed release workflow (#2816) - ([6df303c](https://github.com/boundaryml/baml/commit/6df303c4415be283ce3b2611b45e114c6e7c280d) ) - Sam Lijin * Fix setup-tools action with directory existence checks (#2741) - ([70f77c7](https://github.com/boundaryml/baml/commit/70f77c71235898c9b393b66e7b0f464049b2135d) ) - mendral-app\[bot\] * Upgrade all setup-node usages to Node.js v6 (#2785) - ([8c8eea5](https://github.com/boundaryml/baml/commit/8c8eea56790b3b15df4603fae52edd78d86794f2) ) - mendral-app\[bot\] * Update react in fiddle apps (#2788) - ([e250a9b](https://github.com/boundaryml/baml/commit/e250a9b15ddd4f5db2db25d0892b5a5089ef34b4) ) - aaronvg * update next (#2793) - ([3ff97b2](https://github.com/boundaryml/baml/commit/3ff97b2080a9f8d2d55331dd181b83b434ee85d9) ) - aaronvg * Patch React CVE (#2801) - ([a3934b9](https://github.com/boundaryml/baml/commit/a3934b9347be689f1542431e3e8418a92764099e) ) - aaronvg [0.214.0](https://github.com/boundaryml/baml/compare/0.213.0..0.214.0) - 2025-11-24 ------------------------------------------------------------------------------------ ### Bug Fixes * Reduce logging in playground to prevent freezes - ([43960d4](https://github.com/boundaryml/baml/commit/43960d472466bd0ae16c73af222043f9424ed63b) ) - Aaron Villalpando * fix ask baaaml (#2711)- ([ef62656](https://github.com/boundaryml/baml/commit/ef6265649d8ab593527d9d7646c5c2eb41fd83fc) ) - Greg Hale ### Documentation * documentation fixups (#2735) * Fixing doc - invalid options for gpt-4.1 model (#2708) - ([5d45cc9](https://github.com/boundaryml/baml/commit/5d45cc9dccbf334062e60fedde140d8e69c75bd9) ) - yasonk * Add docs for OpenAI region selection via base\_url * Fix docs for media constructor functions * Add example code and description for `media_url_handler` - ([386a5d9](https://github.com/boundaryml/baml/commit/386a5d915c6ff2c5e15f36aa76a2f9396b85a799) ) - Greg Hale ### Features * **(baml)** implement static control flow visualizer (#2716) - ([4c9d507](https://github.com/boundaryml/baml/commit/4c9d50795563748952263a1ce4423f62460e2923) ) - Sam Lijin * **(cli)** load dotenv in baml-cli dev and baml-cli serve (#2703) - ([e6fff13](https://github.com/boundaryml/baml/commit/e6fff13b7a7685e987c4a68a626984b7495ece33) ) - Sam Lijin * **(cli)** hide internal subcommands by default (#2704) - ([a61d28c](https://github.com/boundaryml/baml/commit/a61d28c7b2e06059875605c3ea30d37aad17a7a2) ) - Sam Lijin * **(engine)** Compress serialized logs for boundary studio (#2729) - ([d75255a](https://github.com/boundaryml/baml/commit/d75255a2212c6662f2512a69e4ad132ebfeff020) ) - hellovai * Add toon Jinja filter for token-efficient data serialization (#2720) - ([c2f31a4](https://github.com/boundaryml/baml/commit/c2f31a4c1d2264c9caca610a5f326dc3e547f8d1) ) - hellovai ### Miscellaneous Chores * fix zed release infra (#2705) - ([8aae697](https://github.com/boundaryml/baml/commit/8aae69735617fd9d95e95fe8e543671358d8eb68) ) - Sam Lijin [0.213.0](https://github.com/boundaryml/baml/compare/0.212.0..0.213.0) - 2025-11-05 ------------------------------------------------------------------------------------ ### Bug Fixes * fix bug in baml-cli init not working with claude code (#2697) ([0333467](https://github.com/boundaryml/baml/commit/03334676728ba27704a4e53be062807fb39b2854) ) - aaronvg * select earliest successful LLM call by lexicographic request\_id order (#2692) - ([516ef6f](https://github.com/boundaryml/baml/commit/516ef6f76f97774734f4d0a86fc33aae01fa550d) ) - Shawn McDonald * default request timeout is too low (#2698) - ([50c7026](https://github.com/boundaryml/baml/commit/50c7026dc338dedd3b64d3d03129493d40099259) ) - aaronvg * Fix timeout exceptions for streaming LLM calls (#2699) - ([2b751db](https://github.com/boundaryml/baml/commit/2b751db4f97e15dc7afa6b5670b0e4b380eece2c) ) - Greg Hale * \[Python\] expose BamlAbortError (#2674) - ([1b6efb3](https://github.com/boundaryml/baml/commit/1b6efb3931cd9d5b68de4949f8fff16e3d007a40) ) - hellovai ### Features * expose better error messages out of the runtime so folks can better understand isseus (i/e can plumb cancel messages more correctly) (#2679) - ([af2d872](https://github.com/boundaryml/baml/commit/af2d872cd93ccd4123a79fdcef61a4f5e9989172) ) - hellovai * bedrock video support (#2681) - ([38cfe9b](https://github.com/boundaryml/baml/commit/38cfe9b2eb9196c90558e4461947d270e894f2e0) ) - Sam Lijin ### Miscellaneous Chores * add apache-2 license to engine/zed (#2670) - ([c1ec923](https://github.com/boundaryml/baml/commit/c1ec923b9be2e1f3ac2b3dddb7f7c0acc27d5132) ) - Sam Lijin [0.212.0](https://github.com/boundaryml/baml/compare/0.211.2..0.212.0) - 2025-10-27 ------------------------------------------------------------------------------------ ### Bug Fixes * Fix issue where a test would stay stuck in running if there was a wasm panic (#2601) - ([ac0ede8](https://github.com/boundaryml/baml/commit/ac0ede85306c6dada5423faeb651aa0288497410) ) - aaronvg * Move class descriptions inside braces for better formatting (#2646) - ([71cc0fa](https://github.com/boundaryml/baml/commit/71cc0fa7c7db0f9243dc248ac847835652f44c57) ) - hellovai * fix literal return values (#2663) * actually emit the version when opening baml file to make LSP switch versions (#2612) - ([700bd39](https://github.com/boundaryml/baml/commit/700bd39b22c7265905b8385e09fed595a9735e19) ) - aaronvg Fixes several typechecker subsumption bugs - ([716b7b1](https://github.com/boundaryml/baml/commit/716b7b120e91c9735bdd68bc7a6580318c3d7000) ) - Greg Hale ### Features * Configurable timeouts (#2628) - ([276f878](https://github.com/boundaryml/baml/commit/276f878e9517037580ca5b6a9306a2189295795d) ) - Greg Hale * Add configurable media URL resolution via media\_url\_resolver (#2578) - ([8530e7f](https://github.com/boundaryml/baml/commit/8530e7fb39cfe36647bf7a61ccaee0591e4efb28) ) - hellovai * Add Windows support for Go BAML client (#2619) - ([5430aa6](https://github.com/boundaryml/baml/commit/5430aa61c22727a6f43d392e30fd9e75d905c18c) ) - hellovai * Add placeholder API keys for new VSCode playground users (#2640) - ([cc995c2](https://github.com/boundaryml/baml/commit/cc995c21a903dab74581efee8ee78976a13e287d) ) - hellovai * Add block-level @@description for BAML classes (#2643) - ([bbe489a](https://github.com/boundaryml/baml/commit/bbe489a7623c31077320e9fa5d4c54d8e1b803e9) ) - hellovai * Add type narrowing for instanceof checks in BAML (#2656) - ([46c3266](https://github.com/boundaryml/baml/commit/46c32663fe42d40ef96402b298b2f05c75c696fc) ) - hellovai ### Miscellaneous Chores * **(zed)** get zed release working again (#2625) - ([5be2647](https://github.com/boundaryml/baml/commit/5be2647c08782d1e411a56aa22b675dee4d89568) ) - Sam Lijin * set up sync path for engine/zed to zed-industries/extensions (#2626) - ([8f85ba7](https://github.com/boundaryml/baml/commit/8f85ba70c001196e01c6c683dbe247119113e132) ) - Sam Lijin * ban println to prevent lsp crashes, since it uses stdio to communicate (#2659) - ([7f9e749](https://github.com/boundaryml/baml/commit/7f9e749f7f990a8f49b9ffd8e78f175ee834b5e5) ) - aaronvg * Evaluation tests suite (#2660) - ([ce250d4](https://github.com/boundaryml/baml/commit/ce250d468cf2eadb023293412d887318f471e138) ) - Greg Hale * Bump version to 0.212.0 - ([d6975ea](https://github.com/boundaryml/baml/commit/d6975eafdf74fec1de68ce9e1813a95a9607ed5c) ) - Aaron Villalpando [0.211.2](https://github.com/boundaryml/baml/compare/0.211.1..0.211.2) - 2025-10-12 ------------------------------------------------------------------------------------ ### Bug Fixes * Fix emit ts codegen bug (#2603) - ([39b1cf6](https://github.com/boundaryml/baml/commit/39b1cf6299b5080234e282367fdec238864c9df4) ) - Greg Hale [0.211.1](https://github.com/boundaryml/baml/compare/0.211.0..0.211.1) - 2025-10-10 ------------------------------------------------------------------------------------ ### Docs * fix TypeScript tool call example (#2550) - ([73bc201](https://github.com/boundaryml/baml/commit/73bc201230fddc410ddcf9547b41d11039eebce1) ) - Eric Winer * Fix variable name of LLM response in modular-api.mdx docs (#2579) - ([8074499](https://github.com/boundaryml/baml/commit/8074499cc1413e36d37318f00936d4997922b06e) ) - Caio Lang ### Features * added endpoint\_url to amazon bedrock (#2555) - ([10fd013](https://github.com/boundaryml/baml/commit/10fd0132bbac6a57f1b9540ac38262286356a744) ) - Roey Ben Chaim [0.211.0](https://github.com/boundaryml/baml/compare/0.210.0..0.211.0) - 2025-10-07 ------------------------------------------------------------------------------------ ### Bug Fixes * **(compiler)** duplicate diagnostics when typechecking (#2535) - ([5a8de50](https://github.com/boundaryml/baml/commit/5a8de50aaf42dc9cdac77e02374c8ad1396b3765) ) - José Rafael Oses * Properly leave the secondary screen after non-erroring baml-cli init (#2565) - ([b911a19](https://github.com/boundaryml/baml/commit/b911a1927046b7a36d43fdaee1b25ebbfbc37f31) ) - Greg Hale * Fix json parser in cases where it would output intermediate representations (#2572) - ([c1a0b0e](https://github.com/boundaryml/baml/commit/c1a0b0e15fa36745a4a59d6a322f182cef034a6e) ) - aaronvg * **(python)** export set\_log\_max\_message\_length config for baml logs (#2553) - ([2c689dc](https://github.com/boundaryml/baml/commit/2c689dc3341b1f8ef4030b397b5e93f46cb25b2e) ) - Samuel Lijin * Add specific error for missing required env vars in clients (#2570) - ([5ea6adb](https://github.com/boundaryml/baml/commit/5ea6adb02f6e4246dd53cd626189ec1578d69b69) ) - Antonio Sarosi * \[Promptfiddle\] fix play button disappearing (#2571) - ([7d31c37](https://github.com/boundaryml/baml/commit/7d31c37142d89758ccff805853db0855af2bd318) ) - aaronvg * Lots of tracing improvements for Boundary Studio [#2576](https://github.com/BoundaryML/baml/pull/2576) ### Documentation * fix @description documentation (#2544) - ([32aec21](https://github.com/boundaryml/baml/commit/32aec21f10840d28e837216f14ffed116e9bc377) ) - Samuel Lijin * Document Next.js version 15 requirement (#2540) - ([c1ce2ab](https://github.com/boundaryml/baml/commit/c1ce2abab0bddb42a84e492ef300a4dc14129a0a) ) - Greg Hale [0.210.0](https://github.com/boundaryml/baml/compare/0.209.0..0.210.0) - 2025-09-30 ------------------------------------------------------------------------------------ ### Bug Fixes * Fix document name for PDF inference on Bedrock (#2545) - ([109612a](https://github.com/BoundaryML/baml/commit/109612ace4d5a1d4a37a8b392e55dc6bfb74997b) ) - Greg Hale * Fix regression in union streaming codegen (#2533) - ([0a7b396](https://github.com/BoundaryML/baml/commit/0a7b39652a940de679025c6044bc4ed51812b5a3) ) - Greg Hale * Jetbrains: avoid using deprecated java 18 api (#2541) - ([ec4f339](https://github.com/BoundaryML/baml/commit/ec4f339b628e34d2e6d0dd04df685929149830ed) ) - Sam Lijin ### Features * Enable “Citations” PDF analysis model for Claude on Bedrock (#2547) - ([219e53f](https://github.com/BoundaryML/baml/commit/219e53f9b3d9f538350c433b26ff68d95ae8324e) ) - Greg Hale * Add type narrowing for discriminated unions in Jinja (#2539) - ([7a395a9](https://github.com/BoundaryML/baml/commit/87e95fe818b596ab2580cd87fd4a26a32a058dd8) ) - Antonio Sarosi ### Docs * Document BAML tag setting and retrieval (#2534) - ([d90e7a3](https://github.com/BoundaryML/baml/commit/d90e7a35c6e43e308ab841b24e69b635ef514f8f) ) - aaronvg [0.209.0](https://github.com/boundaryml/baml/compare/0.208.5..0.209.0) - 2025-09-28 ------------------------------------------------------------------------------------ ### Bug Fixes * Make Studio trace uploads 6x more efficient, and fix flushing logic (#2531) * Fix an issue where we wouldn’t parse a stream until the end of the stream, fix openai responses pdf input, and vertex-anthropic streaming. (#2530) - ([4bb2f33](https://github.com/boundaryml/baml/commit/4bb2f33ff908ff6a2f97fca222bc7afb5a12e8f3) ) - aaronvg * **(language-server)** handle non-baml-src baml files gracefully (#2506) - ([613df6b](https://github.com/boundaryml/baml/commit/613df6b9398d2921b5551be4f54db4cb285ba32f) ) - Samuel Lijin * **(playground)** make vertex work in the vscode playground (#2525) - ([6a5fa73](https://github.com/boundaryml/baml/commit/6a5fa73253da89952d698cac16514d1673d84a48) ) - Samuel Lijin ### Features * Bedrock modular api support (#2526) - ([42dfef3](https://github.com/boundaryml/baml/commit/42dfef3a1e66b265858b42600fc759e330ea0f56) ) - Greg Hale * Expose tags in the collector. Allow passing tags via baml function baml\_options (#2528) - ([27f0694](https://github.com/boundaryml/baml/commit/27f06945727cd5354421516f9fe7183e86a6e298) ) - aaronvg ### Docs * Update vertex ai provider docs with api key info (#2519) - ([f146914](https://github.com/boundaryml/baml/commit/f1469143472c041521b6c8774a01e2670397977b) ) - aaronvg * Bump version to 0.209.0 - ([ca4cf4d](https://github.com/boundaryml/baml/commit/ca4cf4d2091be8f7561a80ca1dbc3c21ada35011) ) - Aaron Villalpando [0.208.5](https://github.com/boundaryml/baml/compare/0.208.4..0.208.5) - 2025-09-24 ------------------------------------------------------------------------------------ ### Bugfix * Allow using clients using vertex api keys in the playground (#2516) - ([0ae357e](https://github.com/boundaryml/baml/commit/0ae357ed295b8f2f4f9ec17fad9ce17d3775bc12) ) - aaronvg * Bump version to 0.208.5 - ([9bb4778](https://github.com/boundaryml/baml/commit/9bb4778c6e45d95d33e0156c6a9fa4de4234ef4f) ) - Aaron Villalpando [0.208.4](https://github.com/boundaryml/baml/compare/0.208.3..0.208.4) - 2025-09-24 ------------------------------------------------------------------------------------ ### Features * baml-cli check command (#2508) - ([a4afaed](https://github.com/boundaryml/baml/commit/a4afaed88265d0029c7ee0a5b91c1681424e16d2) ) - José Rafael Oses * add vertex api key auth (#2512) - ([a0a83fe](https://github.com/boundaryml/baml/commit/a0a83fe40c407b139ad62f2c431012470c750dcf) ) - aaronvg [0.208.3](https://github.com/boundaryml/baml/compare/0.208.2..0.208.3) - 2025-09-23 ------------------------------------------------------------------------------------ ### Bug Fixes * **(lang-server)** handle non-baml-src baml files (#2486) - ([6bf3299](https://github.com/boundaryml/baml/commit/6bf32994d9411eddd2384552822a3e50a84f790f) ) - Samuel Lijin * Fix wasm integ tests, fix playground not streaming (#2504) - ([f892440](https://github.com/boundaryml/baml/commit/f892440721dca21c53b57e3521176bb8dc03bb38) ) - aaronvg * Bump version to 0.208.3 - ([f983b84](https://github.com/boundaryml/baml/commit/f983b8463db412ff469944acc16a031aa027f89d) ) - Aaron Villalpando [0.208.2](https://github.com/boundaryml/baml/compare/0.208.0..0.208.2) - 2025-09-23 ------------------------------------------------------------------------------------ ### Bugfixes * Add mcp types (#2500) - ([0501d6d](https://github.com/boundaryml/baml/commit/0501d6db3c66cd21b02f88e2316d0bda167d56a5) ) - aaronvg * Bump version to 0.208.2 - ([1624f6c](https://github.com/boundaryml/baml/commit/1624f6c60c1874ff92ae6b02366f19769c0cb9df) ) - Aaron Villalpando [0.208.1](https://github.com/boundaryml/baml/compare/0.208.0..0.208.1) - 2025-09-22 ------------------------------------------------------------------------------------ ### Bugfixes * Autosave changes on Import .env click (#2488) - ([11d8a69](https://github.com/boundaryml/baml/commit/11d8a69bd40fda20d73d3031c7acc7e88d18bf50) ) - Antonio Sarosi * Slightly more lenient set of keywords (#2495) - ([9a98c3f](https://github.com/boundaryml/baml/commit/9a98c3ffeedf8147e72ef8c66e841ea847e6de90) ) - Greg Hale * Bump version to 0.208.1 - ([8def010](https://github.com/boundaryml/baml/commit/8def0105d257952233ed62f8cefef31c2d199335) ) - Aaron Villalpando [0.208.0](https://github.com/boundaryml/baml/compare/0.207.1..0.208.0) - 2025-09-21 ------------------------------------------------------------------------------------ ### Features * **(jetbrains)** get closer to feature parity with vscode (#2447) - ([0efb169](https://github.com/boundaryml/baml/commit/0efb169a13b5bc14d20438e960ba3dfa530a0f29) ) - Samuel Lijin * **(sdk)** errors now expose fallback history in detailed\_message (#2449) - ([11a131f](https://github.com/boundaryml/baml/commit/11a131fae96ad05f49a429bc4ca845863a61f9c6) ) - Samuel Lijin * Improve streaming latencies in case parsing ever takes too long (#2467) - ([84bd606](https://github.com/boundaryml/baml/commit/84bd60622bc74ba5452c24c7046b6fb8704af76b) ) - aaronvg * BAML warns you if you use a template string without ’()’ (#2476) - ([a3b8c57](https://github.com/boundaryml/baml/commit/a3b8c576a594774bf3b47e68d4efa042b1ee567c) ) - aaronvg * Implement collector clear() and update docs (#2478) - ([13e7e13](https://github.com/boundaryml/baml/commit/13e7e1361fc0f99c08876c9b24cc6d783b2458d3) ) - aaronvg ### Bugs * Fix vertical scroll on `PromptView` component (#2462) - ([5eb3381](https://github.com/boundaryml/baml/commit/5eb3381b2c715d70538ebaf129a010e90ae40215) ) - Antonio Sarosi * Fix pdf input as base64url in openai-responses (#2464) - ([2fad7cd](https://github.com/boundaryml/baml/commit/2fad7cd57b432ff3f70c46ef3b137039b987c15e) ) - aaronvg * Fix colons in config maps (#2475) - ([9736532](https://github.com/boundaryml/baml/commit/9736532b2f07eec2a4b87e3975bb83624452f4e2) ) - Greg Hale * Fix deep config object parsing and env var redaction (#2485) - ([9e35412](https://github.com/boundaryml/baml/commit/9e35412a4c2a942d9c301553575dd61b47a4359c) ) - Greg Hale ### Docs * Add vercel ai gateway to docs (#2453) - ([a2e98a5](https://github.com/boundaryml/baml/commit/a2e98a584cf5601ea07c3abf777257de4953bf61) ) - aaronvg * Update pdf testing documentation in playground (#2457) - ([66e449c](https://github.com/boundaryml/baml/commit/66e449c64aef2356a6ee6de627429e9952172233) ) - aaronvg * Fix LLM Parse Fixup recipe in docs (#2459) - ([80db51a](https://github.com/boundaryml/baml/commit/80db51a3bda096f90c48f033e321fdf7835d9145) ) - Greg Hale * Update documentation and examples to use latest 2025 AI models (#2460) - ([0b1bc44](https://github.com/boundaryml/baml/commit/0b1bc44131aad61199cf5b583eb0ef9f2b113ef2) ) - hellovai * Add `on_generate` option to other languages (#2461) - ([d7853bd](https://github.com/boundaryml/baml/commit/d7853bded81f034a8d3dadb0bb9acd3180c436b9) ) - Antonio Sarosi * remove fn keyword (#2468) - ([8557ab4](https://github.com/boundaryml/baml/commit/8557ab466c878d7515e952fb062455b8e3bc2b86) ) - Greg Hale * Bump version to 0.208.0 - ([c1630f5](https://github.com/boundaryml/baml/commit/c1630f556a8bc90c17dc1f97229884714a6937b1) ) - Aaron Villalpando [0.207.1](https://github.com/boundaryml/baml/compare/0.207.0..0.207.1) - 2025-09-13 ------------------------------------------------------------------------------------ ### Bug Fixes * **(jetbrains)** implement dynamic versioning (#2439) - ([d352f02](https://github.com/boundaryml/baml/commit/d352f02883c5c01200ae4aacfe095396c6ef272b) ) - Samuel Lijin * **(openai)** openai-responses had a bug in the assistant request format (#2440) - ([aca1c53](https://github.com/boundaryml/baml/commit/aca1c5314d29d7f91d02c29356d5e2a2dbb87319) ) - Samuel Lijin * make baml-cli in go also work if you type ‘baml’ (#2445) - ([5f2df4b](https://github.com/boundaryml/baml/commit/5f2df4b323231d9d9b1a21cf4f4fb7d8ee92fac4) ) - aaronvg * \[Playground\] Dont animate sidebar to improve performance - ([80ff10a](https://github.com/boundaryml/baml/commit/80ff10a7ff3432a94b17b2982c3ad1a01c4c59e2) ) - Aaron Villalpando ### Docs * Document fixing parsing issues with LLMs (#2448) - ([137ee7e](https://github.com/boundaryml/baml/commit/137ee7e303cd009f41504e15c2a7ed4aa3132eb0) ) - Greg Hale [0.207.0](https://github.com/boundaryml/baml/compare/0.206.1..0.207.0) - 2025-09-10 ------------------------------------------------------------------------------------ ### Bug Fixes * **(python)** Update internal runtime type annotations (#2400) - ([992acaa](https://github.com/boundaryml/baml/commit/992acaa5afcdb8e52f1315f4d9c7260906b38eb0) ) - Samuel Lijin * **(vscode)** make “Run test” codelenses appear in the correct place and run the correct test (#2395) - ([b9c3fea](https://github.com/boundaryml/baml/commit/b9c3fea18603f611fae3d616b6082a29004701f9) ) - Samuel Lijin * **(vscode)** Fix Jetbrains and VScode test selection (#2427) - ([e4d3529](https://github.com/boundaryml/baml/commit/e4d35296da2a9b39f9b56039d774f2c1871b9269) ) - Samuel Lijin * use roles correctly with openai-responses (#2392) - ([d976c55](https://github.com/boundaryml/baml/commit/d976c55a7048f5a025f941a7bfae545d2bc94a54) ) - Samuel Lijin * Emit notification to check CLI version against client (#2404) - ([6ea5617](https://github.com/boundaryml/baml/commit/6ea5617c99c82e4e4fd4296b82a5a44b50264e95) ) - Jesús Lapastora * Fix media file path resolution on Windows (#2391) - ([3950a49](https://github.com/boundaryml/baml/commit/3950a495a3f91ec9bf274ace91df9c05837a3e9f) ) - Greg Hale * syntax highlighting for pdf type (#2414) - ([21f7d62](https://github.com/boundaryml/baml/commit/21f7d62ba0ba8488cc1acc88557b459f859c1d46) ) - Greg Hale * Fix TS double ‘export declare’ in baml\_client by migrating to napiv3 (#2228) - ([a5294fa](https://github.com/boundaryml/baml/commit/a5294fabbb4f9d6806fe81ba99b9d436acb3f9c8) ) - Ethan Lijin * \[Python\] Pass `abort_controller` to `Runtime::stream_function` (#2416) - ([8100bc2](https://github.com/boundaryml/baml/commit/8100bc2ecb36d1cf0338f9d2a61738a641d7ef13) ) - Antonio Sarosi * Improve the samples and error messages for test blocks (#2418) - ([e1a8fd5](https://github.com/boundaryml/baml/commit/e1a8fd5541ed9e1401a66194aea32bd9c5e83289) ) - Greg Hale ### Docs * Fix tabs not syncing correctly in docs (#2420) - ([134fac0](https://github.com/boundaryml/baml/commit/134fac0aacd7ab49f77edf2648b0fd640bf9e08b) ) - aaronvg * Enhance OpenAPI Docs (#2399) - ([964bc40](https://github.com/boundaryml/baml/commit/964bc408bca71279af676ff0b2ed6dc618dba0c4) ) - Antonio Sarosi ### Features * Add cached input token tracking to Usage reporting (#2394) - ([7e460e6](https://github.com/boundaryml/baml/commit/7e460e68dae52d203a7a0bb8e9906a7acff359c3) ) - Luke Ramsden ### BAML Agents / Workflows (WIP) * Improve expr-fn parsing (#2408) - ([eca5142](https://github.com/boundaryml/baml/commit/eca5142b7cef94b29e9a07aec7ddb567fcc8b71b) ) - Greg Hale * Merge Mermaid diagram visualizer (#2381) - ([df6ee12](https://github.com/boundaryml/baml/commit/df6ee1250107ff989f704df942004ba46a2d9fbf) ) - Greg Hale * Update syntax highlighting (#2412) - ([5c3c412](https://github.com/boundaryml/baml/commit/5c3c412e7ab99d582d202c10d9933bd29d163c7f) ) - Greg Hale * VM Errors & Type Convertions & Missing Types (#2403) - ([51fc365](https://github.com/boundaryml/baml/commit/51fc365510577f3a271fb088f1b3df522be9f983) ) - Antonio Sarosi * Add string concatenation: `"a" + "b"` (#2426) - ([41d53ea](https://github.com/boundaryml/baml/commit/41d53eaf12a689edab4a876b738c91d053932805) ) - Antonio Sarosi ### Boundary Studio * More improvements to studio2 publishing (#2333) - ([39e731a](https://github.com/boundaryml/baml/commit/39e731a23d88faaa750519fd402f85281b46f1cb) ) - aaronvg [0.206.1](https://github.com/boundaryml/baml/compare/0.206.0..0.206.1) - 2025-08-28 ------------------------------------------------------------------------------------ ### Bugfix * vscode extension is broken (#2387) - ([i43e4f72](https://github.com/BoundaryML/baml/commit/43e4f72effeb8ec48c40681dc129ba3ce9124288) ) - hellovai * media types in jinja should evaluate to true in jinja bool conversions (#2384) - ([d25d3eb](https://github.com/boundaryml/baml/commit/d25d3ebce21ab6157dd760dfcde217e711229191) ) - hellovai [0.206.0](https://github.com/boundaryml/baml/compare/0.205.0..0.206.0) - 2025-08-27 ------------------------------------------------------------------------------------ ### Bug Fixes * package the baml-py license correctly (#2325) - ([eb70206](https://github.com/boundaryml/baml/commit/eb7020639ef4d79ff9f5c513d1102c5ded9b2ed1) ) - Samuel Lijin * teach PromptRenderer to render enum values as their alias, not the value literal (#2326) - ([5366299](https://github.com/boundaryml/baml/commit/5366299334fb0320245f5fb5d44bdc22f87996d2) ) - Samuel Lijin * Make the Jetbrains extension work (#2358) - ([09aeb12](https://github.com/boundaryml/baml/commit/09aeb1256c2ba3d6f9074040c89dbce24ef239b4) ) - Samuel Lijin * Fix ERR\_MODULE\_NOT\_FOUND for ESM users (#2299) - ([1bd1021](https://github.com/boundaryml/baml/commit/1bd10214c700b83a118ee16ca7b74ab53727dcea) ) - Luke Ramsden * Do not generate code when generator/LSP versions do not match (#2367) - ([e8c9859](https://github.com/boundaryml/baml/commit/e8c98595c3b9048ee40b8a99d2f735ce9610cf74) ) - Jesús Lapastora * fix roles and multi-modality on openai-responses provider (#2327) - ([01595b2](https://github.com/boundaryml/baml/commit/01595b20433af529bd2be128a6e6a385252f075f) ) - hellovai * Fix `Pdf.from_base64` in Python to expose a logical API (#2366) - ([76fcd70](https://github.com/boundaryml/baml/commit/76fcd70ecc0df59226f6cda3a5b54b84e6ab9261) ) - Antonio Sarosi ### Features * Implement `onTick` which will allow users to get callbacks and access thinking tokens (#2362) - ([915ae27](https://github.com/boundaryml/baml/commit/915ae27118821e499b607185bb34c06f138035a9) ) - hellovai * Implement AbortController in py, ts, go, wasm (also cancel buttons) (#2357) - ([fb4dd72](https://github.com/boundaryml/baml/commit/fb4dd72136dae70257a49f66c8707343ee7bb191) ) - Samuel Lijin * Use AbortSignal in typescript, add a native timeout capability in python. (#2373) - ([a12ba5a](https://github.com/boundaryml/baml/commit/a12ba5a61792a2c59b23bf63f96d25f3b6457ea5) ) - hellovai * render raw curl for aws-bedrock (#2319) - ([2bbb267](https://github.com/boundaryml/baml/commit/2bbb267e7c91bb089bc35089f4d878eddeeaa6c6) ) - Ethan Lijin ### Documentation * add env var docs for studio v2 (#2347) - ([146f4b4](https://github.com/boundaryml/baml/commit/146f4b4659dbefeff669ef2fa58c1ddd6513aab5) ) - Chris Watts * Add official docs for go (#2253) - ([16d3612](https://github.com/boundaryml/baml/commit/16d3612c79bf89e8f1e0da440f48c749a0cba91f) ) - hellovai ### Miscellaneous Chores * claude code permissions should not be checked in (#2269) - ([99204c8](https://github.com/boundaryml/baml/commit/99204c8c00a559eb3c29961faf960b795e583828) ) - Trenton Lawrence [0.205.0](https://github.com/boundaryml/baml/compare/0.204.0..0.205.0) - 2025-08-14 ------------------------------------------------------------------------------------ ### Bug Fixes * **(jetbrains)** Fix installer logic (#2275) - ([a89ceb6](https://github.com/boundaryml/baml/commit/a89ceb6d1022b95e8842bcdb056d22816e3e4680) ) - Samuel Lijin * handle missing `parts` field in gemini flash responses (#2272) - ([5aa9995](https://github.com/boundaryml/baml/commit/5aa9995699533d90136c508b01ac09ef9d8df4d3) ) - Juan Manuel Verges * issue with some ids for embed prompt fiddle (#2279) - ([66f6566](https://github.com/boundaryml/baml/commit/66f65666f546c5e9b00b09c746203eb90e463850) ) - Chris Watts * Fix cases where BAML extension would deadlock — not loading playground (#2311) - ([d9a2a3d](https://github.com/boundaryml/baml/commit/d9a2a3d51f7b103a626d77f8503e4b78882b4a85) ) - Samuel Lijin * \[Python\] Allow Baml PDF, Image, Audio types to serialize correctly (#2274) - ([d017bfe](https://github.com/boundaryml/baml/commit/d017bfea1441ac8bfb6602d94299a69c91b60f55) ) - Egor Lukiyanov * Allow openapi generator to remove unknown files from output dir (#2281) - ([cba26f9](https://github.com/boundaryml/baml/commit/cba26f963eaac4c6506a19d483e89e81a63db5cf) ) - Antonio Sarosi * add version number on generations (#2282) - ([5e995ef](https://github.com/boundaryml/baml/commit/5e995ef6b05c233525de4dd7a07fe0a815adcf98) ) - aaronvg * Set token usage for gemini streaming (#2302) - ([2f6be15](https://github.com/boundaryml/baml/commit/2f6be15d05bf7ff7b3a96d46092584e4ad5184d4) ) - masonk ### Features * \[feature\] Allow users to remap common roles -> model specific roles. (#2288) - ([279051d](https://github.com/boundaryml/baml/commit/279051db754913b8087a1ad99be9fb3f64cabd35) ) - hellovai * Make `baml-cli test` run expression functions (#2294) - ([e163ce1](https://github.com/boundaryml/baml/commit/e163ce10aa090fca7ac7a9775dc78c369f94756d) ) - Greg Hale ### BAML VM (WIP) * Baml VM (#2089) - ([5e4b946](https://github.com/boundaryml/baml/commit/5e4b9467723e3371140dfa6f97d691f83c2dec9d) ) - Antonio Sarosi * Bitwise operators (`&`, `|`, `^`, `>>`, `<<`) (#2300) - ([9bd9552](https://github.com/boundaryml/baml/commit/9bd955237c629f306287fa7bd168f5a103a63378) ) - Antonio Sarosi * Assignment operators (`&=`, `|=`, `+=`, `-=`, `*=`, `/=`, `%=`, `>>=`, `<<=`) (#2301) - ([934ad56](https://github.com/boundaryml/baml/commit/934ad56a4ab64b99e58b3d50eb871511746c4c50) ) - Antonio Sarosi * While loops (#2297) - ([781846b](https://github.com/boundaryml/baml/commit/781846b4941318dfa64ad38039777ce633ddc0f7) ) - Jesús Lapastora * Bump version to 0.205.0 - ([e416f81](https://github.com/boundaryml/baml/commit/e416f81315749ddf0db32ad6049c7755a4c67ddc) ) - Aaron Villalpando [0.204.0](https://github.com/boundaryml/baml/compare/0.203.1..0.204.0) - 2025-08-06 ------------------------------------------------------------------------------------ ### Features * Enhance Type Builder API with listProperties() and reset() (#2177) - ([b4ddb6f](https://github.com/boundaryml/baml/commit/b4ddb6f6bae1c5bbd30ac3548103a5e997c6b695) ) - Antonio Sarosi * implement ai assistant for docs (#2189) - ([d326da7](https://github.com/boundaryml/baml/commit/d326da73ebba405362016bc09fd271ef16248d50) ) - Egor Lukiyanov * Implement caching for VertexAuth instances. (#2250) - ([66dba18](https://github.com/boundaryml/baml/commit/66dba1845c237b774c2ec29630dd8c5bcf251607) ) - hellovai ### Bug Fixes * **(jetbrains)** rename baml extension and publish to stable (#2260) - ([76e4e1b](https://github.com/boundaryml/baml/commit/76e4e1b463358c1c5465366d84f60fd80691fad5) ) - Samuel Lijin * issue with Promptfiddle.com/embeded not working correctly (#2245) - ([b8e78f9](https://github.com/boundaryml/baml/commit/b8e78f991d3bd9767a59bad78511e538a3ddf60a) ) - Chris Watts * issue with vscode colors (#2261) - ([85707b7](https://github.com/boundaryml/baml/commit/85707b7904c38ff9fb05e4b7a93db1cae1972909) ) - Chris Watts * make api key dialog scrollable (#2251) - ([b22f29c](https://github.com/boundaryml/baml/commit/b22f29c2dec7146af8d156d23b46180437c13b9d) ) - aaronvg * Make sure to update cli version of generator (#2256) - ([63f45d4](https://github.com/boundaryml/baml/commit/63f45d4b34b4682b297e024e5ac96b15030a2fcf) ) - Egor Lukiyanov * Fix validation to reject field-level assertions in test blocks (#2259) ([f741e43](https://github.com/boundaryml/baml/commit/f741e4319b4f95657a08e46f4404d258a1d91e5a) ) - Dex [0.203.1](https://github.com/boundaryml/baml/compare/0.203.0..0.203.1) - 2025-08-01 ------------------------------------------------------------------------------------ ### Bug Fixes * fix baml-cli init, and playground state when selecting and running tests (#2242) [0.203.0](https://github.com/boundaryml/baml/compare/0.202.1..0.203.0) - 2025-08-01 ------------------------------------------------------------------------------------ ### Bug Fixes * \[Go\] fix panic when downloading baml cli (#2201) - ([c8fd18b](https://github.com/boundaryml/baml/commit/c8fd18b143d19b235f44e707c2d4037e9895f4ad) ) - Rahul Tiwari * \[Go\] Support go mod vendor (#2203) - ([c62cf63](https://github.com/boundaryml/baml/commit/c62cf63e400072292649c6ae59fb9f107ee4fc73) ) - Rahul Tiwari * \[Python\] fix typebuilder type imports (#2209) - ([c104174](https://github.com/boundaryml/baml/commit/c10417488b0b4dd2667bf860e6e5a036d1960137) ) - Rahul Tiwari * Dont parse thinking blocks from Gemini (#2215) - ([c5a9cbc](https://github.com/boundaryml/baml/commit/c5a9cbc24488561c934b946749122d0a7e4f1a84) ) - Rahul Tiwari * Fix Issue with cross-origin policy on playground (#2217) - ([a82f682](https://github.com/boundaryml/baml/commit/a82f6829806e0502a4c30804b34cc97744d17027) ) - Chris Watts * Fix missing types for some llm responses like computer use (#2226) * fix union type warning (#2225) * Improve BAML SAP parser performance by 100x in many scenarios (#2233) - ([28b092e](https://github.com/boundaryml/baml/commit/28b092efb78f0d2758f03b6f06dc07fff7dd9f90) ) - Rahul Tiwari * Fix issue with BAML\_LOG env var not being respected (#2235) - ([65c8c66](https://github.com/boundaryml/baml/commit/65c8c663e43bea9b8b9cc3e11631546c6b0be525) ) - Rahul Tiwari * \[Breaking\] Remove Pdf media type specification (#2167) - ([fcbcb55](https://github.com/boundaryml/baml/commit/fcbcb55ae5d27d122903c8aaa92e961b55569a68) ) - egol * Add a pool timeout to try to fix open File descriptor issue like deno (#2205) - ([2a031b6](https://github.com/boundaryml/baml/commit/2a031b608af6de79534960ebbf9f186ffe09cb10) ) - aaronvg * Fix parser during streaming so that we correctly parse string\[\] from ”\[“foo”, (#2213) - ([5838036](https://github.com/boundaryml/baml/commit/583803634c98dfdb2eed2faff43306d2dab7250b)\ ) - hellovai\ * \[Playground\] Fix issue with test selection, and improve performance when selecting another function (#2224) - ([dd00956](https://github.com/boundaryml/baml/commit/dd00956f7ade26e6e09a865191802b8b4a840367)\ ) - aaronvg\ \ ### Features\ \ * Finalize Zed Extension (#2169) - ([ec170db](https://github.com/boundaryml/baml/commit/ec170dbc0bb01598715ef8e220828c0dc52777c7)\ ) - egol\ * Re-add playground tests sidebar to ‘run all’ tests (#2214) - ([96e9d64](https://github.com/boundaryml/baml/commit/96e9d648411d24df5eaac796e6b5d69e91df5559)\ ) - Chris Watts\ * Add ClientRegistry, BamlPdf and BamlVideo in openapi generator (#2170) - ([0bc450f](https://github.com/boundaryml/baml/commit/0bc450facd2a9b2fdae9d7ed34341a8bfbf7c56c)\ ) - Greg Hale\ * \[feature\] add multimodal support for go (#2192) - ([f49c25c](https://github.com/boundaryml/baml/commit/f49c25c8d356a00695b287f07e05c55f4878e47a)\ ) - hellovai\ * \[feat\] Add internationalization to SAP parser (#2210) - ([dce9074](https://github.com/boundaryml/baml/commit/dce9074f5910b43c8a7197edd614bd8ca7585fb1)\ ) - hellovai\ * Refreshed playground look (#2227) - ([e514d53](https://github.com/boundaryml/baml/commit/e514d53c775ef6b305b6a1ff85d97f5288c2f1a7)\ ) - Chris Watts\ \ ### Cli\ \ * add IDE/terminal auto-detect from baml-cli init (#2178) - ([34a0428](https://github.com/boundaryml/baml/commit/34a0428d6b755226110f891327aa8ec7d6f0cf0b)\ ) - Rahul Tiwari\ \ [0.202.1](https://github.com/boundaryml/baml/compare/0.202.0..0.202.1)\ - 2025-07-18\ ------------------------------------------------------------------------------------\ \ ### Bug fixes\ \ * apply suggestions by cargo fix to reduce warnings (#2158) - ([4a851dc](https://github.com/boundaryml/baml/commit/4a851dca4f7fb3161602589bc6214d11fd845aee)\ ) - Rahul Tiwari\ * \[feat\] merge union types in go whenever possible (#2160) - ([73f0c36](https://github.com/boundaryml/baml/commit/73f0c36dbe9d087acc2213374e3d14bd4ea750af)\ ) - hellovai\ * Bump version to 0.202.1 - ([4ff6a02](https://github.com/boundaryml/baml/commit/4ff6a02148d516cf3af9505a8aaa168b88ca2168)\ ) - Aaron Villalpando\ \ [0.202.0](https://github.com/boundaryml/baml/compare/0.201.0..0.202.0)\ - 2025-07-16\ ------------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * issues with setup-dev.sh (#2133) - ([059b7c3](https://github.com/boundaryml/baml/commit/059b7c304482444c5e6b58330ed31bcf528375b3)\ ) - Chris Watts\ * Fix baml-cli generate panic (#2142) - ([8884e20](https://github.com/boundaryml/baml/commit/8884e2040660782d52f2b63a0049f44bfbd05bc4)\ ) - aaronvg\ * Fix generation of ignore files in openapi (#2112) - ([7eb1450](https://github.com/boundaryml/baml/commit/7eb145080d95f6f8f407e849ff338ff6f8fa9cfb)\ ) - Greg Hale\ * In go, fix issue with top level strings / primitiive types being returned (#2110) - ([0a1aa60](https://github.com/boundaryml/baml/commit/0a1aa60d38efa2129e39b2578df1a18a211c5516)\ ) - hellovai\ * Support moving / renaming baml files and directories and remove language server crash (#2131) - ([9d6a3db](https://github.com/boundaryml/baml/commit/9d6a3dbb4cce7a04c9c156e298196c810a74b36b)\ ) - Antonio Sarosi\ * Propertly escape env vars from VSCode -> BAML runtime to handle JSON strings (credentials for vertex) (#2135) - ([d81a0a7](https://github.com/boundaryml/baml/commit/d81a0a7225dbd17b32e6bf4d515380b97539f850)\ ) - hellovai\ \ ### Documentation\ \ * Update playground UI references and screenshots (#2122) - ([a7974fb](https://github.com/boundaryml/baml/commit/a7974fb8294f17d1d496adc9e4cef2ec9e31a5bc)\ ) - George\ * Improved documentation for baml versioning (#2124) - ([083ccb7](https://github.com/boundaryml/baml/commit/083ccb785e6ce9164cbef9e75a525ab3c36b9d48)\ ) - egol\ * Docs for using anthropic models on vertex (#2123) - ([0db53c1](https://github.com/boundaryml/baml/commit/0db53c1fd93d9683fcb9ad2a6fea970161d16730)\ ) - Gabe Villasana\ * Make baml directory structure and set up easier (./scripts/setup-dev.sh && pnpm build) (#2087) - ([6b7c178](https://github.com/boundaryml/baml/commit/6b7c1782ce73c19891a08b81e1291c2295500daf)\ ) - Chris Watts\ \ ### Features\ \ * Add new provider “openai-responses” for OpenAI Responses API support (#2103) - ([18ef4e4](https://github.com/boundaryml/baml/commit/18ef4e4a59f6fd5c15e8eeca275ce579745603cf)\ ) - Rahul Tiwari\ * Add SSE stream to the collector (#2118) - ([d389451](https://github.com/boundaryml/baml/commit/d389451fd1dd2dc114eedf1c158339b74ef67455)\ ) - hellovai\ * Add Pdf and Video support (#2121) - ([f33bd71](https://github.com/boundaryml/baml/commit/f33bd718ff29315e8fc6cd67f596cba922409c38)\ ) - egol\ * Add collector capability to Go (#2119) - ([de024cf](https://github.com/boundaryml/baml/commit/de024cf5324640b85358312a42c1e9f9d3405cd5)\ ) - hellovai\ * \[feat\] Add experiemental support for accessing collector prior to first streamed value in go (#2146) - ([786c303](https://github.com/boundaryml/baml/commit/786c303ea29207036f8570006e3ca38d0185244f)\ ) - hellovai\ \ [0.201.0](https://github.com/boundaryml/baml/compare/0.200.0..0.201.0)\ - 2025-07-03\ ------------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Add complete type validation for Go (#2101) - ([8b35440](https://github.com/boundaryml/baml/commit/8b354407746dc3c26120369edb05dab2e3cd6e45)\ ) - hellovai\ \ [0.200.0](https://github.com/boundaryml/baml/compare/0.90.2..0.200.0)\ - 2025-07-01\ -----------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Fix issue with baml-cli test where env vars wouldnt work (#2060) - ([344fb8a](https://github.com/boundaryml/baml/commit/344fb8a55ab46df8672904cf89bc5a814161d9c4)\ ) - Rahul Tiwari\ * fix VSCode Proxy Handling due to v2 -> v3 for npm:http-proxy-middleware (#2065)\ * \[Python\] Fix issue where Baml wouldn’t be pickleable\ * Render `none` as `null` for jinja inputs (#2037) - ([bfa98e8](https://github.com/boundaryml/baml/commit/bfa98e8ec7f272a888bb581a75c71469c21dfef7)\ ) - Antonio Sarosi\ * Add linter warnings for experimental expr features (#2053) - ([9fbc9ee](https://github.com/boundaryml/baml/commit/9fbc9ee38336bf08a0c67c02f237a6886e931cd5)\ ) - Greg Hale\ * Fix prompt-fiddle highlighting (#2082) - ([350914c](https://github.com/boundaryml/baml/commit/350914cf4f2ca7244951eb62f7e1570248ee2482)\ ) - Greg Hale\ * Fix performance issue on promptfiddle codemirror editor (#2083) - ([a64848c](https://github.com/boundaryml/baml/commit/a64848c9e5f29adad89a558a8ae9c0f3092e1545)\ ) - aaronvg\ * Fix env vars in promptfiddle (#2084) - ([52b5329](https://github.com/boundaryml/baml/commit/52b532906506dc684d683242ccea871747ec458c)\ ) - Antonio Sarosi\ * Add fixes for typesystem to deal with semantic streaming (#2086) - ([d2c26f2](https://github.com/boundaryml/baml/commit/d2c26f2c43fd7384a99343248e09b83454f0ae4d)\ ) - hellovai\ * Parsing fix for streaming lists of objects (#2092) - ([cca8863](https://github.com/boundaryml/baml/commit/cca8863cbad3430f59e1e6dd40077f5a94aa036b)\ ) - aaronvg\ \ ### Features\ \ * Zed Extension support (#2044) - ([f07d944](https://github.com/boundaryml/baml/commit/f07d944a357506b14cdd6549ccf435289ed5ab47)\ ) - egol\ * Boundary studio v2 alpha release - ([843dfde](https://github.com/boundaryml/baml/commit/843dfdeb7e00acb6a464aa26654bc7f94fc382ce)\ ) - aaronvg\ * Jetbrains Extension support (#2001) - ([984e800](https://github.com/boundaryml/baml/commit/984e800ffe26236963de080820cb43d7f410c826)\ ) - Samuel Lijin\ \ ### Miscellaneous\ \ * Adding more docs for llama api (#2077) - ([412eaff](https://github.com/boundaryml/baml/commit/412eaff86895d4c163510651e912b8c5bcd550c9)\ ) - hellovai\ * Bump version to 0.200.0 - ([c153d4a](https://github.com/boundaryml/baml/commit/c153d4ae1835aa9e8bd33c341b1126b16f1a219d)\ ) - Aaron Villalpando\ \ [0.90.1](https://github.com/boundaryml/baml/compare/0.90.0..0.90.1)\ - 2025-06-16\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * Fix fatal log line showing up with publisher not started (#2038) - ([e02c30a](https://github.com/boundaryml/baml/commit/e02c30abf8aecfdccbd28386d0bc4049d017bc8c)\ ) - aaronvg\ \ [0.90.0](https://github.com/boundaryml/baml/compare/0.89.0..0.90.0)\ - 2025-06-14\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Fix bug where BAML\_LOG wouldnt be printed in python due to a tracing bug (#2030) - ([7736f22](https://github.com/boundaryml/baml/commit/7736f22cc98916e7e24fcec7dfbaa406c5aa3a65)\ ) - aaronvg\ * Fix parsing issue when there was a newline before object field (#1985) - ([ad92d3e](https://github.com/boundaryml/baml/commit/ad92d3ee847125a7a8537f3d3873e9689a0a1ce9)\ ) - Greg Hale\ * implement handling of Media under coerce\_arg (#1996) - ([929ee97](https://github.com/boundaryml/baml/commit/929ee97c716e0932f1dce4af54dcdf073c8659f5)\ ) - Greg Hale\ * Fix inconsistent class hoisting bug (#1998) - ([779450d](https://github.com/boundaryml/baml/commit/779450daa8f35542d6bd86563b01dbe685389e91)\ ) - Antonio Sarosi\ * Fix prompt rendering highlight regex (#1997) - ([0363df7](https://github.com/boundaryml/baml/commit/0363df7e5f3a92756e8966a386255d4b390b9f08)\ ) - Antonio Sarosi\ * Correctly infer Vertex AI base URL for location ‘global’ (#2014) (#2015) - ([149b742](https://github.com/boundaryml/baml/commit/149b7420f32fc391701f69425777b59ea5370075)\ ) - Luke Ramsden\ * Reduce namespace pollution in codegen (#2016) - ([505a9e9](https://github.com/boundaryml/baml/commit/505a9e976e097a3ba3a6f941dec62cd4f257a2e6)\ ) - Antonio Sarosi\ * Fix bug where LSP crashed when a baml file not in a baml\_src was opened (#2019) - ([e9303ae](https://github.com/boundaryml/baml/commit/e9303aebdc5c79d86b1c2a59aa43e46250693d28)\ ) - aaronvg\ \ ### Features\ \ * Release jetbrains extension (alpha) (#1983) - ([18b57dd](https://github.com/boundaryml/baml/commit/18b57ddcc264720f3ba016319e61147d30f12f5f)\ ) - Samuel Lijin\ * lazy load env vars to not rely on baml client import order (#1949) - ([4397cf1](https://github.com/boundaryml/baml/commit/4397cf100f6a6d164bd46820aaafc46615f5b918)\ ) - Rahul Tiwari\ * deeply typecheck class constructors (#2000) - ([8d66b80](https://github.com/boundaryml/baml/commit/8d66b8071301b9b7ed7cb999a6aa692c3b8503e4)\ ) - Greg Hale\ * Fetch API (#1916) - ([67b3f4f](https://github.com/boundaryml/baml/commit/67b3f4fe06652749809aeee64aacfb7bef57cc1f)\ ) - Antonio Sarosi\ * Migrate jinja to minijinja2, enabling latest fixes on jinja templating (#2025) - ([230c51c](https://github.com/boundaryml/baml/commit/230c51cbc879c073cbe225d03f8bbc86e80bd55c)\ ) - aaronvg\ \ ### Other\ \ * improve error message for asserts and checks (#1975) - ([070ad26](https://github.com/boundaryml/baml/commit/070ad26131f73afb2630d2559c19cbaa26a63abc)\ ) - Greg Hale\ * Reduce Vscode Extension bundle size by removing old LSP code (#2031) - ([c92bcf6](https://github.com/boundaryml/baml/commit/c92bcf64dd1e50c40781c57a82405a428debe56a)\ ) - aaronvg\ \ ### Docs\ \ * Fix dynamic enum spelling in docs (#1986) - ([9212af2](https://github.com/boundaryml/baml/commit/9212af236c997d0a46167de2b7eefc57dbf01d93)\ ) - ngirard\ * update docs for env vars (#1987) - ([8405ee5](https://github.com/boundaryml/baml/commit/8405ee5bb9b96d4a99a5f4b326f61a39e4336d5b)\ ) - Rahul Tiwari\ * Add baml-cli test documentation (#2021) - ([854cdbd](https://github.com/boundaryml/baml/commit/854cdbdd259398e24311fa958e647b30dc2c8b73)\ ) - aaronvg\ * add docs for `selected_call` (#2028) - ([97b2408](https://github.com/boundaryml/baml/commit/97b2408b5dd5d5555272cca24b3569ff1c9d5164)\ ) - Ben Epstein\ \ [0.89.0](https://github.com/boundaryml/baml/compare/0.88.0..0.89.0)\ - 2025-05-21\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Add `hoist_classes` parameter in `ctx.output_format` (#1957) - ([42ee507](https://github.com/boundaryml/baml/commit/42ee507e21422ea6d7267172c22d534a65f700ac)\ ) - Antonio Sarosi\ * \[feat\] Adding support for pydantic v1 (#1968) - ([3fdbfd0](https://github.com/boundaryml/baml/commit/3fdbfd05207f44a92d48d952c2ccbfeec9104850)\ ) - hellovai\ * \[Go\] Add ClientRegistry (#1967) - ([1cb4648](https://github.com/boundaryml/baml/commit/1cb464826d8cbc21b555b725fd6594239605cf01)\ ) - Todd Berman\ \ ### Bug Fixes\ \ * enum validation to disallow reserved names as enum values (#1955) - ([ae13c4d](https://github.com/boundaryml/baml/commit/ae13c4dfde7cd2f51d17934d564980662cfb9e3b)\ ) - Rahul Tiwari\ * \[Go\] Maps are being returned not as pointers as they are already pointers (#1956) - ([3d83f99](https://github.com/boundaryml/baml/commit/3d83f9975eb38d0cf0820ff634c7cafd91044be9)\ ) - Todd Berman\ * \[go\] JSON deserialize Union fix (#1954) - ([f748439](https://github.com/boundaryml/baml/commit/f7484395bf349231ffa626fdd7222f6929e79be6)\ ) - Todd Berman\ * Fix height rendering issue on playground (#1963) - ([bb39c3d](https://github.com/boundaryml/baml/commit/bb39c3d1d0914d6c8b724b471f21023cd519aab2)\ ) - aaronvg\ * Fix nested assert typechecking (#1966) - ([113966f](https://github.com/boundaryml/baml/commit/113966f6f43c2cf2fbcc6c0796ebe353d5f2d3f6)\ ) - Greg Hale\ * Fix issue where tracing logs would not be sent if you had an empty BOUNDARY\_BASE\_URL env var (#1971) - ([9203f6a](https://github.com/boundaryml/baml/commit/9203f6aa81dd6ca0d4160d82392bbf1183bf8c82)\ ) - aaronvg\ \ ### Miscellaneous\ \ * \[docs\] adding docs for cerebras (#1952) - ([e9d699b](https://github.com/boundaryml/baml/commit/e9d699bd8f7a47b462ad6289991b9231f4e1517f)\ ) - hellovai\ * \[docs\] adding support for tinfoil models (#1958) - ([9255eb0](https://github.com/boundaryml/baml/commit/9255eb01fecbfdf6dd45ebba7c81274484786887)\ ) - hellovai\ * \[MVP\] add conditional expressions (#1959) - ([ee15d0f](https://github.com/boundaryml/baml/commit/ee15d0f379f53a93f2d80b39909c74495b19930b)\ ) - Greg Hale\ * use regex\_match in constraint docs (#1953) - ([fbba5cc](https://github.com/boundaryml/baml/commit/fbba5cc43066ca719ca7f8a003e5ffba4cfbdb6c)\ ) - Greg Hale\ \ [0.88.0](https://github.com/boundaryml/baml/compare/0.87.2..0.88.0)\ - 2025-05-14\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ * **(tools)** add string literal examples (#1939) - ([b037124](https://github.com/boundaryml/baml/commit/b037124a64d5951b5d96ae8b237006fa3c780151)\ ) - Elijas Dapšauskas\ \ ### Features\ \ * Support openai audio input (#1940) - ([87ed2b1](https://github.com/boundaryml/baml/commit/87ed2b1454ddf02d9e4950d0c72b12a2b04f848e)\ ) - aaronvg\ * add HookData for baml react hooks, as a utility to get nonnullable types (#1925) - ([6501ad2](https://github.com/boundaryml/baml/commit/6501ad20985a426d1ae3952a24062595e935de53)\ ) - Chris Watts\ * \[Python\] Support windows arm64 (#1944) - ([ef9e8be](https://github.com/boundaryml/baml/commit/ef9e8be2f59b0b1280842ff53963ba57f9c86275)\ ) - aaronvg\ \ ### Bugs\ \ * Maintain field order when rendering class in Python (#1931) - ([46921b7](https://github.com/boundaryml/baml/commit/46921b7ad9e0a5766f02828b267e08ec6b48ef8b)\ ) - Antonio Sarosi\ * \[Go\] Fix Union JSON serialization (#1936) - ([6d4eb2b](https://github.com/boundaryml/baml/commit/6d4eb2b14451137c950e931d39d072b1f79ba254)\ ) - Todd Berman\ \ [0.87.2](https://github.com/boundaryml/baml/compare/0.87.1..0.87.2)\ - 2025-05-08\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * \[Go\] Fix build of baml-cli for Go in linux (#1921) - ([d234dc9](https://github.com/boundaryml/baml/commit/d234dc922d6f01487a5e680ee52f1d8b28ef7ebb)\ ) - Todd Berman\ * Bump version to 0.87.2 - ([77d6502](https://github.com/boundaryml/baml/commit/77d650219af58debc33d2544a2704197645ced32)\ ) - Aaron Villalpando\ \ [0.87.1](https://github.com/boundaryml/baml/compare/0.87.0..0.87.1)\ - 2025-05-07\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * \[bug\] Correctly parse enums when other json elements may exist in the string (#1913) - ([da202d1](https://github.com/boundaryml/baml/commit/da202d1e2c9147bf72b993e7ad1d0f203487b284)\ ) - hellovai\ * \[Go\] Switch bool to int in CFFI layer (#1915) - ([4b7075a](https://github.com/boundaryml/baml/commit/4b7075affc8f24d07d8aa3a1695266d5864e1771)\ ) - Todd Berman\ * Disable completions due to issues with non-ascii chars (#1917) - ([c0f3fa1](https://github.com/boundaryml/baml/commit/c0f3fa1e484d1fce4f519447065f61783d128ab3)\ ) - aaronvg\ * Bump version to 0.87.1 - ([d5a1d3f](https://github.com/boundaryml/baml/commit/d5a1d3fb99a4a9fa82f193b47be1db20782a0eeb)\ ) - Aaron Villalpando\ \ [0.87.0](https://github.com/boundaryml/baml/compare/0.86.1..0.87.0)\ - 2025-05-06\ ---------------------------------------------------------------------------------\ \ ### Miscellaneous Chores\ \ * run integ tests during the release workflow (#1897) - ([9645621](https://github.com/boundaryml/baml/commit/964562186583d399ce7f6fe7984d71cce92d1a5a)\ ) - Samuel Lijin\ * fix concurrency groups (#1902) - ([8104859](https://github.com/boundaryml/baml/commit/8104859fb2b99cf9f5701581300f6e4b99c30612)\ ) - Samuel Lijin\ \ ### Bugfixes\ \ * \[Go\] Fix optional struct fields (#1889) - ([7105b13](https://github.com/boundaryml/baml/commit/7105b13cb991e70be0cfaf338321aee6a3effbe9)\ ) - Todd Berman\ * \[Go\] Fix go enum encoding (#1892) - ([f198ba3](https://github.com/boundaryml/baml/commit/f198ba33eea9666406fefc3da6a08c152fd63b3a)\ ) - Todd Berman\ * \[Go\] Fix union encoding/decoding (#1898) - ([6a7dc25](https://github.com/boundaryml/baml/commit/6a7dc25e0baf61ab095b6c21a214f2f75e15b247)\ ) - Todd Berman\ * \[Python\] Export BamlClientFinishReason (#1907) - ([3c08e83](https://github.com/boundaryml/baml/commit/3c08e8307ca1c801d0acc15951df43f59048fb01)\ ) - aaronvg\ * make vertex http resonse parsing more lenient (#1909) - ([dd26a2d](https://github.com/boundaryml/baml/commit/dd26a2dbc4e860c9b2d97832cfc43e93c1b9f099)\ ) - aaronvg\ \ ### Features\ \ * \[feature\] Expose all types via type-builder (not just dynamic) (#1893) - ([a635a06](https://github.com/boundaryml/baml/commit/a635a06efb859b9d4fa246c89b45739c95f5eb22)\ ) - hellovai\ * Enable LSP Downloading to keep versions in sync (all platforms except windows) (#1910) - ([2a4771b](https://github.com/boundaryml/baml/commit/2a4771b8d9b41e2903f7a0f42ae36b6a46afbe95)\ ) - aaronvg\ \ [0.86.1](https://github.com/boundaryml/baml/compare/0.86.0..0.86.1)\ - 2025-04-30\ ---------------------------------------------------------------------------------\ \ ### Bugs\ \ * Fix arguments for functions from go (#1884) - ([b83557c](https://github.com/boundaryml/baml/commit/b83557c2c2ff279e49a7e589f5d6f06e1bd59fba)\ ) - Todd Berman\ * Bump version to 0.86.1 - ([af4c366](https://github.com/boundaryml/baml/commit/af4c366c2633b6049dbdb87b8a8e0fb4ad08c286)\ ) - Aaron Villalpando\ \ [0.86.0](https://github.com/boundaryml/baml/compare/0.85.0..0.86.0)\ - 2025-04-30\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * fix union streaming bug where unions wouldn’t stream until they were done (#1858)\ * Fix codegen when streaming done types (#1861) - ([d6c4ff3](https://github.com/boundaryml/baml/commit/d6c4ff30ebdaa4b90440b92b2d2045eca0205775)\ ) - Greg Hale\ * Go Encode/Decode fixes (#1865) - ([8ecb065](https://github.com/boundaryml/baml/commit/8ecb065d89cc10b9e306c6155146122ee3427a0f)\ ) - Todd Berman\ * Fix bedrock stalled stream protection not working with custom http client, and support additional\_model\_request\_fields (#1877) - ([da15434](https://github.com/boundaryml/baml/commit/da1543470ff2a3601808e6ebc04548c1a56a445f)\ ) - aaronvg\ * Remove run command from CLI (#1879) - ([7684d71](https://github.com/boundaryml/baml/commit/7684d71c615c0dc4d093a2316cf06054292c74ae)\ ) - hellovai\ * \[Rust LSP\] Support generateCodeOnSave setting, clean up error messages (#1881) - ([784f1b1](https://github.com/boundaryml/baml/commit/784f1b1ccbb2361254020a2a389f8b2633c8a39a)\ ) - aaronvg\ \ ### Features\ \ * Download the right LSP and CLI depending on the project version (#1738) - ([429936d](https://github.com/boundaryml/baml/commit/429936dcfa802db5a51b9c250ce52ca5657fd3de)\ ) - Antonio Sarosi\ * make gcp auth work seamlessly from vscode (#1860) - ([484c449](https://github.com/boundaryml/baml/commit/484c44987dcf5b87512d333cc71bc2f2717c58a7)\ ) - Samuel Lijin\ \ [0.85.0](https://github.com/boundaryml/baml/compare/0.84.4..0.85.0)\ - 2025-04-23\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * make playground env var reveal toggle visibility on the correct row (#1816) - ([5c3794a](https://github.com/boundaryml/baml/commit/5c3794a10b2257b8f3ef9c4cc8bc49429359dbe3)\ ) - Samuel Lijin\ * Fix issue where playground proxy wasn’t actually used which caused CORS issues (#1841) - ([1657e35](https://github.com/boundaryml/baml/commit/1657e3529476ec1aa9ccdd2059e50795a3a5a0b9)\ ) - aaronvg\ * add support for plumbing through some errors for go (#1844) - ([766ba08](https://github.com/boundaryml/baml/commit/766ba08f4fb7062d977cc834e3016211d06ac27f)\ ) - hellovai\ \ ### Features\ \ * move REST API out of preview and add docs on streaming (#1818) - ([55e9d9d](https://github.com/boundaryml/baml/commit/55e9d9da7055b3ad708890d769128c9d1a1be403)\ ) - Samuel Lijin\ * Support claude models via vertex apis (#1820) - ([c8378bc](https://github.com/boundaryml/baml/commit/c8378bc4d049d6c254cb30b4fc4c3eaa95af1ff2)\ ) - Samuel Lijin\ * Support HTTPS\_PROXY and HTTP\_PROXY system proxies in AWS client by delegating to the reqwest client (#1827) - ([c5c7fc6](https://github.com/boundaryml/baml/commit/c5c7fc63138a391f16c432ba3cc84376189ef6b8)\ ) - aaronvg\ * Make Typescript generator have a `outputFormat "esm"` field to use ES Module-friendly imports (#1831) - ([d27e729](https://github.com/boundaryml/baml/commit/d27e729b9bb6d50fac0059401c4a8ca1269d8168)\ ) - aaronvg\ * Support ruby 3.4 (#1830) - ([960c7d8](https://github.com/boundaryml/baml/commit/960c7d8bc2adde79c1f62b1ed6887fde212ececb)\ ) - aaronvg\ \ ### Miscellaneous\ \ * Test collector using openai-generic client (groq) (#1813) - ([430e428](https://github.com/boundaryml/baml/commit/430e4288b3a8b17166832bd61beda1a36fa4d1c6)\ ) - aaronvg\ * Document jinja in checks and asserts (#1826) - ([b27c980](https://github.com/boundaryml/baml/commit/b27c98073519120914ad29fae0ca627fc1757b57)\ ) - Greg Hale\ * only print out vertex auth errors if it failed to auth completely (#1843) - ([e42a594](https://github.com/boundaryml/baml/commit/e42a594475557c75c04f2aeeafc77ffae7fdb0d9)\ ) - aaronvg\ * Bump version to 0.85.0 - ([654fec2](https://github.com/boundaryml/baml/commit/654fec219d88ff90fa64fdf77aa49a124cbd0d45)\ ) - Aaron Villalpando\ \ [0.84.4](https://github.com/boundaryml/baml/compare/0.84.3..0.84.4)\ - 2025-04-17\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * make vscode proxy work again (#1806) - ([667851d](https://github.com/boundaryml/baml/commit/667851d2902c2eec26db3db7e98855ec3657ff8f)\ ) - Samuel Lijin\ * BAML gem supports ruby 3.4 (#1804) - ([eae1cec](https://github.com/boundaryml/baml/commit/eae1cec03c5993ee6aff3dfe50a0202483b26412)\ ) - Dimitri Roche\ \ [0.84.3](https://github.com/boundaryml/baml/compare/0.84.2..0.84.3)\ - 2025-04-16\ ---------------------------------------------------------------------------------\ \ ### Miscellaneous Chores\ \ * reduce warnings when compiling non-wasm (#1796) - ([1cf28bb](https://github.com/boundaryml/baml/commit/1cf28bb080256734e6dcdcce8e4e61acab80b85f)\ ) - Samuel Lijin\ \ ### Bugfixes\ \ * \[bug\] fix downloader for go binary (#1797) - ([f5654c8](https://github.com/boundaryml/baml/commit/f5654c83b3ef13c5ed864be70f8f9bb502094efd)\ ) - hellovai\ * Support multiroot workspaces in the new Rust LSP (#1798) - ([691dece](https://github.com/boundaryml/baml/commit/691dece5783170d67db666290a85e1a20351fbeb)\ ) - aaronvg\ * Bump version to 0.84.3 - ([bdacb0c](https://github.com/boundaryml/baml/commit/bdacb0c51fd25b0aa2890752cd63f61e46d043dc)\ ) - Aaron Villalpando\ \ [0.84.2](https://github.com/boundaryml/baml/compare/0.84.1..0.84.2)\ - 2025-04-16\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * Disable formatting in LSP due to incorrect behavior (#1793) - ([36f0fe4](https://github.com/boundaryml/baml/commit/36f0fe4593dca119b7e346b02e23dba1142b61a6)\ ) - aaronvg\ * Bump version to 0.84.2 - ([f5c484d](https://github.com/boundaryml/baml/commit/f5c484d408b1657c0a06fcc4108f9a3bbe1e668a)\ ) - Aaron Villalpando\ \ [0.84.1](https://github.com/boundaryml/baml/compare/0.84.0..0.84.1)\ - 2025-04-16\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * \[LSP\] Fix issue where vscode-generated baml\_client would have stale data (#1791) - ([93eb192](https://github.com/boundaryml/baml/commit/93eb192aa5ef1ed821393606c2f9b97dff552fbb)\ ) - aaronvg\ * Bump version to 0.84.1 - ([074a517](https://github.com/boundaryml/baml/commit/074a5171c2bd350133abe047766dbd057bc00d0b)\ ) - Aaron Villalpando\ \ [0.84.0](https://github.com/boundaryml/baml/compare/0.83.0..0.84.0)\ - 2025-04-16\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ * document `aws sso login` support (#1753) - ([ea0ddd1](https://github.com/boundaryml/baml/commit/ea0ddd1f800ca445de0be2a250fe0d37863d4ac7)\ ) - Samuel Lijin\ \ ### Features\ \ * New LSP Rust server (#1465) - ([bab6cc9](https://github.com/boundaryml/baml/commit/bab6cc9a8c692c0e02ecfaab6a1b983795d51875)\ ) - Greg Hale\ * Add BETA support for go (#1744) - ([b623e76](https://github.com/boundaryml/baml/commit/b623e76973a2788fcf2930408ad399975d46db0c)\ ) - hellovai\ * add stripe and propel webhook types (#1762) - ([e018d10](https://github.com/boundaryml/baml/commit/e018d10c6d821a3e937adae3ef295f63eb5960f0)\ ) - Samuel Lijin\ * allow copy-pasting a .env file into vscode (#1770) - ([bd449f0](https://github.com/boundaryml/baml/commit/bd449f096bc3c30281544716cf9fd1cb606e0e94)\ ) - Samuel Lijin\ * add explicit handling for newlines in env vars (#1775) - ([b2dc8d0](https://github.com/boundaryml/baml/commit/b2dc8d054429ad4663648dd72561793264e36cc0)\ ) - Samuel Lijin\ * handle edge cases in env var rendering (#1786) - ([427a6db](https://github.com/boundaryml/baml/commit/427a6db3ee63f4d9a9e2cfce5f171bda32e6d19e)\ ) - Samuel Lijin\ * LLM function composition (#1722) - ([63b4e44](https://github.com/boundaryml/baml/commit/63b4e44695d51b14d3cf18218d2815bca49c73c9)\ ) - Greg Hale\ \ ### Bugfixes\ \ * Use `AnyValue: {}` for the `any` type in OpenAPI (#1773) - ([145e887](https://github.com/boundaryml/baml/commit/145e88708eafe0437b58305d85ff6cb9fb6be42d)\ ) - Antonio Sarosi\ * \[bug-fix\] Fixed issue with enums not rendering in the prompt for some types (#1769) - ([857de40](https://github.com/boundaryml/baml/commit/857de4008186101bcd87d50f8776075455b22f9d)\ ) - hellovai\ * Parser for openai must have `created` as an optional field (#1778) - ([db2a0dc](https://github.com/boundaryml/baml/commit/db2a0dc02b1bb73aaf81ab9f16e522a6dbfe578b)\ ) - hellovai\ * Fix issue where shorthand clients always had missing api keys (#1787) - ([39b7959](https://github.com/boundaryml/baml/commit/39b7959f4223cbea26f6dbfb461697dcac43771b)\ ) - aaronvg\ \ [0.83.0](https://github.com/boundaryml/baml/compare/0.82.0..0.83.0)\ - 2025-04-09\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ * **(dynamic-types.mdx)** Fix unstable\_features.add\_json\_schema section (#1734) - ([5ab2c3e](https://github.com/boundaryml/baml/commit/5ab2c3ec453c112689ba3460432b1823afb38827)\ ) - Elijas Dapšauskas\ * **(fallbacks)** fix typos (#1735) - ([463ad96](https://github.com/boundaryml/baml/commit/463ad96ca4bfa816a4497d549980960a2e8eaab2)\ ) - Elijas Dapšauskas\ * update all docs with bun and deno (#1736) - ([44346ae](https://github.com/boundaryml/baml/commit/44346aefe22bfde052a9cd5a30d427e2573254ee)\ ) - Chris Watts\ \ ### Features\ \ * Playground now supports your aws profiles (no need to copy aws access key ids) (#1493) - ([53d3343](https://github.com/boundaryml/baml/commit/53d3343a304d6607460ca6ae25517577b22c6b1c)\ ) - Samuel Lijin\ * Playground Tests can now be run in parallel (#1717) - ([b944438](https://github.com/boundaryml/baml/commit/b94443886931572572d4ba3a928c65a8e8db71d3)\ ) - Rahul Tiwari\ \ ### Bug-fix\ \ * Fix self-loop cycle detections in type-system (#1725) - ([ad5da5d](https://github.com/boundaryml/baml/commit/ad5da5dc289bbf527badc6207de8d613c81f7572)\ ) - hellovai\ * Fix issue where setting baml\_log would be overwritten (#1732) - ([412d7f8](https://github.com/boundaryml/baml/commit/412d7f8fec2b046098b65258d32cf8f213a4e5a2)\ ) - aaronvg\ * Don’t allow parameters with checks/asserts (#1689) - ([e66a462](https://github.com/boundaryml/baml/commit/e66a462bad18e33404a3c4c1c966fef22d6883ca)\ ) - Antonio Sarosi\ * Fix whitespace in JSON keys by trimming during parsing (#1727) - ([5a93b0d](https://github.com/boundaryml/baml/commit/5a93b0d0e8a2011e58b42df94bc6fb09a26bff16)\ ) - mentatbot\[bot\]\ * Fix python codgen use `Literal` directly instead of `types.Literal`. (#1697) - ([b0e79a2](https://github.com/boundaryml/baml/commit/b0e79a271203e5af6878d3f5827124995fb48852)\ ) - hellovai\ * Support OpenSamba by parsing floats into ints (#1746) - ([28e3d0a](https://github.com/boundaryml/baml/commit/28e3d0a5e18796b8fb71ed57c7c2adad50a0d266)\ ) - Greg Hale\ \ [0.82.0](https://github.com/boundaryml/baml/compare/0.81.3..0.82.0)\ - 2025-04-01\ ---------------------------------------------------------------------------------\ \ ### Breaking changes\ \ * HTTPResponses have a HTTPBody object. You must now call `.json()` or `.text()` to access the http response message.\ \ | | |\ | --- | --- |\ | 1 | response = call.http\_response |\ | 2 | assert response is not None |\ | 3 | response\_body = response.body.json() |\ | 4 | assert isinstance(response\_body, dict) |\ | 5 | assert "candidates" in response\_body |\ \ ### Features\ \ * Support AWS Bedrock in the Collector API (#1703) - ([e7c45c2](https://github.com/boundaryml/baml/commit/e7c45c27a63aba273151f246834d9a049c763168)\ ) - aaronvg\ \ ### Bugfixes\ \ * Allow multiple unique block-level attributes (#1686) - ([f945204](https://github.com/boundaryml/baml/commit/f94520489bd597b7dc69fdaf7617c5a9edcf9079)\ ) - Greg Hale\ \ [0.81.3](https://github.com/boundaryml/baml/compare/0.81.2..0.81.3)\ - 2025-03-26\ ---------------------------------------------------------------------------------\ \ ### Bug fixes\ \ * Fix ts build arguments (#1682) - ([83db889](https://github.com/boundaryml/baml/commit/83db889fa3c7e594f2e6133ba1c736afc332e710)\ ) - aaronvg\ * Bump version to 0.81.3 - ([6a65cfa](https://github.com/boundaryml/baml/commit/6a65cfaed212e0df1f99cf4a0697e2e141533bbb)\ ) - Aaron Villalpando\ \ [0.81.2](https://github.com/boundaryml/baml/compare/0.81.1..0.81.2)\ - 2025-03-26\ ---------------------------------------------------------------------------------\ \ Bug fixes\ ---------\ \ * lower glibc for 2 more platforms (#1677) - ([516b125](https://github.com/boundaryml/baml/commit/516b125eb6b61932ed91a1ccdbd795d1bf236879)\ ) - aaronvg\ * Bump version to 0.81.2 - ([c70ed33](https://github.com/boundaryml/baml/commit/c70ed33282a33913784f0180a335204785d94d55)\ ) - Aaron Villalpando\ \ [0.81.1](https://github.com/boundaryml/baml/compare/0.81.0..0.81.1)\ - 2025-03-25\ ---------------------------------------------------------------------------------\ \ Bug fixes\ ---------\ \ * \[docs\] Fix broken links + add more docs for openai generic (#1667) - ([1d53ed8](https://github.com/boundaryml/baml/commit/1d53ed85a2e2419be24d141ccf45665bff18fdac)\ ) - hellovai\ * Make TS compatible with glibc 2.31+ (#1670) - ([a37cdb7](https://github.com/boundaryml/baml/commit/a37cdb762b4cf5c9bec5af760dbed0d9853e9165)\ ) - aaronvg\ \ [0.81.0](https://github.com/boundaryml/baml/compare/0.80.2..0.81.0)\ - 2025-03-24\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * make vertex work in vscode playground again (#1645) - ([7d6b4cb](https://github.com/boundaryml/baml/commit/7d6b4cb94660672d833972c50b69b3d0c7c6308a)\ ) - Samuel Lijin\ * improve error quality when vertex oauth exchange fails (#1647) - ([c96fdb4](https://github.com/boundaryml/baml/commit/c96fdb4420f84a964498535e636708a3df668a17)\ ) - Samuel Lijin\ * Playground should persist tests and functions across code errors (#1644) - ([8e8cdc3](https://github.com/boundaryml/baml/commit/8e8cdc3f269836f82d4c28e4b7efd5d978670d13)\ ) - Greg Hale\ * \[bug\] In BAML tests, functions with typebuilder wouldnt stream (#1660) - ([ffe81a3](https://github.com/boundaryml/baml/commit/ffe81a33289b2884b842c2073863778361057998)\ ) - hellovai\ * \[bug\] Fix log level prints (#1661) - ([cf8823e](https://github.com/boundaryml/baml/commit/cf8823e3ad4a1d023bd9da86fa971cb55dfac7d5)\ ) - hellovai\ * Fix add file button, drag and rename in fiddle frontend (#1656) - ([4e476dc](https://github.com/boundaryml/baml/commit/4e476dc0c436a582c18ed588fb079282e2c8890f)\ ) - Antonio Sarosi\ * Dont use require() for imports in TS files (#1665) - ([b628def](https://github.com/boundaryml/baml/commit/b628def1ba58e288caf8ae452d1f4889d0431f66)\ ) - aaronvg\ \ ### Features\ \ * add media (image/audio) support for React/Next.js (#1646) - ([c3b9011](https://github.com/boundaryml/baml/commit/c3b9011cc00f45d5b3381248bdf35107fb831739)\ ) - Chris Watts\ * move browser baml Image from @boundaryml/baml to generated code (#1663) - ([f503cdc](https://github.com/boundaryml/baml/commit/f503cdc97821f4177368977f2f45ad9c0fff4ae5)\ ) - Chris Watts\ \ ### Docs\ \ * \[docs\] improve documentation for llm clients and highlight openai-generic compatability (#1655) - ([a760f84](https://github.com/boundaryml/baml/commit/a760f84c045e3d4ab7a3779959a5fa954f23c4b5)\ ) - hellovai\ \ [0.80.2](https://github.com/boundaryml/baml/compare/0.80.1..0.80.2)\ - 2025-03-20\ ---------------------------------------------------------------------------------\ \ Bug Fixes\ ---------\ \ * Fix cases where collector failed in an unrecoverable way (#1633) - ([03a11d5](https://github.com/boundaryml/baml/commit/03a11d5b56bae986405adfbf97bafc604bbd4f41)\ ) - hellovai\ * Fix exit codes and error logging for baml cli (#1636) - ([6c3c6d5](https://github.com/boundaryml/baml/commit/6c3c6d5d1d11a8c036659d9c9eba87b65e179ac8)\ ) - aaronvg\ * Added `from __future__ import annotations` to support python 3.9 (#1642) - ([daf2b34](https://github.com/boundaryml/baml/commit/daf2b34cbe70700477301c712a0a17cd69eb0f17)\ ) - hellovai\ * Bump version to 0.80.2 - ([0e72137](https://github.com/boundaryml/baml/commit/0e721378008fd900554e98a005a9a01a9f3e7a84)\ ) - Aaron Villalpando\ \ [0.80.1](https://github.com/boundaryml/baml/compare/0.80.0..0.80.1)\ - 2025-03-19\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Fix streaming for dynamic types (#1606) - ([eac4bbf](https://github.com/boundaryml/baml/commit/eac4bbfd99c0b6f54cd3ab5962eb7d52d6e72216)\ ) - hellovai\ \ [0.80.0](https://github.com/boundaryml/baml/compare/0.79.0..0.80.0)\ - 2025-03-18\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Removed default params from python code gen (#1627) - ([ff613ce](https://github.com/boundaryml/baml/commit/ff613ce9df7f7d1c4e036ca8f92c1bd3c38ad4a4)\ ) - hellovai\ \ ### Documentation\ \ * Add docs for with\_options, and for the Collector (#1601) - ([b19d1ee](https://github.com/boundaryml/baml/commit/b19d1ee3031a35b8afa9e6b74240fa0a67429a77)\ ) - aaronvg\ \ [0.79.0](https://github.com/boundaryml/baml/compare/0.78.0..0.79.0)\ - 2025-03-18\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Add a way to create a `b` baml\_client with a default set of options (#1595) - ([0f2c730](https://github.com/boundaryml/baml/commit/0f2c730ef4da47f1bd78632d5831c05d1d2d2765)\ ) - aaronvg\ * Expose Prompt and Parser separately so people can use their own http clients or use Batch APIs (#1505) - ([8e48147](https://github.com/boundaryml/baml/commit/8e4814705fbffb87d0afa4b107e6f2509f3f82d9)\ ) - Antonio Sarosi\ * Add support for manually configuring log level via code (#1600) - ([d036c4f](https://github.com/boundaryml/baml/commit/d036c4f9f68e84df1c2777d1ea708eb2adc5510c)\ ) - hellovai\ * implement baml-cli test to run BAML-defined tests via terminal (#1458) - ([1ecde1c](https://github.com/boundaryml/baml/commit/1ecde1c1c5ccd93eae4e38ae1e9f2f6c5de799ab)\ ) - Samuel Lijin\ * Add typescript collector to expose tokens (#1573) - ([90b7434](https://github.com/boundaryml/baml/commit/90b74345270492fe606977f1aa24bc0ccb54a6b6)\ ) - aaronvg\ * Add ruby collector to expose tokens (#1587) - ([ab7a269](https://github.com/boundaryml/baml/commit/ab7a269e78ba645044dd6156afba2979bfd1f972)\ ) - aaronvg\ * support lazily loading env vars in python (#1558) - ([12ab33f](https://github.com/boundaryml/baml/commit/12ab33f6a81479ec0aec977d9f1a93b654a1119f)\ ) - hellovai\ * Add version checking and safe import mechanism for Python generators (#1591) - ([f681243](https://github.com/boundaryml/baml/commit/f6812435622cdedbac9072852f3c71c72047ad4e)\ ) - hellovai\ \ ### Bug Fixes\ \ * propagate finish reason correctly, add tests to ensure correct deserialization (#1566) - ([b80a2ef](https://github.com/boundaryml/baml/commit/b80a2efac5ff9663522b10304a1b381ce60c35b7)\ ) - hellovai\ * google-vertex docs (#1571) - ([2a3c865](https://github.com/boundaryml/baml/commit/2a3c8652e4a1604624f669a4cae0bd835167bd83)\ ) - Ben Epstein\ * fix docs for assert and deno (#1609)\ * fix wasm build, and add playground to docs (#1616)\ * vertex auth should log when a given strategy fails (#1577) - ([23c857d](https://github.com/boundaryml/baml/commit/23c857dc3d710123055f2e44f1fd73305925c271)\ ) - Samuel Lijin\ * Add default values to function parameters in python clients (#1579) - ([14eba7e](https://github.com/boundaryml/baml/commit/14eba7e58ae3ba627143b028cf51f8840bf283ab)\ ) - Greg Hale\ * Maintain attribute information when combining fields (#1585) - ([4153bd3](https://github.com/boundaryml/baml/commit/4153bd379223c422168067060f49dad4cac14407)\ ) - Antonio Sarosi\ * \[BUGFIX\] Fix a “null”-rendering issue (#1575) - ([09db83e](https://github.com/boundaryml/baml/commit/09db83e2acc7cb6c02f08e045904ac8d2ee10158)\ ) - Greg Hale\ * Fix event handling in BamlStream to use non-blocking queue retrieval (#1596) - ([05460cd](https://github.com/boundaryml/baml/commit/05460cd90d51f8dd9e7bcb5d90d993688184d1eb)\ ) - hellovai\ * Fix partial recursive aliases and broken Python integ test (#1598) - ([4a9d451](https://github.com/boundaryml/baml/commit/4a9d45145322df41dc1e2e36f46779a718b3041e)\ ) - Antonio Sarosi\ * Fix partial recursive aliases codegen (#1611) - ([1839acf](https://github.com/boundaryml/baml/commit/1839acf3a11ca5e278e027d38f284c724b5c066c)\ ) - Antonio Sarosi\ * Fix ambiguous literal string parsing (#1623) - ([c0cac50](https://github.com/boundaryml/baml/commit/c0cac50f786bcda5e05dfb204c8974e82d377947)\ ) - Antonio Sarosi\ \ ### Miscellaneous Chores\ \ * speed up ruby dev builds (#1597) - ([73eb09c](https://github.com/boundaryml/baml/commit/73eb09c9d432edd4ad98a49b66cdf0b10c7a459e)\ ) - Samuel Lijin\ \ ### Docs\ \ * RAG example (#1581) - ([56a8c75](https://github.com/boundaryml/baml/commit/56a8c75f0c82a7db6f68064c8981972422458240)\ ) - Prashanth Rao\ * baml tool calling control flow image (#1563) - ([754171a](https://github.com/boundaryml/baml/commit/754171ac409f168c09cc5ac5681724356d71d681)\ ) - Ben Epstein\ * Update README.md - Align Chat Agent Example with ReplyTool Model (#1570) - ([166cdaa](https://github.com/boundaryml/baml/commit/166cdaa250011e8cb21615c13b7d417af7a4592b)\ ) - Andriy Tkach\ * Fix tutorial icon (#1594) - ([3500413](https://github.com/boundaryml/baml/commit/35004137abff0ac84914bf665008ea69524f521e)\ ) - Michael Yen\ * Update BAML documentation to clarify recursive class definitions and map type in TypeBuilder (#1605) - ([c5fb371](https://github.com/boundaryml/baml/commit/c5fb37165ccfa376f77f46b2ea387a90748808cb)\ ) - hellovai\ * Remove redundant model for RAG example (#1583) - ([6c6c5c2](https://github.com/boundaryml/baml/commit/6c6c5c29f8d1689f6e3fc9b6056b28faacbf746c)\ ) - Prashanth Rao\ \ [0.78.0](https://github.com/boundaryml/baml/compare/0.77.0..0.78.0)\ - 2025-03-05\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * **(docs)** fix broken links (/ref/baml-client -> /ref/baml\_client) and broken code (missing comma) (#1522) - ([a881571](https://github.com/boundaryml/baml/commit/a88157159a660b50d09e88ff107c18f698bea6ee)\ ) - Elijas Dapšauskas\ * Fix broken Next JS Guide Link\ * Allow types to have multiple block-level constraints (#1545) - ([e4dc633](https://github.com/boundaryml/baml/commit/e4dc633807fb9430a414a77d0fed9d43b0361422)\ ) - Greg Hale\ * Resolve all non-google file uris when calling gemini Fixes #1548 (#1553) - ([0fe8e10](https://github.com/boundaryml/baml/commit/0fe8e105593ba233eafcd6f8fadad77c318a2e99)\ ) - hellovai\ \ ### Features\ \ * **(runtime)** claude now supports image URLs in requests (#1542) - ([c2d35d4](https://github.com/boundaryml/baml/commit/c2d35d4e4b9de908ae1c56a56edbc3f21139f36d)\ ) - Samuel Lijin\ * (Python) Expose tokens / prompt / http response etc through the Collector interface - (pre-alpha release) (#1512) - ([9b21ace](https://github.com/boundaryml/baml/commit/9b21ace306dee4cdcc0c24960da8794bc9cd9028)\ ) - aaronvg\ * Support thinking models from anthropic. (#1555) - ([be1119f](https://github.com/boundaryml/baml/commit/be1119f89ca46cd147c51589dc8c47c1e5f6f3ea)\ ) - hellovai\ * Support VSCode Rename for enums & type aliases (#1552) - ([80ba612](https://github.com/boundaryml/baml/commit/80ba6121c079c82e61dbaec74012f0c0a50c088c)\ ) - Antonio Sarosi\ * Parser improvements (#1536) - ([8f758ef](https://github.com/boundaryml/baml/commit/8f758ef29cee811c124c234304d65bca281ee8d6)\ ) - hellovai\ \ [0.77.0](https://github.com/boundaryml/baml/compare/0.76.2..0.77.0)\ - 2025-02-25\ ---------------------------------------------------------------------------------\ \ ### Bug fixes\ \ * Fix truthy bug in jinja and improve static analysis (#1503) - ([b8e3423](https://github.com/boundaryml/baml/commit/b8e34231ef10f80dc2aaaba6bcd84618381f933c)\ ) - Greg Hale\ * Rename Null to None in jinja (#1504) - ([f42567d](https://github.com/boundaryml/baml/commit/f42567d40195841527b9193be154dc517155907a)\ ) - Greg Hale\ * Fixed React Codegen in VSCode (#1490) - ([74b3dbf](https://github.com/boundaryml/baml/commit/74b3dbf35875078e7e4b5be542c2d73702ff82b8)\ ) - Chris Watts\ * Release python GIL more liberally in baml\_client.sync\_client (#1501) - ([4d7f3d3](https://github.com/boundaryml/baml/commit/4d7f3d361a72cb82839730fcafdbd3915969cfcb)\ ) - hellovai\ \ ### Features\ \ * VSCode Proxy can now be configured via API Keys UX (#1489) - ([8671527](https://github.com/boundaryml/baml/commit/867152734405c9cf24ecd836e85dadae9315950d)\ ) - hellovai\ * Support renaming of BAML class via LSP (#1518) - ([339068a](https://github.com/boundaryml/baml/commit/339068ac8165f6766f8efbba4e1417745fcc95a3)\ ) - Antonio Sarosi\ \ ### Docs / Improvements\ \ * update python installation instruction to use correct package name (#1508) - ([cd1a21b](https://github.com/boundaryml/baml/commit/cd1a21bebc1e7b2c6a94109f7457812ae889b92c)\ ) - Elijas Dapšauskas\ * fix typo (mutliplier -> multiplier) (#1510) - ([c6d4126](https://github.com/boundaryml/baml/commit/c6d41264f8405da0312b00f0a845d18a270ea79f)\ ) - Elijas Dapšauskas\ * Update ruby.mdx (#1506) - ([22b35a4](https://github.com/boundaryml/baml/commit/22b35a43518217d75b0050ec03da138991b53e48)\ ) - aaronvg\ * Update overview.mdx (#1507) - ([2b19892](https://github.com/boundaryml/baml/commit/2b1989238b8bced47e08dbff58b5f856a337e139)\ ) - aaronvg\ * remove await in python snippet in typebuilder.mdx (#1495) - ([d30220d](https://github.com/boundaryml/baml/commit/d30220d980cc3a06a0bb8f7a873c4f9229bbbd50)\ ) - hellovai\ \ [0.76.2](https://github.com/boundaryml/baml/compare/0.76.1..0.76.2)\ - 2025-02-18\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * fix openapi parser for baml\_options (#1484) - ([c8d2e13](https://github.com/boundaryml/baml/commit/c8d2e1375aa7162e22e4a32133c0f768dd46623b)\ ) - hellovai, invakid404\ \ [0.76.1](https://github.com/boundaryml/baml/compare/0.76.0..0.76.1)\ - 2025-02-18\ ---------------------------------------------------------------------------------\ \ ### Bugs\ \ * Attempt to fix release script for TS (#1479) - ([e048080](https://github.com/boundaryml/baml/commit/e0480801552f21fb818f904531727d9397628935)\ ) - aaronvg\ \ [0.76.0](https://github.com/boundaryml/baml/compare/0.75.0..0.76.0)\ - 2025-02-18\ ---------------------------------------------------------------------------------\ \ We added a new NextJS generator and deep support for Typebuilder!! Read the docs to learn more about it!\ \ ### Bug Fixes\ \ * Default max\_tokens to null for openai providers (azure defaults to 4069 still) (#1438) - ([1ee0124](https://github.com/boundaryml/baml/commit/1ee01242ceca4bd39eed110deeabb30888d35ba1)\ ) - Chris Watts\ * Rest/OpenAPI: Fix the way we parse providers for during reading client-registry (#1428) - ([9ec9927](https://github.com/boundaryml/baml/commit/9ec992746beb0e54772bfe92586d47079643f6a2)\ ) - hellovai\ * Fix typescript partial types codegen (#1437) - ([078eef7](https://github.com/boundaryml/baml/commit/078eef7d046bab7816bd6c105bf996962fdfe97f)\ ) - Greg Hale\ * import typealias correctly for python 3.8+ from typing\_extensions Fixes #1448 (#1451) - ([2b1d51d](https://github.com/boundaryml/baml/commit/2b1d51d12b95cc2fb21c8f73658441b530fbcc07)\ ) - hellovai\ * Enhance error handling and validation for duplicate definitions (#1462) - ([9f6443c](https://github.com/boundaryml/baml/commit/9f6443c51324e8323c50d186c1c10afe39ad6861)\ ) - hellovai\ * Fix default None and Optional Nesting in python partial types (#1459) - ([06a311b](https://github.com/boundaryml/baml/commit/06a311bd159082d8a9925b7283953b4754340387)\ ) - Greg Hale\ * Show nicer error message when VSCode extension crashes (#1467) - ([d14a913](https://github.com/boundaryml/baml/commit/d14a913401930a185df4df4c7fe0bce6f4ecc1e2)\ ) - Antonio Sarosi\ \ ### Documentation\ \ * Improve docs for Chain-of-thought prompting Fixes #1412 (#1445) - ([79083b1](https://github.com/boundaryml/baml/commit/79083b13a37c42d603f24b44e27a02993acc2ac3)\ ) - hellovai\ * Update README.md (#1430) - ([f5f9291](https://github.com/boundaryml/baml/commit/f5f92911e637028627641c12ac30123d0607e2e3)\ ) - Yasser Shalabi\ \ ### Features\ \ * NextJS Generator (read the docs!) (#1346) - ([0b792de](https://github.com/boundaryml/baml/commit/0b792decf96ebd2c84e6b9388b996612910e52f8)\ ) - Chris Watts\ * Implement `TypeBuilder::add_baml` (#1449) - ([da76b96](https://github.com/boundaryml/baml/commit/da76b963f98a916cefdc5a763f7e97f1333e9283)\ ) - Antonio Sarosi\ * Add a TypeBuilder string representation! (#1260) - ([fca8b91](https://github.com/boundaryml/baml/commit/fca8b91eede7ebe26393e332497b64c7e6edf0e6)\ ) - afyef\ * Add ClientHttpError support across language clients (#1443) - ([1d481f1](https://github.com/boundaryml/baml/commit/1d481f1994ba90bb135aa4340d646f7768692b6a)\ ) - hellovai\ * Add duration display option to test panel tabular view (#1463) - ([4d5c993](https://github.com/boundaryml/baml/commit/4d5c9931a7f1f6d07f597309ef5ca6260bf5e5c9)\ ) - hellovai\ * Hide API credentials from frontend rendering for raw curl (#1431) - ([03735fe](https://github.com/boundaryml/baml/commit/03735feb5b9e70ad6a872e1c5d0837eea43034df)\ ) - Greg Hale\ * Support overriding `media_type` when using from\_url() Fixes #1436 (#1444) - ([c913f09](https://github.com/boundaryml/baml/commit/c913f09389ce0d63498e1aede6d61008b6b3f3f0)\ ) - hellovai\ * Adding support for Azure AI Foundary (#1469) - ([92e139a](https://github.com/boundaryml/baml/commit/92e139aa61dc85e79de9bc9d3d5305f61e34854d)\ ) - hellovai\ * Add client response type validation and support for LLM clients (#1473) - ([2987d59](https://github.com/boundaryml/baml/commit/2987d591718440a77cea77b0f30768904b06e0bb)\ ) - hellovai\ \ [0.75.0](https://github.com/boundaryml/baml/compare/0.74.0..0.75.0)\ - 2025-02-06\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Implement tests for dynamic types (#1343) - ([7f852d0](https://github.com/boundaryml/baml/commit/7f852d02892637b3a6e9637e59b26c2ec822e626)\ ) - Antonio Sarosi\ \ ### Bug Fixes\ \ * issue with o1 models not accepting max\_tokens (#1410) - ([3831243](https://github.com/boundaryml/baml/commit/383124339dd71a5097f61a75b2e5c7121f5e9a8d)\ ) - Chris Watts\ * Fix panic when recursive type alias is used as class field (#1399) - ([f36f80c](https://github.com/boundaryml/baml/commit/f36f80c7d1f8fa4d5b4f52baaac3772cd054f8cf)\ ) - Antonio Sarosi\ * Fix infinite cycles in client fallbacks (#1401) - ([7b7eec0](https://github.com/boundaryml/baml/commit/7b7eec01412e52429f447c7edebfead7f96e2601)\ ) - Antonio Sarosi\ * Fix panic when using type alias that points to enum (#1407) - ([8994ba6](https://github.com/boundaryml/baml/commit/8994ba6011c70d22e5d9852c0e15b54b683addbb)\ ) - Antonio Sarosi\ * Track Pending fields in Semantic Streaming (#1411) - ([026bc21](https://github.com/boundaryml/baml/commit/026bc21c4b9d5c687c413342a202b6b09f5504b0)\ ) - Greg Hale\ * In prompt rendering, recurse into recursive type alias unions (#1416) - ([a648559](https://github.com/boundaryml/baml/commit/a6485597c0e44c9b44ba9fc89dbe423b3dd9b61e)\ ) - Antonio Sarosi\ \ ### Documentation\ \ * Fix typos in README.md (#1402) - ([cc132ad](https://github.com/boundaryml/baml/commit/cc132ad2d035df42b67ef37f1c696b496e08a4ca)\ ) - Prashanth Rao\ \ [0.74.0](https://github.com/boundaryml/baml/compare/0.73.5..0.74.0)\ - 2025-01-30\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Add dark mode to docs (#1382) - ([c684e2d](https://github.com/boundaryml/baml/commit/c684e2d2d35fd9d62e2aae01b4025e5302c3740b)\ ) - Chris Watts\ * dedent strings parsed within triple quote blocks (#1395) - ([8ce04a9](https://github.com/boundaryml/baml/commit/8ce04a951ef9ac7dc2eab934c8163af2440b52bb)\ ) - hellovai\ * Update README with better details (#1380) - ([02d1950](https://github.com/boundaryml/baml/commit/02d19503759986c0dba3b022afb03f45a52c31ad)\ ) - hellovai\ * Semantic Streaming (#1293) - ([e30bdd5](https://github.com/boundaryml/baml/commit/e30bdd526910f11a6a9057cc4df90cf302939666)\ ) - Greg Hale\ \ ### Bugfixes\ \ * Drop unnecessary jsonwebtoken dep in wasm build (#1381) - ([7b85c71](https://github.com/boundaryml/baml/commit/7b85c715e07be8f908ee114c50b85bd784cf567b)\ ) - Greg Hale\ * Removing broken links (#1388) - ([e4b0b5b](https://github.com/boundaryml/baml/commit/e4b0b5ba390d3449247bfebb1f24013df69b6068)\ ) - hellovai\ * Reduce JS client memory usage considerably during streaming (#1390) - ([3165e0f](https://github.com/boundaryml/baml/commit/3165e0f3126d94691bdd1e0a1411ee6de8ed0dea)\ ) - aaronvg\ * Fix issue with semantic-streaming on unions of classes (#1393) - ([39b499d](https://github.com/boundaryml/baml/commit/39b499de396973bc1d1da991079a8d587cb29d75)\ ) - Greg Hale\ * Fix issue where output panel pops open in cursor (#1394) - ([5fd5c46](https://github.com/boundaryml/baml/commit/5fd5c4672887050db533bda4c6f0f46b7ef18644)\ ) - hellovai\ \ [0.73.5](https://github.com/boundaryml/baml/compare/0.73.4..0.73.5)\ - 2025-01-27\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * Fix Google AI system prompt JSON (#1374) - ([fe366fe](https://github.com/boundaryml/baml/commit/fe366fe4036b2c9d6863a0d3246df2526bdcb3a4)\ ) - Antonio Sarosi\ * show token usage in the playground card view (#1376) - ([0500a87](https://github.com/boundaryml/baml/commit/0500a87d98c6198807a04268f23a436fb260bec3)\ ) - aaronvg\ * Bump version to 0.73.5 - ([a32aebf](https://github.com/boundaryml/baml/commit/a32aebf51d0f6b5471fe884fa8a0da21aa45c753)\ ) - Aaron Villalpando\ \ [0.73.4](https://github.com/boundaryml/baml/compare/0.73.3..0.73.4)\ - 2025-01-22\ ---------------------------------------------------------------------------------\ \ Fix another issue where playground could rerender over and over\ \ [0.73.3](https://github.com/boundaryml/baml/compare/0.73.2..0.73.3)\ - 2025-01-22\ ---------------------------------------------------------------------------------\ \ Fix issue where playground could rerender over and over\ \ ### Bug Fixes\ \ * fix rerendering of component causing performance issue in the playground (#1368)\ \ [0.73.2](https://github.com/boundaryml/baml/compare/0.73.1..0.73.2)\ - 2025-01-22\ ---------------------------------------------------------------------------------\ \ ### Bugfixes\ \ * Gemini should use system message (#1364) - ([b29fb18](https://github.com/boundaryml/baml/commit/b29fb18386634e6e75cc9149b09592889619ba22)\ ) - hellovai\ * Add more explanations to the tool use doc (#1324) - ([bf048a6](https://github.com/boundaryml/baml/commit/bf048a6871f4073807ce1acbe39a411ace42406e)\ ) - Ben Epstein\ * Improve playground performance in vscode (#1366) - ([ba2b0f1](https://github.com/boundaryml/baml/commit/ba2b0f17f8db321705f8c037c6ede5e6a34e2590)\ ) - aaronvg\ * Bump version to 0.73.2 - ([a877ca9](https://github.com/boundaryml/baml/commit/a877ca9b35ec7d643f80c1225d8de4b1b244486f)\ ) - Aaron Villalpando\ \ [0.73.1](https://github.com/boundaryml/baml/compare/0.73.0..0.73.1)\ - 2025-01-22\ ---------------------------------------------------------------------------------\ \ High-level Overview\ -------------------\ \ This release includes V2 of our VSCode Playground! It includes\ \ * dark mode\ * test history\ * better rendering of errors, including markdown output renderer\ * cleaner UI\ * highlighting of inputs in prompts\ * Condensed table view to see results\ * Test navigation sidebar, to more quickly jump to different tests\ * many bugfixes and stability issues!\ \ See below for what we fixed and improved across all parts of BAML\ \ ### Documentation\ \ * gemini generationConfig (#1348) - ([d3c7e1c](https://github.com/boundaryml/baml/commit/d3c7e1ca272ec191c60eb0a17e46c654db438217)\ ) - Abhishek Tripathi\ * add baml-cli fmt docs (#1299) - ([a25e2bc](https://github.com/boundaryml/baml/commit/a25e2bc9389dffce633a8c1cdfa77456998d82fa)\ ) - hellovai\ * Add more info on what forwarded options vs nonforwarded means (#1321) - ([9f39cb7](https://github.com/boundaryml/baml/commit/9f39cb7b3c6d9d9d7a53c73ac374458a0f56e7d8)\ ) - aaronvg\ * Update cursor IDE instructions (#1331) - ([98b7783](https://github.com/boundaryml/baml/commit/98b778397feb6bfeca9fd88a808546469c9f173b)\ ) - aaronvg\ \ ### Features\ \ * New Playground V2 (#1304) - ([fa22c4f](https://github.com/boundaryml/baml/commit/fa22c4f741dd939bc5b2122a6625f998c8071625)\ ) - aaronvg\ * update aws provider docs with credentials information (#1298) - ([aee52a3](https://github.com/boundaryml/baml/commit/aee52a3dc8417a32bc68cfdd43208ae1a5e3fd6e)\ ) - Chris Watts\ * implement a gcp auth chain for vertex-ai clients (#1328) - ([6dfa23b](https://github.com/boundaryml/baml/commit/6dfa23b1005fce7ba662cfe8efd666cf0b0a8d0b)\ ) - Samuel Lijin\ \ ### Miscellaneous Chores\ \ * (dx) split out integ tests into provider specific (#1296) - ([2c6279c](https://github.com/boundaryml/baml/commit/2c6279c53a5d9baea5317d5c25d8a9d3b4899c02)\ ) - Samuel Lijin\ * add readmes for all relevant folders (#1302) - ([7165331](https://github.com/boundaryml/baml/commit/7165331fed459d2d3d2618774c2a6f9ec01d7fab)\ ) - Chris Watts\ * remove ai generated readme (#1306) - ([e0bf112](https://github.com/boundaryml/baml/commit/e0bf11278761777284c6e157fdd0bbf3354e8b98)\ ) - Chris Watts\ * fix elided-named-lifetimes and ban it (#1341) - ([ba303f0](https://github.com/boundaryml/baml/commit/ba303f0b44ecfcea248e17f3b9dedf558b28f63c)\ ) - Samuel Lijin\ \ ### Bug\ \ * update 404 link on docs (#1309) - ([65e2a1a](https://github.com/boundaryml/baml/commit/65e2a1ac2b2a158ea6f42193634dd21ff77d35b5)\ ) - hellovai\ * finish\_reason\_allow\_list and finish\_reason\_deny\_list should be case insensitive (#1333) - ([1cbb268](https://github.com/boundaryml/baml/commit/1cbb268be01b5f46e59e696cc83424ffe814c81c)\ ) - hellovai\ * windows generator bugfix (#1311) - ([ab64540](https://github.com/boundaryml/baml/commit/ab64540327f38a5bb8ca3452ad2c5a52d481bb9b)\ ) - aaronvg\ * Type-narrowing for `if` blocks (#1313) - ([546f58f](https://github.com/boundaryml/baml/commit/546f58f1bde022501e32e353ba432026bc4b7423)\ ) - Greg Hale\ * Enable ALPN feature in `reqwest` crate (#1318) - ([1ea1d8b](https://github.com/boundaryml/baml/commit/1ea1d8b37f20d0b1b63c14a24be10df1f00f1830)\ ) - Antonio Sarosi\ * Fix Vertex system prompt (#1319) - ([4b7db0f](https://github.com/boundaryml/baml/commit/4b7db0f2f4c7e829455f8f695be912db08a4cb74)\ ) - Antonio Sarosi\ * Add error boundary around posthog, add react-error-boundary dependency (#1327) - ([5c4acb4](https://github.com/boundaryml/baml/commit/5c4acb4e71d08386633c1c1a3149f6c779fd4aa2)\ ) - aaronvg\ * Make literals nullable in generated python (#1334) - ([68745d0](https://github.com/boundaryml/baml/commit/68745d0ae9ab4c3c59097e6930ae984fea9283ab)\ ) - Greg Hale\ * Fix type alias highlighting in promptfiddle (#1344) - ([81ab2ba](https://github.com/boundaryml/baml/commit/81ab2ba3dfe3679987572e4ce97170da0e06d767)\ ) - Antonio Sarosi\ * Fix field type parsing (#1349) - ([d08445f](https://github.com/boundaryml/baml/commit/d08445f6ffcafcdf0758cff398c14ffa4f14d311)\ ) - hellovai\ * Fix syntax highlighting for @@assert expressions with commas (#1357) - ([e5d595e](https://github.com/boundaryml/baml/commit/e5d595e311088574f4bbf94ddf95feb9abf727c9)\ ) - aaronvg\ \ [0.72.0](https://github.com/boundaryml/baml/compare/0.71.1..0.71.2)\ - 2025-01-07\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Update gemini 2 flash thinking model name check (#1283) - ([76ceeff](https://github.com/boundaryml/baml/commit/76ceeff0f780c0ddc9b6baaa2dc786e63c5c7377)\ ) - Gasser-Aly\ \ ### Features\ \ * get baml-fmt ready for beta (#1278) - ([abb0958](https://github.com/boundaryml/baml/commit/abb0958b8ee1c5d5000a3781677ee32da03daba4)\ ) - Samuel Lijin\ * provide saner semantics around aws\_session\_token (#1295) - ([98c6b99](https://github.com/boundaryml/baml/commit/98c6b999f5232c4bb6192183151ee52ce5416a0e)\ ) - Samuel Lijin\ * Include type aliases in Jinja (#1286) - ([207eab8](https://github.com/boundaryml/baml/commit/207eab8e2591577ecc863ff57c3572f268b41773)\ ) - Antonio Sarosi\ * Implement jump to definition for type aliases (#1287) - ([6cb5009](https://github.com/boundaryml/baml/commit/6cb50096e102f5c01f1371b616ca5bd2537610d9)\ ) - Antonio Sarosi\ * Improved ‘o1’ model detection in OpenAI client and updated documentation for error handling and client setup (#1290) - ([479d06e](https://github.com/boundaryml/baml/commit/479d06e4546538b3908422801b21a50f22a3fc3f)\ ) - hellovai\ * Add docs for recursive type aliases (#1294) - ([43a0007](https://github.com/boundaryml/baml/commit/43a0007876a04c3e71c808e377662a30a7c062b6)\ ) - Antonio Sarosi\ \ [0.71.1](https://github.com/boundaryml/baml/compare/0.71.0..0.71.1)\ - 2024-12-31\ ---------------------------------------------------------------------------------\ \ * Bump version to 0.71.1 - ([4ff76e8](https://github.com/boundaryml/baml/commit/4ff76e8bbd697bd48b0f9b08044b3f2d98df476c)\ ) - Aaron Villalpando\ \ [0.71.0](https://github.com/boundaryml/baml/compare/0.70.5..0.71.0)\ - 2024-12-31\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * fix concurrency docs (#1269)\ * issue with aws credentials not being passed in correctly (#1266) - ([7b79ac4](https://github.com/boundaryml/baml/commit/7b79ac4c28620ca09e72139ee8cd8fc0dc23cec1)\ ) - Chris Watts\ * Fix windows generation through vscode always outputting to the root workspace directory if the path was ../ (#1247) - ([cdc1838](https://github.com/boundaryml/baml/commit/cdc1838c114fd4d13e032da9cf7312aa55a8a889)\ ) - aaronvg\ * Fix VSCode link (#1264) - ([14342cd](https://github.com/boundaryml/baml/commit/14342cd2b9cdf53d9c2cbdc16a800fc88ff1cdf1)\ ) - Greg Hale\ * Special-case handling of Flash Thinking Mode for Gemini (#1276) - ([039b45a](https://github.com/boundaryml/baml/commit/039b45a965b56dd415f6ec104a8d44343d144e79)\ ) - Greg Hale\ * Fix typescript trace bugs (#1275) - ([e41b5aa](https://github.com/boundaryml/baml/commit/e41b5aa8a52fad9f9a5f833b2d1cecd2cc195868)\ ) - Edward Zhang\ * Add token counts to raw.**str**() (#1277) - ([b57bd30](https://github.com/boundaryml/baml/commit/b57bd30747dae563cf40b560cd5da3e50b783c5d)\ ) - aaronvg\ \ ### Features\ \ * **(serve)** Add graceful Ctrl+C handling with exit message (#1238) - ([83e68f2](https://github.com/boundaryml/baml/commit/83e68f2aadd6638e767eacfbb6087ef2483dd361)\ ) - revidious\ * implement format-on-save in vscode and baml-cli fmt (#1246) - ([66af7c5](https://github.com/boundaryml/baml/commit/66af7c57d22098b8d4c42f0d49ead84090b16407)\ ) - Samuel Lijin\ * allow optional lists and maps (#1251) - ([9170b89](https://github.com/boundaryml/baml/commit/9170b899b799302a4fc0781d99a493bf9fc13095)\ ) - revidious\ * Implement Type Aliases (#1163) - ([6310c41](https://github.com/boundaryml/baml/commit/6310c41e7fbe838026180071e881242d79789a2a)\ ) - Antonio Sarosi\ \ ### Miscellaneous Chores\ \ * add approval reqs to release workflows (#1243) - ([d3b9596](https://github.com/boundaryml/baml/commit/d3b959674957bfd07fd44817022c64e5b4d248c7)\ ) - Samuel Lijin\ * “Switching LLMs” Docs Fixes (#1244) - ([c62cef4](https://github.com/boundaryml/baml/commit/c62cef4949e1326c8da88dc46df762165c8f7b87)\ ) - Ethan\ * Add tests for azure and failure scenarios (#1250) - ([20ec134](https://github.com/boundaryml/baml/commit/20ec1345d3b8e26cddea9eccacc1420bdb3be804)\ ) - aaronvg\ * clarified readme (#1263) - ([8cac1ef](https://github.com/boundaryml/baml/commit/8cac1ef24e78b7f537b1aabf393d1b2a0e400ca2)\ ) - MoofSoup\ \ [0.70.5](https://github.com/boundaryml/baml/compare/0.70.1..0.70.5)\ - 2024-12-13\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Remove log statements (#1230) - ([4bcdd19](https://github.com/boundaryml/baml/commit/4bcdd198f219cd016ee64cc6444dd62e69f796fb)\ ) - hellovai\ * Fix playground proxy related issues (#1228, #1229, #1237) - ([7384ba8](https://github.com/boundaryml/baml/commit/7384ba8cb5d1f012c50ddfb2a44a142ec9654397)\ ) ([7bb6df4](https://github.com/boundaryml/baml/commit/7bb6df40fe37753b946ceeec6b30c4d9cdcc4ce7)\ ) ([16054f5](https://github.com/boundaryml/baml/commit/16054f5f858dcaf80f013d466ceb9354c6a160b7)\ ) - aaronvg\ \ ### DOCS\ \ * deno run instead of dpx (#1225) - ([7c64299](https://github.com/boundaryml/baml/commit/7c642992cd7d52b7e7cd718542dfa68c41b5aab3)\ ) - Jeffrey Konowitch\ * Fix broken links (#1235) - ([859c699](https://github.com/boundaryml/baml/commit/859c6998cef7950d52cc3287f51d74106a58d89d)\ ) - Samuel Lijin\ \ ### Features\ \ * Support parsing primitive values from single-key objects (#1224) - ([935a190](https://github.com/boundaryml/baml/commit/935a190556d12077f961ce083723e7c1f816f387)\ ) - revidious\ \ [0.70.1](https://github.com/boundaryml/baml/compare/0.70.0..0.70.1)\ - 2024-12-05\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Make baml\_py work with playwright/inspect (#1214) - ([6741999](https://github.com/boundaryml/baml/commit/674199992e21fb439a5c972c5868b6b3f106d267)\ ) - Samuel Lijin\ * Fix Python release pipeline (#1218) - ([bde634c](https://github.com/boundaryml/baml/commit/bde634cd6064784e77620f26f52202494fb659ec)\ ) - Samuel Lijin\ \ ### Documentation\ \ * Docs for LLM Clients paramaters updated (#1216) - ([6f99a28](https://github.com/boundaryml/baml/commit/6f99a28a918e557a75e2d763ac21ca587350adf4)\ ) - hellovai\ \ [0.70.0](https://github.com/boundaryml/baml/compare/0.69.0..0.70.0)\ - 2024-12-04\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Improvements for promptfiddle (#1201) - ([c6fb306](https://github.com/boundaryml/baml/commit/c6fb3067ce74f7864c8e071ed9ea3b3b1f69d00a)\ ) - aaronvg\ * Add vscode config to disable proxying (#1197) - ([c593284](https://github.com/boundaryml/baml/commit/c59328479a60847147d7141f0053fb208821d49a)\ ) - aaronvg\ * update lezer syntax for tests (#1199) - ([269ad9d](https://github.com/boundaryml/baml/commit/269ad9da5ca1dede5bf3d6a42f11f158cfe57dda)\ ) - aaronvg\ * Various playground fixes (#1202) - ([ce4f397](https://github.com/boundaryml/baml/commit/ce4f39737b88d2fcf27851ff8b230eda5a1e714b)\ ) - aaronvg\ \ ### Documentation\ \ * Add test-block constraints docs (#1198) - ([b566d4c](https://github.com/boundaryml/baml/commit/b566d4ceadab2bff0ae77765be63aadb4d3660d2)\ ) - Greg Hale\ \ ### Features\ \ * Fix azure client - ([9b57395](https://github.com/boundaryml/baml/commit/9b5739565b684c2179ac2ab24cabaa441a6269a7)\ ) - hellovai\ * Add new client paramters: allowed\_roles, default\_role, finish\_reason\_allow\_list, finish\_reason\_deny\_list (#1209) - ([9b57395](https://github.com/boundaryml/baml/commit/9b5739565b684c2179ac2ab24cabaa441a6269a7)\ ) - hellovai\ \ ### Miscellaneous Chores\ \ * cargo clippy (#1206) - ([c17e0da](https://github.com/boundaryml/baml/commit/c17e0da45db4188e0b0618d9e69f21220dc2fcff)\ ) - Antonio Sarosi\ * add colors to the CLI by default (#1208) - ([eba73c7](https://github.com/boundaryml/baml/commit/eba73c783c7f4e0013c0f128b0f2a7c20af330f0)\ ) - Samuel Lijin\ * simplify string formatting for readability (#1072) - ([3ebf08f](https://github.com/boundaryml/baml/commit/3ebf08fe54bcfcc384188296f32efa6a878416ec)\ ) - Hamir Mahal\ \ [0.69.0](https://github.com/boundaryml/baml/compare/0.68.0..0.69.0)\ - 2024-11-26\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ * Move documentation link higher in README.md for better visibility (#1190) - ([aaa1149](https://github.com/boundaryml/baml/commit/aaa1149acca0b4552b2d84aba6e6ee933a3a6d6b)\ ) - Dex\ * Update Vertex docs for different publishers (#1191) - ([66b2274](https://github.com/boundaryml/baml/commit/66b2274f895615f15b5a6edba51444b7d98dcaa5)\ ) - Antonio Sarosi\ * Update TypeScript installation docs to use `pnpm exec` instead of deprecated `pnpx` (#1144) - ([56194b8](https://github.com/boundaryml/baml/commit/56194b8084a08447dfb6ca5bf537289cd36022c4)\ ) - Manav Bokinala\ * Update LM Studio documentation (#1176) - ([7689ce7](https://github.com/boundaryml/baml/commit/7689ce7c3c42d49a020b81e0bdca16ef8e0209c7)\ ) - Jeff Winkler\ \ ### Features\ \ * Support enums & literals as map keys (#1178) - ([39e0271](https://github.com/boundaryml/baml/commit/39e0271f605234535cc53470a6aedff07aaa0c6c)\ ) - Antonio Sarosi\ * Parse triple backtick strings, discarding the info header (#1162) - ([353b21e](https://github.com/boundaryml/baml/commit/353b21e0ba3689420dfea6ff50a9454cf87fa199)\ ) - Samuel Lijin\ * Add ability to validate types for template strings (#1161) - ([a578cc2](https://github.com/boundaryml/baml/commit/a578cc287abbd9c23697adc4c83bcf0979916fcf)\ ) - hellovai\ * Support single line quoteless JSON parsing (#1170) - ([b1b9cab](https://github.com/boundaryml/baml/commit/b1b9cabcd51f87afef0ef54c7ecd0e2349d97f83)\ ) - hellovai\ * Generated code includes docstrings from BAML source docstrings (#1177) - ([170ece9](https://github.com/boundaryml/baml/commit/170ece9e8d72e235a7f5d628739899cd564ee995)\ ) - Greg Hale\ * Add ability to parse clients statically whenever possible (#1193) - ([03d9475](https://github.com/boundaryml/baml/commit/03d947581ceb56a3c3498f2746f697ce06a55077)\ ) - hellovai\ * Support setting all env vars for AWS-bedrock (#1179) - ([fcdbdfb](https://github.com/boundaryml/baml/commit/fcdbdfbb80e5e7d09411b0e55aa0039b0be998bc)\ ) - hellovai\ * Add constraints to test blocks (#1185) - ([cafd2ea](https://github.com/boundaryml/baml/commit/cafd2ea35ac0d3129ddddb7c4fc81561a7316657)\ ) - Greg Hale\ * Add sum jinja filter (#1174) - ([2353862](https://github.com/boundaryml/baml/commit/2353862730ed3be9b354a9f6a6c20c4c75a6058f)\ ) - Greg Hale\ * Add openrouter key (#1186) - ([28d58c0](https://github.com/boundaryml/baml/commit/28d58c060320154bddfef03bdd6de67d27e26c0f)\ ) - aaronvg\ \ ### Bug Fixes\ \ * Fix image path in README.md (#1190) - ([aaa1149](https://github.com/boundaryml/baml/commit/aaa1149acca0b4552b2d84aba6e6ee933a3a6d6b)\ ) - Dex\ * Fix template string highlights (#1182) - ([60c823a](https://github.com/boundaryml/baml/commit/60c823a000507e6667670f96f1607ba2ea160c57)\ ) - aaronvg\ * Fix nextjs and TS server hot-reload (#1183) - ([22e6bbb](https://github.com/boundaryml/baml/commit/22e6bbb7dbe125b40f72d37e6fb8a73e603aade8)\ ) - aaronvg\ * Fix lang name (#1188) - ([8c3d536](https://github.com/boundaryml/baml/commit/8c3d5363dd36c32a512430f970da8c76788335e3)\ ) - aaronvg\ * Make id optional as gemini doesn’t include it in openai generic (#1187) - ([97d1cd4](https://github.com/boundaryml/baml/commit/97d1cd48dc80bdfaeb08bf8a27b65c21a48145bd)\ ) - aaronvg\ * Correctly compute required\_env\_vars even for shorthand clients (#1164) - ([8b51b6e](https://github.com/boundaryml/baml/commit/8b51b6eb186b8c2853139e37e87a69a87e893059)\ ) - hellovai\ * Report wrong keyword errors in type defs (#1166) - ([3b1d152](https://github.com/boundaryml/baml/commit/3b1d15230c9ba6dae3cb8d9f0f7f7e9b75f8f00e)\ ) - Antonio Sarosi\ * Remove win32-arm64 support for now to fix yarn and deno builds (#1173) - ([c0234d7](https://github.com/boundaryml/baml/commit/c0234d730915506097ff17b54afd7316fdc850cd)\ ) - aaronvg\ * Validate fieldnames and types when using pydantic codegen (#1189) - ([93b393d](https://github.com/boundaryml/baml/commit/93b393ded048817fdb7ffef65cb698f9edb14764)\ ) - Greg Hale\ \ [0.68.0](https://github.com/boundaryml/baml/compare/0.67.0..0.68.0)\ - 2024-11-11\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ ### Features\ \ * Recursive types! (#1065) - ([8100df9](https://github.com/boundaryml/baml/commit/8100df999e67690458e8bc6adc50575e855bd242)\ ) - Antonio Sarosi\ * Support specifying “region” for aws-bedrock (#1150) - ([cbe3c92](https://github.com/boundaryml/baml/commit/cbe3c9261b3fa5cd026b9492a2858c1822e354df)\ ) - Samuel Lijin\ * Add `hoisted_class_prefix` option in docs (#1154) - ([cf2298e](https://github.com/boundaryml/baml/commit/cf2298ec53c74c317c495c7b84e1a56a97193b4f)\ ) - Antonio Sarosi\ * Make render messages dynamic and use `hoisted_class_prefix` instead of `"schema"` (#1155) - ([873751b](https://github.com/boundaryml/baml/commit/873751ba84f736dfbcbd9cbb0b6debfe7081cc1f)\ ) - Antonio Sarosi\ * Support o1 in playground (allow certain models to disable streaming) (#1157) - ([09c6549](https://github.com/boundaryml/baml/commit/09c65497c3218387756775827ba22bcad16f0362)\ ) - hellovai\ * Add basic grammar for `a` vs `an` articles in ctx.output\_format (#1158) - ([e084130](https://github.com/boundaryml/baml/commit/e0841307d4da809754d995a4524b39b87040f2d0)\ ) - Antonio Sarosi\ \ ### Bug Fixes\ \ * Improved syntax highlighting for template\_strings (#1151) - ([8c43e37](https://github.com/boundaryml/baml/commit/8c43e37fdaa05d9f3626fde7ad56614610727348)\ ) - Greg Hale\ * Improved error detection for client parsing (#1026) - ([c6b1167](https://github.com/boundaryml/baml/commit/c6b116744f55f831352209c04cd6bce7b028eda9)\ ) - hellovai\ * Fix BAML\_LOG\_JSON logs for py, ruby, and TS (#1153) - ([9e08642](https://github.com/boundaryml/baml/commit/9e08642470435fbefca20b163de010dd805560b8)\ ) - aaronvg\ \ [0.67.0](https://github.com/boundaryml/baml/compare/0.66.0..0.67.0)\ - 2024-11-05\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * URGENT: fix generated typescript code (#1147) - ([bd9da16](https://github.com/boundaryml/baml/commit/bd9da1683112d849595580866382cba2c6bed8be)\ ) - hellovai\ \ ### Features\ \ * Parser improvement: handle code within backticks (\`) (#1146) - ([3d8ef34](https://github.com/boundaryml/baml/commit/3d8ef34af15a7f2b957876ffa71314ce38da2a01)\ ) - hellovai\ \ [0.66.0](https://github.com/boundaryml/baml/compare/0.65.0..0.66.0)\ - 2024-11-04\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * BAML\_LOG supports JSON mode (#1137) - ([f140767](https://github.com/boundaryml/baml/commit/f1407674fc0d91c079fd93b655ff097a05475740)\ ) - aaronvg\ * Block-level constraints (#1124) - ([e931acb](https://github.com/boundaryml/baml/commit/e931acb7f765e86a70cb33cd86728aabe058024b)\ ) - Greg Hale\ * Parser improvement! Streaming arrays is much more stable and parsing file paths improved (#1134) - ([56570f0](https://github.com/boundaryml/baml/commit/56570f0fe6c4c09594eb757c8a78158cf0e73fcd)\ ) - hellovai\ \ ### Documentation\ \ * Improvements to Reference Documentation (#1125) - ([12c8fa7](https://github.com/boundaryml/baml/commit/12c8fa7ec5aea8571f27fb65b8f2a327a1a5e0ce)\ ) - hellovai\ * README.md: typo/readability fixes (#1092) - ([cb67e31](https://github.com/boundaryml/baml/commit/cb67e316dce2c4ee29b6fd625316f5df4409335f)\ ) - Prathamesh Pawar\ * README.md: Correct Promptfiddle link (#1108) - ([b296c4c](https://github.com/boundaryml/baml/commit/b296c4cf6104513e40ef89f17d534d6d8858f223)\ ) - Sagar Sharma\ * Fix broken links (#1133) - ([e0bfc94](https://github.com/boundaryml/baml/commit/e0bfc94f453f35971e871a4b121a1f35fa0b17cc)\ ) - aaronvg\ \ ### Bug-fix\ \ * Improve syntax highlighting for template strings (#1130) - ([54de4b6](https://github.com/boundaryml/baml/commit/54de4b6ed9144a68fe0a84d916679f9aec46fe28)\ ) - hellovai\ * Improved static analysis for literals in jinja (#1132) - ([b8a221f](https://github.com/boundaryml/baml/commit/b8a221ff44668e2b1d9fa75100c270ce5a227ed4)\ ) - Greg Hale\ * Adds missing imports to the sync\_client template (#1131) - ([823f74c](https://github.com/boundaryml/baml/commit/823f74c88df3cc7b9ebb4b19b74b5ee6edbafd9c)\ ) - Jesus Lizama\ * Add `Checked` in baml client typescript (#1135) - ([ad759cd](https://github.com/boundaryml/baml/commit/ad759cdb67cb0b6a6d2bd0d16575e3e1bc847a68)\ ) - Greg Hale\ * Produce syntax error when user misses return type on functions (#1129) - ([034d6eb](https://github.com/boundaryml/baml/commit/034d6ebda38aded1c6a93321d363575156b0ecc6)\ ) - hellovai\ \ [0.65.0](https://github.com/boundaryml/baml/compare/0.64.0..0.65.0)\ - 2024-10-31\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ * **New Documentation Structure**: Introduced version 3 of the documentation, enhancing clarity and organization. ([#1118](https://github.com/boundaryml/baml/commit/bab2767414172dd632437a57631c4cee04910518)\ )\ \ ### Bug Fixes\ \ * **Python Type Handling**: Moved Python Checked and Check types into `baml_client` for better type management. ([#1122](https://github.com/boundaryml/baml/commit/0ccf473fd821d25d431bbf4341c4e837967104bf)\ )\ * **Literal Input Type Checking**: Fixed an issue where literal inputs were not being type-checked correctly. ([#1121](https://github.com/boundaryml/baml/commit/aa5dc85026a175216b5caae6320d09a1fcd35752)\ )\ \ [0.64.0](https://github.com/boundaryml/baml/compare/0.63.0..0.64.0)\ - 2024-10-29\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * **Playground Stability:** Prevented crashes in the playground due to malformed vertex credentials ([#1107](https://github.com/boundaryml/baml/commit/e665346fbc84a9b969a979cfdf1c70d530201e93)\ ) - _Samuel Lijin_\ * **Union Handling:** Addressed an issue with union types in the schema ([#1096](https://github.com/boundaryml/baml/commit/cb5ce7623d3e95464fb5e5152c4d2339458caa26)\ ) - _Greg Hale_\ * **WASM Function Signatures:** Resolved stack overflow when computing WASM function signatures ([#1100](https://github.com/boundaryml/baml/commit/aa736ed2d7386cae78421c22d5669c73d8921085)\ ) - _aaronvg_\ * **VSCode Extension:** Fixed crashes in the VSCode extension that caused the output panel to open unexpectedly ([#1103](https://github.com/boundaryml/baml/commit/cb5a266bc68f15483f3ec3fa0f4edbc8d176287a)\ ) - _hellovai_\ * **Static Analysis Improvements:** Enhanced static analysis on Jinja expressions and `regex_match` functions ([#1102](https://github.com/boundaryml/baml/commit/7ca8136ffbc690877091627415941674f6f14b2f)\ , [#1104](https://github.com/boundaryml/baml/commit/83ddb1cfe81c9b5f6ae620c331c4eefe512c78bd)\ ) - _hellovai_\ * **Codegen Enhancements:** Fixed code generation for Python boolean literals and updated integration tests ([#1099](https://github.com/boundaryml/baml/commit/635976238fd9246bfb8764875358a36b4ec6a7f5)\ ) - _Antonio Sarosi_\ * **Enum Handling:** Improved substring alias handling for enums ([#1098](https://github.com/boundaryml/baml/commit/0c5cbd4ae03d2bc836ee4b61a7df638855bb72ca)\ ) - _Miguel Cárdenas_\ * **Syntax Highlighting:** Refined span calculations for Jinja expressions and improved VSCode syntax highlighting with Lezer ([#1110](https://github.com/boundaryml/baml/commit/a53072f5fe9fe83a0accb36e43a06550602a3c65)\ ) - _hellovai_\ * **Ruby Support:** Fixed literal boolean tests for Ruby ([#1109](https://github.com/boundaryml/baml/commit/23e590b0b2fdb51f80e7eced769baabd12b3be22)\ ) - _Antonio Sarosi_\ \ ### Features\ \ * **Constraint Support:** Added the ability to define constraints using Jinja expressions ([#1006](https://github.com/boundaryml/baml/commit/d794f28b4f8830b1a40cd08043ecdc562938d36e)\ ) - _Greg Hale_\ * **VSCode & Fiddle UI:** Introduced a new “Intro to Checks” UI for easier onboarding ([#1106](https://github.com/boundaryml/baml/commit/11efa5e97f8e9b8f385b7fb0e823f5ff2bc4c314)\ ) - _Samuel Lijin_\ * **Dev Container Configurations:** Added Dev Container configurations for streamlined development environments ([#1112](https://github.com/boundaryml/baml/commit/5790393d7ad320e9e257c09e461c9bc39310a834)\ ) - _Antonio Sarosi_\ \ ### Documentation\ \ * **Constraints Documentation:** Published new documentation for defining constraints in BAML ([#1113](https://github.com/boundaryml/baml/commit/6332021a59661d3931934adc2afbf4f99f6f4bee)\ ) - _Greg Hale_\ * **Dynamic Types Linking:** Added cross-links to dynamic types documentation for easier navigation ([#1116](https://github.com/boundaryml/baml/commit/8ce0a539d74d05438e8047e4e02022ddd7121e21)\ ) - _Greg Hale_\ \ ### Miscellaneous\ \ * **Code Quality:** Improved style and fixed typos in the codebase ([#1115](https://github.com/boundaryml/baml/commit/4c3970a6e6ce998a784e682f4c218ba2a69cf86a)\ ) - _Greg Hale_\ * **Parsing Stability:** Added logic to prevent assertions from parsing errors and ensured checks no longer affect parsing ([#1101](https://github.com/boundaryml/baml/commit/5ec89c92ab14622afddc3ce348c5b981b4840492)\ ) - _hellovai_\ * **Version Bump:** Bumped version to 0.64.0 ([#1114](https://github.com/boundaryml/baml/commit/90d3c17ba67bc1467ee5973ff6cf257069e265b9)\ , [#ff7e152](https://github.com/boundaryml/baml/commit/ff7e152510395bab1d38afa60211226070d12cc2)\ ) - _Vaibhav Gupta_\ \ [0.63.0](https://github.com/boundaryml/baml/compare/0.62.0..0.63.0)\ - 2024-10-23\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Fix dynamic enums which already are defined in BAML (#1080) - ([22d0f1c](https://github.com/boundaryml/baml/commit/22d0f1cff3428c2cd58ea78c50c4fc7ea39c8d0c)\ ) - hellovai\ \ ### Features\ \ * Updated clients.baml to use the latest sonnet model (#1081) - ([71df0b7](https://github.com/boundaryml/baml/commit/71df0b7b627ba218d581d2c21be01fea4e4993c1)\ ) - aaronvg\ * Improved clients.baml generated via baml init (#1089) - ([682dd66](https://github.com/boundaryml/baml/commit/682dd66f4adab8c4fad13bfe32a3fc0268d8b511)\ ) - hellovai\ \ [0.62.0](https://github.com/boundaryml/baml/compare/0.61.1..0.62.0)\ - 2024-10-21\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Support serializing/deserializing `baml_py.Image`, `baml_py.Audio` for pydantic (#1062) - ([11cb699](https://github.com/boundaryml/baml/commit/11cb69903dce1ae348c68f88a82b4731da3977a7)\ ) - Samuel Lijin\ * Support rendering input classes with aliases (#1045) - ([3824cda](https://github.com/boundaryml/baml/commit/3824cda75524105f3401e5c7e4c21e604d639f76)\ ) - aaronvg\ * Add unstable\_internal\_repr on FunctionResult in python (#1068) - ([00082e8](https://github.com/boundaryml/baml/commit/00082e8b941d3648ec499215d2c38091f36db944)\ ) - hellovai\ * Add literal support for type\_builder (#1069) - ([c0085d9](https://github.com/boundaryml/baml/commit/c0085d908cbf8696623fd70f49de5ca8325de06c)\ ) - hellovai\ \ ### Bug Fixes\ \ * Surface errors in fallbacks containing only erroneous clients (#1061) - ([b69ef79](https://github.com/boundaryml/baml/commit/b69ef79542ec818b8779f9710dad65d33166c862)\ ) - Greg Hale\ * Fix parser so that we are able to correctly detect sequences of empty strings. (#1048) - ([977e277](https://github.com/boundaryml/baml/commit/977e2776119a6f1e79f29cbe596b1c31697becb5)\ ) - hellovai\ * Make substring match algorithm case insensitive (#1056) - ([fa2c477](https://github.com/boundaryml/baml/commit/fa2c4770791297a7a37a3f0c837ede4bb709f0ef)\ ) - Antonio Sarosi\ * Fix vertex-ai citation data being optional (#1058) - ([5eae0a7](https://github.com/boundaryml/baml/commit/5eae0a73be6cc8286ce045185537aeed0b9feb7d)\ ) - aaronvg\ * Fix bug to correctly cast to pydantic types in ambiguous scenarios where BAML knows better (#1059) - ([830b0cb](https://github.com/boundaryml/baml/commit/830b0cb194b99fa6f019928e7466dcf3e3992596)\ ) - hellovai\ * Parser: Prefer case sensitive match over case insensitive (#1063) - ([cd6b141](https://github.com/boundaryml/baml/commit/cd6b141020ec8dfd2514c82ffffaebc5678a025b)\ ) - Antonio Sarosi\ * Only popup the vscode env var dialog once (#1066) - ([1951474](https://github.com/boundaryml/baml/commit/19514745cfc8efeb8bda0be655e0fa2f216e4b29)\ ) - aaronvg\ \ ### Documentation\ \ * Docs for literal types (#1030) - ([55e5964](https://github.com/boundaryml/baml/commit/55e596419055c8da52b841b9ecbf16e328bc1033)\ ) - Antonio Sarosi\ * Contribution guide (#1055) - ([f09d943](https://github.com/boundaryml/baml/commit/f09d9432d95c876f5e63f3abdb47a40417c5c45a)\ ) - aaronvg\ \ ### Misc\ \ * Fix VSCode metrics (#1044) - ([a131336](https://github.com/boundaryml/baml/commit/a13133656e1610cac9a92aa4b4459c78340c7304)\ ) - hellovai\ * Add more test cases for unquoted strings in objects (#1054) - ([2d1b700](https://github.com/boundaryml/baml/commit/2d1b700e82604e444d904cfeb67f46ced97153a5)\ ) - hellovai\ \ [0.61.1](https://github.com/boundaryml/baml/compare/0.61.0..0.61.1)\ - 2024-10-15\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * add musl to the ts release artifacts (#1042) - ([e74f3e9](https://github.com/boundaryml/baml/commit/e74f3e90489a403e38b39cc694d30d038ad38b8d)\ ) - Samuel Lijin\ \ [0.61.0](https://github.com/boundaryml/baml/compare/0.60.0..0.61.0)\ - 2024-10-14\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Implement literal types (#978) - ([9e7431f](https://github.com/boundaryml/baml/commit/9e7431f43b74d4428e6a20b9aa3a1e93768ff905)\ ) - Antonio Sarosi\ * allow installing the TS library on node-alpine (#1029) - ([1c37a0d](https://github.com/boundaryml/baml/commit/1c37a0d71d921d13f05340ff6727255ba6074152)\ ) - Samuel Lijin\ * Add WYSIWYG UI (Swagger UI) to baml-cli dev (#1019) - ([0c73cab](https://github.com/boundaryml/baml/commit/0c73cab3d6ac3bbb04cc898ac102900ca9b17f86)\ ) - Greg Hale\ * Suppress streaming for Numbers (#1032) - ([3f4621b](https://github.com/boundaryml/baml/commit/3f4621b36555062312aabd9ba8435b965ba8fd92)\ ) - Greg Hale\ \ ### Bug Fixes\ \ * Add limit on connection pool to prevent stalling issues in pyo3 and other ffi boundaries (#1027) - ([eb90e62](https://github.com/boundaryml/baml/commit/eb90e62ffe21109e0da1bd74439d36bb37246ec3)\ ) - hellovai\ * Update docs (#1025) - ([2dd1bb6](https://github.com/boundaryml/baml/commit/2dd1bb6cf743c20af53d7147db8a4573de9cdbe0)\ ) - Farookh Zaheer Siddiqui\ * Fix parsing for streaming of objects more stable (#1031) - ([8aa9c00](https://github.com/boundaryml/baml/commit/8aa9c00b8f26a8c30178ff25aecc1c3b47b6696e)\ ) - hellovai\ * Fix python BamlValidationError type (#1036) - ([59a9510](https://github.com/boundaryml/baml/commit/59a9510c9d2c1216df01b0701cc23afb02e3f700)\ ) - aaronvg\ \ ### Miscellaneous\ \ * Popup settings dialog when no env vars set (#1033) - ([b9fa52a](https://github.com/boundaryml/baml/commit/b9fa52aea8686f8095878e7f210c2d937b533c63)\ ) - aaronvg\ * Bump version to 0.61.0 - ([ca2242b](https://github.com/boundaryml/baml/commit/ca2242b26214699268fda9e9ac07338c6491026d)\ ) - Aaron Villalpando\ \ [0.60.0](https://github.com/boundaryml/baml/compare/0.59.0..0.60.0)\ - 2024-10-09\ ---------------------------------------------------------------------------------\ \ ### Miscellaneous Chores\ \ * update Dockerfile (#1017) - ([51539b7](https://github.com/boundaryml/baml/commit/51539b7b5778d6a3e6619698d2033d4f66f15d27)\ ) - Ikko Eltociear Ashimine\ * Revert “feat: add a WYSIWYG UI (Swagger UI) to `baml-cli dev` (#1011)” (#1018) - ([f235050](https://github.com/boundaryml/baml/commit/f235050a57916116aff8359236b819ac69011a21)\ ) - Greg Hale\ \ ### Bug fixes\ \ * Fix python types for BamlValidationError (#1020) - ([520a09c](https://github.com/boundaryml/baml/commit/520a09c478ea8c5eb811447ce9b36689692aa01d)\ ) - aaronvg\ * coerce floats and ints with commas and other special cases (#1023) - ([904492e](https://github.com/boundaryml/baml/commit/904492ee298727085e00a391beb628c8d999083e)\ ) - aaronvg\ \ ### Docs\ \ * Add Docs for Jupyter notebook usage (#1008) - ([c51d918](https://github.com/boundaryml/baml/commit/c51d918f76f63ce55b353661459ba3b27b9a0ea7)\ ) - aaronvg\ \ [0.59.0](https://github.com/boundaryml/baml/compare/0.58.0..0.59.0)\ - 2024-10-04\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * **(vertex)** allow specifying creds as JSON object (#1009) - ([98868da](https://github.com/boundaryml/baml/commit/98868da4e75dde3a00178cbf60afebc501d37b0c)\ ) - Samuel Lijin\ * Add prompt, raw\_output and error message to BamlValidationError in TS and Python (#1005) - ([447dbf4](https://github.com/boundaryml/baml/commit/447dbf4e0d0cf0744307ef50f89050752334d982)\ ) - aaronvg\ * Add BamlValidationError to `baml-cli serve` (#1007) - ([3b8cf16](https://github.com/boundaryml/baml/commit/3b8cf1636594c1a7245a733556efa690da40e139)\ ) - aaronvg\ * Include a WYSIWYG UI (Swagger UI) to `baml-cli dev` (#1011) - ([fe9dde4](https://github.com/BoundaryML/baml/commit/fe9dde4f3a7ff0503fd13087da50e4da9d97c3a0)\ ) - imalsogreg\ \ [0.58.0](https://github.com/boundaryml/baml/compare/0.57.1..0.58.0)\ - 2024-10-02\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Add client registry support for BAML over Rest (OpenAPI) (#1000) - ([abe70bf](https://github.com/boundaryml/baml/commit/abe70bf368c9361a3ab32643735f68e0fafd8425)\ ) - Lorenz Ohly\ \ ### Bug Fixes\ \ * Improve performance of parsing escaped characters in strings during streaming. (#1002) - ([b35ae2c](https://github.com/boundaryml/baml/commit/b35ae2c4777572206a79af5c2943f5bdd6ada081)\ ) - hellovai\ \ ### Documentation\ \ * Add Docs for Document Extraction API (#996) - ([da1a5e8](https://github.com/boundaryml/baml/commit/da1a5e876368074235f4474673a1ebfe632e11ed)\ ) - aaronvg\ \ [0.57.1](https://github.com/boundaryml/baml/compare/0.57.0..0.57.1)\ - 2024-09-29\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * \[BUGFIX\] Parser should require a space between class keyword and class name (#990) - ([7528247](https://github.com/boundaryml/baml/commit/752824723404a4ed4c4b1e31c43d140e9346dca2)\ ) - Greg Hale\ * Remove dynamic string attributes (#991) - ([0960ab2](https://github.com/boundaryml/baml/commit/0960ab2e0d16c50fef58772336b91297ddac6919)\ ) - Greg Hale\ * ts fixes (#992) - ([36af43f](https://github.com/boundaryml/baml/commit/36af43f4f773e1565527916eff7d7837d9f8a983)\ ) - aaronvg\ * Bump version to 0.57.1 - ([0aa71dd](https://github.com/boundaryml/baml/commit/0aa71dd4d3aa7082db6a19f0a3a976ff55789d83)\ ) - Aaron Villalpando\ \ [0.57.0](https://github.com/boundaryml/baml/compare/0.56.1..0.57.0)\ - 2024-09-27\ ---------------------------------------------------------------------------------\ \ ### Documentation\ \ * Fix Python dynamic types example (#979) - ([eade116](https://github.com/boundaryml/baml/commit/eade116de14bcc15d738fec911d8653685c13706)\ ) - lorenzoh\ \ ### Features\ \ * teach vscode/fiddle to explain when we drop information (#897) - ([93e2b9b](https://github.com/boundaryml/baml/commit/93e2b9b8d54a4ced0853ce72596d0b0a9896a0da)\ ) - Samuel Lijin\ * Add ability for users to reset env vars to their desire. (#984) - ([69e6c29](https://github.com/boundaryml/baml/commit/69e6c29c82ccc06f8939b9ece75dd7797c8f6b98)\ ) - hellovai\ \ ### Bug Fixes\ \ * Fixed panic during logging for splitting on UTF-8 strings. (#987) - ([c27a64f](https://github.com/boundaryml/baml/commit/c27a64f6320515cd5ab6385ab93013d3d7ba88b8)\ ) - hellovai\ * Improve SAP for triple quoted strings along with unions (#977) - ([44202ab](https://github.com/boundaryml/baml/commit/44202ab63aa3d2881485b9b32fa744797c908e33)\ ) - hellovai\ * Add more unit tests for parsing logic inspired by user (#980) - ([48dd09f](https://github.com/boundaryml/baml/commit/48dd09f89b6447cbc1a539ecade66ab4da87b8dc)\ ) - hellovai\ * Improve syntax errors e.g. class / enum parsing and also update pestmodel to handle traling comments (#981) - ([adbb6ae](https://github.com/boundaryml/baml/commit/adbb6ae38833d700bfe0123ac712cd90d7e4d970)\ ) - hellovai\ * Updating docs for env vars (#985) - ([305d6b3](https://github.com/boundaryml/baml/commit/305d6b3e5a57513adc43c8ab9068c523dfc2e69c)\ ) - hellovai\ * When using openai-generic, use a string as the content type in the api request if theres no media (#988) - ([e8fa739](https://github.com/boundaryml/baml/commit/e8fa739838cc124a8eed49103871b1b971063821)\ ) - aaronvg\ \ [0.56.1](https://github.com/boundaryml/baml/compare/0.56.0..0.56.1)\ - 2024-09-21\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * Improved parser for unions (#975) - ([b390521](https://github.com/boundaryml/baml/commit/b39052111529f217762b3271846006bec4a604de)\ ) - hellovai\ * \[syntax\] Allow lists to contain trailing comma (#974) - ([9e3dc6c](https://github.com/boundaryml/baml/commit/9e3dc6c90954905a96b599ef28c40094fe48a43e)\ ) - Greg Hale\ \ [0.56.0](https://github.com/boundaryml/baml/compare/0.55.3..0.56.0)\ - 2024-09-20\ ---------------------------------------------------------------------------------\ \ Shout outs to Nico for fixing some internal Rust dependencies, and to Lorenz for correcting our documentation! We really appreciate it :)\ \ ### Features\ \ * use better default for openapi/rust client (#958) - ([b74ef15](https://github.com/boundaryml/baml/commit/b74ef15fd4dc09ecc7d1ac8284e7f22cd6d5864c)\ ) - Samuel Lijin\ \ ### Bug Fixes\ \ * push optional-list and optional-map validation to post-parse (#959) - ([c0480d5](https://github.com/boundaryml/baml/commit/c0480d5cfd46ce979e957223dc7b5fa744778552)\ ) - Samuel Lijin\ * improve OpenAPI instructions for windows/java (#962) - ([6010efb](https://github.com/boundaryml/baml/commit/6010efbb7990fda966640c3af267de41362d3fa4)\ ) - Samuel Lijin\ * assorted fixes: unquoted strings, openai-generic add api\_key for bearer auth, support escape characters in quoted strings (#965) - ([847f3a9](https://github.com/boundaryml/baml/commit/847f3a9bb0f00303eae7e410663efc63e54c38b6)\ ) - hellovai\ * serde-serialize can cause a package dependency cycle (#967) - ([109ae09](https://github.com/boundaryml/baml/commit/109ae0914852f2ee4a771d27103e4e46ad672647)\ ) - Nico\ * make anthropic work in fiddle/vscode (#970) - ([32eccae](https://github.com/boundaryml/baml/commit/32eccae44b27c3fec5fbc3270b6657819d75a426)\ ) - Samuel Lijin\ * make dynamic enums work as outputs in Ruby (#972) - ([7530402](https://github.com/boundaryml/baml/commit/7530402f0dc063f10f57cf7aa7f06790574de705)\ ) - Samuel Lijin\ \ ### Documentation\ \ * suggest correct python init command in vscode readme (#954) - ([e99c5dd](https://github.com/boundaryml/baml/commit/e99c5dd1903078d08aef451e4addc6110d7ca279)\ ) - Samuel Lijin\ * add more vscode debugging instructions (#955) - ([342b657](https://github.com/boundaryml/baml/commit/342b657da69441306fa7711d7d14893cf8036f84)\ ) - Samuel Lijin\ * NextJS hook needs to be bound to the correct context (#957) - ([ee80451](https://github.com/boundaryml/baml/commit/ee80451de85063b37e658ba58571c791e8514273)\ ) - aaronvg\ * update nextjs hooks and docs (#952) - ([01cf855](https://github.com/boundaryml/baml/commit/01cf855500159066fdcd162dc2e2087768d5ba28)\ ) - aaronvg\ * Fix some documentation typos (#966) - ([5193cd7](https://github.com/boundaryml/baml/commit/5193cd70686173c863af5ce40fd6bb3792406951)\ ) - Greg Hale\ * Keywords AI router (#953) - ([1c6f975](https://github.com/boundaryml/baml/commit/1c6f975d8cc793841745da0db82ee1e2f1908e56)\ ) - aaronvg\ * Fix `post_generate` comment (#968) - ([919c79f](https://github.com/boundaryml/baml/commit/919c79fa8cd85a96e6559055b2bb436d925dcb2a)\ ) - lorenzoh\ \ ### Bug Fixes\ \ * show actionable errors for string\[\]? and map>…>? type validation (#946) - ([48879c0](https://github.com/boundaryml/baml/commit/48879c0744f79b482ef0d2b0624464053558ada4)\ ) - Samuel Lijin\ \ ### Documentation\ \ * add reference docs about env vars (#945) - ([dd43bc5](https://github.com/boundaryml/baml/commit/dd43bc59087e809e09ca7d3caf628e179a28fc3e)\ ) - Samuel Lijin\ \ [0.55.2](https://github.com/boundaryml/baml/compare/0.55.1..0.55.2)\ - 2024-09-11\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * use correct locking strategy inside baml-cli serve (#943) - ([fcb694d](https://github.com/boundaryml/baml/commit/fcb694d033317d8538cc7b2c61aaa94f772778db)\ ) - Samuel Lijin\ \ ### Features\ \ * allow using DANGER\_ACCEPT\_INVALID\_CERTS to disable https verification (#901) - ([8873fe7](https://github.com/boundaryml/baml/commit/8873fe7577bc879cf0d550063252c4532dcdfced)\ ) - Samuel Lijin\ \ [0.55.1](https://github.com/boundaryml/baml/compare/0.55.0..0.55.1)\ - 2024-09-10\ ---------------------------------------------------------------------------------\ \ ### Bug Fixes\ \ * in generated TS code, put eslint-disable before ts-nocheck - ([16d04c6](https://github.com/BoundaryML/baml/commit/16d04c6e360eefca10b4e0d008b03c34de279491)\ ) - Sam Lijin\ * baml-cli in python works again - ([b57ca0f](https://github.com/boundaryml/baml/commit/b57ca0f529c80f59b79b19132a8f1339a6b7bfe2)\ ) - Sam Lijin\ \ ### Documentation\ \ * update java install instructions (#933) - ([b497003](https://github.com/boundaryml/baml/commit/b49700356f2f69c4acbdc953a66a95224656ffaf)\ ) - Samuel Lijin\ \ ### Miscellaneous Chores\ \ * add version headers to the openapi docs (#931) - ([21545f2](https://github.com/boundaryml/baml/commit/21545f2a4d9b3987134d98ac720705dde2045290)\ ) - Samuel Lijin\ \ [0.55.0](https://github.com/boundaryml/baml/compare/0.54.2..0.55.0)\ - 2024-09-09\ ---------------------------------------------------------------------------------\ \ With this release, we’re announcing support for BAML in all languages: we now allow you to call your functions over an HTTP interface, and will generate an OpenAPI specification for your BAML functions, so you can now generate a client in any language of your choice, be it Golang, Java, PHP, Ruby, Rust, or any of the other languages which OpenAPI supports.\ \ Start here to learn more: [https://docs.boundaryml.com/docs/get-started/quickstart/openapi](https://docs.boundaryml.com/docs/get-started/quickstart/openapi)\ \ ### Features\ \ * implement BAML-over-HTTP (#908) - ([484fa93](https://github.com/boundaryml/baml/commit/484fa93a5a4b4677f531e6ef03bb88d144925c12)\ ) - Samuel Lijin\ * Add anonymous telemetry about playground actions (#925) - ([6f58c9e](https://github.com/boundaryml/baml/commit/6f58c9e3e464a8e774771706c2b0d76adb9e6cda)\ ) - hellovai\ \ [0.54.2](https://github.com/boundaryml/baml/compare/0.54.1..0.54.2)\ - 2024-09-05\ ---------------------------------------------------------------------------------\ \ ### Features\ \ * Add a setting to disable restarting TS server in VSCode (#920) - ([628f236](https://github.com/boundaryml/baml/commit/628f2360c415fa8a7b0cd90d7249733ff06acaa9)\ ) - aaronvg\ * Add prompt prefix for map types in ctx.output\_format and add more type validation for map params (#919) - ([4d304c5](https://github.com/boundaryml/baml/commit/4d304c583b9188c1963a34e2a153baaf003e36ac)\ ) - hellovai\ \ ### Bug fixes\ \ * Fix glibC issues for python linux-x86\_64 (#922) - ([9161bec](https://github.com/boundaryml/baml/commit/9161becccf626f8d13a15626481720f29e0f992c)\ ) - Samuel Lijin\ \ ### Documentation\ \ * Add nextjs hooks (#921) - ([fe14f5a](https://github.com/boundaryml/baml/commit/fe14f5a4ef95c9ccda916ff80ce852d3855554a3)\ ) - aaronvg\ \ [0.54.1](https://github.com/boundaryml/baml/compare/0.54.0..0.54.1)\ - 2024-09-03\ ---------------------------------------------------------------------------------\ \ ### BREAKING CHANGE\ \ * Fix escape characters in quoted strings (#905) - ([9ba6eb8](https://github.com/boundaryml/baml/commit/9ba6eb834e0145f4c57e582b63730d3d0ac9b2e9)\ ) - hellovai\ \ Prior `"\n"` was interpreted as `"\\n"` in quoted strings. This has been fixed to interpret `"\n"` as newline characters and true for other escape characters.\ \ ### Documentation\ \ * updated dead vs-code-extension link (#914) - ([b12f164](https://github.com/boundaryml/baml/commit/b12f1649cf5bfd0d457c5d6d117fd3a21ba5dc6b)\ ) - Christian Warmuth\ * Update docs for setting env vars (#904) - ([ec1ca94](https://github.com/boundaryml/baml/commit/ec1ca94c91af2a51b4190a0bad0e0bc1c052f2a3)\ ) - hellovai\ * Add docs for LMStudio (#906) - ([ea4c187](https://github.com/boundaryml/baml/commit/ea4c18782de1f713e8d69d473f9e1818c97024c6)\ ) - hellovai\ * Fix docs for anthropic (#910) - ([aba2764](https://github.com/boundaryml/baml/commit/aba2764e5b04820d00b08bf52bda603ee27631f1)\ ) - hellovai\ * Update discord links on docs (#911) - ([927357d](https://github.com/boundaryml/baml/commit/927357dd64b36c25513352ed4968ebc62dad6132)\ ) - hellovai\ \ ### Features\ \ * BAML\_LOG will truncate messages to 1000 characters (modify using env var BOUNDARY\_MAX\_LOG\_CHUNK\_SIZE) (#907) - ([d266e5c](https://github.com/boundaryml/baml/commit/d266e5c4157f3b28d2f6454a7ea265dda7296bb2)\ ) - hellovai\ \ ### Bug Fixes\ \ * Improve parsing parsing when there are initial closing `]` or `}` (#903) - ([46b0cde](https://github.com/boundaryml/baml/commit/46b0cdeffb15bbab20a43728f52ad2a05623e6f7) ) - hellovai * Update build script for ruby to build all platforms (#915) - ([df2f51e](https://github.com/boundaryml/baml/commit/df2f51e52615451b3643cc124e7262f11965f3ef) ) - hellovai * Add unit-test for openai-generic provider and ensure it compiles (#916) - ([fde7c50](https://github.com/boundaryml/baml/commit/fde7c50c939c505906417596d16c7c4607173339) ) - hellovai [0.54.0](https://github.com/boundaryml/baml/compare/0.53.1..0.54.0) - 2024-08-27 --------------------------------------------------------------------------------- ### BREAKING CHANGE * Update Default Gemini Base URL to v1beta (#891) - ([a5d8c58](https://github.com/boundaryml/baml/commit/a5d8c588e0fd0b7e186d7c71f1f6171334250629) ) - gleed The default base URL for the Gemini provider has been updated to v1beta. This change is should have no impact on existing users as v1beta is the default version for the Gemini python library, we are mirroring this change in BAML. ### Bug Fixes * Allow promptfiddle to talk to localhost ollama (#886) - ([5f02b2a](https://github.com/boundaryml/baml/commit/5f02b2ac688ceeb5a34e848a8ff87fd43a6b093a) ) - Samuel Lijin * Update Parser for unions so they handle nested objects better (#900) - ([c5b9a75](https://github.com/boundaryml/baml/commit/c5b9a75ea6da7c45da1999032e2b256bec97d922) ) - hellovai ### Documentation * Add ollama to default prompt fiddle example (#888) - ([49146c0](https://github.com/boundaryml/baml/commit/49146c0e50c88615e4cc97adb595849c23bad8ae) ) - Samuel Lijin * Adding improved docs + unit tests for caching (#895) - ([ff7be44](https://github.com/boundaryml/baml/commit/ff7be4478b706da049085d432b2ec98627b5da1f) ) - hellovai ### Features * Allow local filepaths to be used in tests in BAML files (image and audio) (#871) - ([fa6dc03](https://github.com/boundaryml/baml/commit/fa6dc03fcdd3255dd83e25d0bfb3b0e740991408) ) - Samuel Lijin * Add support for absolute file paths in the file specifier (#881) - ([fcd189e](https://github.com/boundaryml/baml/commit/fcd189ed7eb81712bf3b641eb3dde158fc6a62af) ) - hellovai * Implement shorthand clients (You can now use “openai/gpt-4o” as short for creating a complete client.) (#879) - ([ddd15c9](https://github.com/boundaryml/baml/commit/ddd15c92c3e8d81c24cb7305c9fcbb36b819900f) ) - Samuel Lijin * Add support for arbritrary metadata (e.g. cache\_policy for anthropic) (#893) - ([0d63a70](https://github.com/boundaryml/baml/commit/0d63a70332477761a97783e203c98fd0bf67f151) ) - hellovai * Expose Exceptions to user code: BamlError, BamlInvalidArgumentError, BamlClientError, BamlClientHttpError, BamlValidationError (#770) - ([7da14c4](https://github.com/boundaryml/baml/commit/7da14c480506e9791b3f4ce52ac73836a042d38a) ) - hellovai ### Internal * AST Restructuring (#857) - ([75b51cb](https://github.com/boundaryml/baml/commit/75b51cbf80a0c8ba19ae05b021ef3c94dacb4e30) ) - Anish Palakurthi [0.53.1](https://github.com/boundaryml/baml/compare/0.53.0..0.53.1) - 2024-08-11 --------------------------------------------------------------------------------- ### Bug Fixes * fix github release not passing params to napi script causing issues in x86\_64 (#872) * ([06b962b](https://github.com/boundaryml/baml/commit/06b962b945f958bf0637d13fec22bd2d59c64c5f) ) - aaronvg ### Features * Add Client orchestration graph in playground (#801) - ([24b5895](https://github.com/boundaryml/baml/commit/24b5895a1f45ac04cba0f19e6da727b5ee766186) ) - Anish Palakurthi * increase range of python FFI support (#870) - ([ec9b66c](https://github.com/boundaryml/baml/commit/ec9b66c31faf97a58c81c264c7fa1b32e0e9f0ae) ) - Samuel Lijin ### Misc * Bump version to 0.53.1 - ([e4301e3](https://github.com/boundaryml/baml/commit/e4301e37835483f51edf1cad6478e46ff67508fc) ) - Aaron Villalpando [0.53.0](https://github.com/boundaryml/baml/compare/0.52.1..0.53.0) - 2024-08-05 --------------------------------------------------------------------------------- ### Bug Fixes * make image\[\] render correctly in prompts (#855) - ([4a17dce](https://github.com/boundaryml/baml/commit/4a17dce43c05efd5f4ea304f2609fe140de1dd8c) ) - Samuel Lijin ### Features * **(ruby)** implement dynamic types, dynamic clients, images, and audio (#842) - ([4a21eed](https://github.com/boundaryml/baml/commit/4a21eed668f32b042fba61f24c9efb8b3794a420) ) - Samuel Lijin * Codelenses for test cases (#812) - ([7cd8794](https://github.com/boundaryml/baml/commit/7cd87942bf50a72de0ad46154f164fb2c174f25b) ) - Anish Palakurthi ### Issue * removed vertex auth token printing (#846) - ([b839316](https://github.com/boundaryml/baml/commit/b83931665a2c3b840eb6c6d31cf3d01c7926e52e) ) - Anish Palakurthi * Fix google type deserialization issue - ([a55b9a1](https://github.com/boundaryml/baml/commit/a55b9a106176ed1ce34bb63397610c2640b37f16) ) - Aaron Villalpando ### Miscellaneous Chores * clean up release stuff (#836) - ([eed41b7](https://github.com/boundaryml/baml/commit/eed41b7474417d2e65b2c5d742234cc20fc5644e) ) - Samuel Lijin * Add bfcl results to readme, fix links icons (#856) - ([5ef7f3d](https://github.com/boundaryml/baml/commit/5ef7f3db99d8d23ff97f1e8372ee71ab7aa127aa) ) - aaronvg * Fix prompt fiddle and playground styles, add more logging, and add stop-reason to playground (#858) - ([38e3153](https://github.com/boundaryml/baml/commit/38e3153843a17ae1e87ae9879ab4374b083d77d0) ) - aaronvg * Bump version to 0.53.0 - ([fd16839](https://github.com/boundaryml/baml/commit/fd16839a2c0b9d92bd5bdcb57f950e22d0a29959) ) - Aaron Villalpando [0.52.1](https://github.com/boundaryml/baml/compare/0.52.0..0.52.1) - 2024-07-24 --------------------------------------------------------------------------------- ### Bug Fixes * build python x86\_64-linux with an older glibc (#834) - ([db12540](https://github.com/boundaryml/baml/commit/db12540a92abf055e286c60864299f53c246b62a) ) - Samuel Lijin [0.52.0](https://github.com/boundaryml/baml/compare/0.51.3..0.52.0) - 2024-07-24 --------------------------------------------------------------------------------- ### Features * Add official support for ruby (#823) - ([e81cc79](https://github.com/boundaryml/baml/commit/e81cc79498809a79f427864704b140967a41277a) ) - Samuel Lijin ### Bug Fixes * Fix ClientRegistry for Typescript code-gen (#828) - ([b69921f](https://github.com/boundaryml/baml/commit/b69921f45df0182072b09ab28fe6231ccfaa5767) ) - hellovai [0.51.2](https://github.com/boundaryml/baml/compare/0.51.1..0.51.2) - 2024-07-24 --------------------------------------------------------------------------------- ### Features * Add support for unions / maps / null in TypeBuilder. (#820) - ([8d9e92d](https://github.com/boundaryml/baml/commit/8d9e92d3050a67edbec5ee6056397becbcdb754b) ) - hellovai ### Bug Fixes * \[Playground\] Add a feedback button (#818) - ([f749f2b](https://github.com/boundaryml/baml/commit/f749f2b19b247de2f050beccd1fe8e50b7625757) ) - Samuel Lijin ### Documentation * Improvements across docs (#807) - ([bc0c176](https://github.com/boundaryml/baml/commit/bc0c1761699ee2485a0a8ee61cf4fda6b579f974) ) - Anish Palakurthi [0.51.1](https://github.com/boundaryml/baml/compare/0.51.0..0.51.1) - 2024-07-21 --------------------------------------------------------------------------------- ### Features * Add a feedback button to VSCode Extension (#811) - ([f371912](https://github.com/boundaryml/baml/commit/f3719127174d8f998579747f14fae8675dafba4c) ) - Samuel Lijin ### Bug * Allow default\_client\_mode in the generator #813 (#815) - ([6df7fca](https://github.com/boundaryml/baml/commit/6df7fcabc1eb55b08a50741f2346440f631abd63) ) - hellovai [0.51.0](https://github.com/boundaryml/baml/compare/0.50.0..0.51.0) - 2024-07-19 --------------------------------------------------------------------------------- ### Bug Fixes * Improve BAML Parser for numbers and single-key objects (#785) - ([c5af7b0](https://github.com/boundaryml/baml/commit/c5af7b0d0e881c3046171ca17f317d820e8882e3) ) - hellovai * Add docs for VLLM (#792) - ([79e8773](https://github.com/boundaryml/baml/commit/79e8773e38da524795dda606b9fae09a274118e1) ) - hellovai * LLVM install and rebuild script (#794) - ([9ee66ed](https://github.com/boundaryml/baml/commit/9ee66ed2dd14bc0ee12a788f41eae64377e7f2b0) ) - Anish Palakurthi * Prevent version mismatches when generating baml\_client (#791) - ([d793603](https://github.com/boundaryml/baml/commit/d7936036e6afa4a0e738242cfb3feaa9e15b3657) ) - aaronvg * fiddle build fix (#800) - ([d304203](https://github.com/boundaryml/baml/commit/d304203241726ac0ba8781db7ac5693339189eb4) ) - aaronvg * Dont drop extra fields in dynamic classes when passing them as inputs to a function (#802) - ([4264c9b](https://github.com/boundaryml/baml/commit/4264c9b143edda0239af197d110357b1969bf12c) ) - aaronvg * Adding support for a sync client for Python + Typescript (#803) - ([62085e7](https://github.com/boundaryml/baml/commit/62085e79d4d86f580ce189bc60f36bd1414893c4) ) - hellovai * Fix WASM-related issues introduced in #803 (#804) - ([0a950e0](https://github.com/boundaryml/baml/commit/0a950e084748837ee2e269504d22dba66f339ca4) ) - hellovai * Adding various fixes (#806) - ([e8c1a61](https://github.com/boundaryml/baml/commit/e8c1a61a96051160566b6458dac5c89d5ddfb86e) ) - hellovai ### Features * implement maps in BAML (#797) - ([97d7e62](https://github.com/boundaryml/baml/commit/97d7e6223c68e9c338fe7110554f1f26b966f7e3) ) - Samuel Lijin * Support Vertex AI (Google Cloud SDK) (#790) - ([d98ee81](https://github.com/boundaryml/baml/commit/d98ee81a9440de0aaa6de05b33b8d3f709003a00) ) - Anish Palakurthi * Add copy buttons to test results in playground (#799) - ([b5eee3d](https://github.com/boundaryml/baml/commit/b5eee3d15a1be4373e25cc8ef1cf6e70d5dd39c9) ) - aaronvg ### Miscellaneous Chores * in fern config, defer to installed version (#789) - ([479f1b2](https://github.com/boundaryml/baml/commit/479f1b2b0b52faf47bc529e4c06c533a9467269a) ) - fern * publish docs on every push to the default branch (#796) - ([180824a](https://github.com/boundaryml/baml/commit/180824a3857a32eae679e4df5704abba3aa6246c) ) - Samuel Lijin * 🌿 introducing fern docs (#779) - ([46f06a9](https://github.com/boundaryml/baml/commit/46f06a95a1e262e62476768b812b372b696da1be) ) - fern * Add test for dynamic list input (#798) - ([7528d6a](https://github.com/boundaryml/baml/commit/7528d6ae10427c1304e356cf5b3c664e4fb2b1b1) ) - aaronvg [0.50.0](https://github.com/boundaryml/baml/compare/0.49.0..0.50.0) - 2024-07-11 --------------------------------------------------------------------------------- ### Bug Fixes * \[Playground\] Environment variable button is now visible on all themes (#762) - ([adc4da1](https://github.com/boundaryml/baml/commit/adc4da1fa36cc9c30ea36e25de1a6cefcce0bc97) ) - aaronvg * \[Playground\] Fix to cURL rendering and mime\_type overriding (#763) - ([67f9c6a](https://github.com/boundaryml/baml/commit/67f9c6add5ea8bbbd5ee82c28476fe0ebbefe344) ) - Anish Palakurthi ### Features * \[Runtime\] Add support for clients that change at runtime using ClientRegistry (#683) - ([c0fb454](https://github.com/boundaryml/baml/commit/c0fb4540d9193194fcafd7fcef71468442d9e6fa) ) - hellovai [https://docs.boundaryml.com/docs/calling-baml/client-registry](https://docs.boundaryml.com/docs/calling-baml/client-registry) ### Documentation * Add more documentation for TypeBuilder (#767) - ([85dc8ab](https://github.com/boundaryml/baml/commit/85dc8ab41e0df3267249a1efc4a95f010e52cc73) ) - Samuel Lijin [0.49.0](https://github.com/boundaryml/baml/compare/0.46.0..0.49.0) - 2024-07-08 --------------------------------------------------------------------------------- ### Bug Fixes * Fixed Azure / Ollama clients. Removing stream\_options from azure and ollama clients (#760) - ([30bf88f](https://github.com/boundaryml/baml/commit/30bf88f65c8583ab02db6a7b7db40c1e9f3b05b6) ) - hellovai ### Features * Add support for arm64-linux (#751) - ([adb8ee3](https://github.com/boundaryml/baml/commit/adb8ee3097fd386370f75b3ba179d18b952e9678) ) - Samuel Lijin [0.48.0](https://github.com/boundaryml/baml/compare/0.47.0..0.48.0) - 2024-07-04 --------------------------------------------------------------------------------- ### Bug Fixes * Fix env variables dialoge on VSCode (#750) * Playground selects correct function after loading (#757) - ([09963a0](https://github.com/boundaryml/baml/commit/09963a02e581da9eb8f7bafd3ba812058c97f672) ) - aaronvg ### Miscellaneous Chores * Better error messages on logging failures to Boundary Studio (#754) - ([49c768f](https://github.com/boundaryml/baml/commit/49c768fbe8eb8023cba28b8dc68c2553d8b2318a) ) - aaronvg [0.47.0](https://github.com/boundaryml/baml/compare/0.46.0..0.47.0) - 2024-07-03 --------------------------------------------------------------------------------- ### Bug Fixes * make settings dialog work in vscode again (#750) ([c94e355](https://github.com/boundaryml/baml/commit/c94e35551872f65404136b60f800fb1688902c11) ) - aaronvg * restore releases on arm64-linux (#751) - ([adb8ee3](https://github.com/boundaryml/baml/commit/adb8ee3097fd386370f75b3ba179d18b952e9678) ) - Samuel Lijin [0.46.0](https://github.com/boundaryml/baml/compare/0.45.0..0.46.0) - 2024-07-03 --------------------------------------------------------------------------------- ### Bug Fixes * Fixed tracing issues for Boundary Studio (#740) - ([77a4db7](https://github.com/boundaryml/baml/commit/77a4db7ef4b939636472ad4975d74e9d1a577cbf) ) - Samuel Lijin * Fixed flush() to be more reliable (#744) - ([9dd5fda](https://github.com/boundaryml/baml/commit/9dd5fdad5c2897b49a5a536df2e9ef775857a39d) ) - Samuel Lijin * Remove error when user passes in extra fields in a class (#746) - ([2755b43](https://github.com/boundaryml/baml/commit/2755b43257f9405ae66a30982d9711fc3f2c0854) ) - aaronvg ### Features * Add support for base\_url for the google-ai provider (#747) - ([005b1d9](https://github.com/boundaryml/baml/commit/005b1d93b7f7d2aa12a1487911766cccd9c25e98) ) - hellovai * Playground UX improvements (#742) - ([5cb56fd](https://github.com/boundaryml/baml/commit/5cb56fdc39496f0aedacd79766c0e93cb0e401b8) ) - hellovai * Prompt Fiddle now auto-switches functions when to change files (#745) ### Documentation * Added a large example project on promptfiddle.com (#741) - ([f80da1e](https://github.com/boundaryml/baml/commit/f80da1e1dd11f0457b5789bc9ce6923a8ed88b51) ) - aaronvg * Mark ruby as in beta (#743) - ([901109d](https://github.com/boundaryml/baml/commit/901109dbb327e6e3e1b65fda37100fcd45f97e07) ) - Samuel Lijin [0.45.0](https://github.com/boundaryml/baml/compare/0.44.0..0.45.0) - 2024-06-29 --------------------------------------------------------------------------------- ### Bug Fixes * Fixed streaming in Python Client which didn’t show result until later (#726) - ([e4f2daa](https://github.com/boundaryml/baml/commit/e4f2daa9e85bb1711d112fb0c87c0d769be0bb2d) ) - Anish Palakurthi * Improve playground stability on first load (#732) - ([2ac7b32](https://github.com/boundaryml/baml/commit/2ac7b328e89400cba0d9eb4f6d09c6a03feb71a5) ) - Anish Palakurthi * Add improved static analysis for jinja (#734) - ([423faa1](https://github.com/boundaryml/baml/commit/423faa1af5a594b7f78f7bb5620e3146a8989da5) ) - hellovai ### Documentation * Docs for Dynamic Types (#722) [https://docs.boundaryml.com/docs/calling-baml/dynamic-types](https://docs.boundaryml.com/docs/calling-baml/dynamic-types) ### Features * Show raw cURL request in Playground (#723) - ([57928e1](https://github.com/boundaryml/baml/commit/57928e178549cb3e5118ce374aab5d0fbad7038b) ) - Anish Palakurthi * Support bedrock as a provider (#725) - ([c64c665](https://github.com/boundaryml/baml/commit/c64c66522a1d496493a30f593103209acd201364) ) - Samuel Lijin [0.44.0](https://github.com/boundaryml/baml/compare/0.43.0..0.44.0) - 2024-06-26 --------------------------------------------------------------------------------- ### Bug Fixes * Fix typebuilder for random enums (#721) [0.43.0](https://github.com/boundaryml/baml/compare/0.42.0..0.43.0) - 2024-06-26 --------------------------------------------------------------------------------- ### Bug Fixes * fix pnpm lockfile issue (#720) [0.42.0](https://github.com/boundaryml/baml/compare/0.41.0..0.42.0) - 2024-06-26 --------------------------------------------------------------------------------- ### Bug Fixes * correctly propagate LICENSE to baml-py (#695) - ([3fda880](https://github.com/boundaryml/baml/commit/3fda880bf39b32191b425ae75e8b491d10884cf6) ) - Samuel Lijin ### Miscellaneous Chores * update jsonish readme (#685) - ([b19f04a](https://github.com/boundaryml/baml/commit/b19f04a059ba18d54544cb278b6990b95170d3f3) ) - Samuel Lijin ### Vscode * add link to tracing, show token counts (#703) - ([64aa18a](https://github.com/boundaryml/baml/commit/64aa18a9cc34071655141c8f6e2ad04ac90e7be1) ) - Samuel Lijin \[0.41.0\] - 2024-06-20 ----------------------- ### Bug Fixes * rollback git lfs, images broken in docs rn (#534) - ([6945506](https://github.com/boundaryml/baml/commit/694550664fa45b5f76987e2663c9d7e7a9a6a2d2) ) - Samuel Lijin * search for markdown blocks correctly (#641) - ([6b8abf1](https://github.com/boundaryml/baml/commit/6b8abf1ccf55bbe7c3bc1046c78081126e01f134) ) - Samuel Lijin * restore one-workspace-per-folder (#656) - ([a464bde](https://github.com/boundaryml/baml/commit/a464bde566199ace45285a78a7f542cd7217fb65) ) - Samuel Lijin * ruby generator should be ruby/sorbet (#661) - ([0019f39](https://github.com/boundaryml/baml/commit/0019f3951b8fe2b49e62eb11d869516b8088e9cb) ) - Samuel Lijin * ruby compile error snuck in (#663) - ([0cb2583](https://github.com/boundaryml/baml/commit/0cb25831788eb8b3eb0a38383917f6d1ffb5633a) ) - Samuel Lijin ### Documentation * add typescript examples (#477) - ([532481c](https://github.com/boundaryml/baml/commit/532481c3df4063b37a8834a5fe2bbce3bb37d2f5) ) - Samuel Lijin * add titles to code blocks for all CodeGroup elems (#483) - ([76c6b68](https://github.com/boundaryml/baml/commit/76c6b68b27ee37972fa226be0b4dfe31f7b4b5ec) ) - Samuel Lijin * add docs for round-robin clients (#500) - ([221f902](https://github.com/boundaryml/baml/commit/221f9020d850e6d24fe2fd8a684081726a0659af) ) - Samuel Lijin * add ruby example (#689) - ([16e187f](https://github.com/boundaryml/baml/commit/16e187f6698a1cc86a37eedf2447648d810370ad) ) - Samuel Lijin ### Features * implement `baml version --check --output json` (#444) - ([5f076ac](https://github.com/boundaryml/baml/commit/5f076ace1f92dc2141b231c9e62f4dc23f7fef18) ) - Samuel Lijin * show update prompts in vscode (#451) - ([b66da3e](https://github.com/boundaryml/baml/commit/b66da3ee355fcd6a8677d834ecb05af44cbf8f20) ) - Samuel Lijin * add tests to check that baml version —check works (#454) - ([be1499d](https://github.com/boundaryml/baml/commit/be1499dfa82ff8ab923a16d45290758120d95015) ) - Samuel Lijin * parse typescript versions in version —check (#473) - ([b4b2250](https://github.com/boundaryml/baml/commit/b4b2250c37b900db899256159bbfc3aa2ec819cb) ) - Samuel Lijin * implement round robin client strategies (#494) - ([599fcdd](https://github.com/boundaryml/baml/commit/599fcdd2a45c5b1e935f36769784ca944566b88c) ) - Samuel Lijin * add integ-tests support to build (#542) - ([f59cf2e](https://github.com/boundaryml/baml/commit/f59cf2e1a9ec7edbe174f4bc7ff9391f2cff3208) ) - Samuel Lijin * make ruby work again (#650) - ([6472bec](https://github.com/boundaryml/baml/commit/6472bec231b581076ee7edefaab2e7979b2bf336) ) - Samuel Lijin * Add RB2B tracking script (#682) - ([54547a3](https://github.com/boundaryml/baml/commit/54547a34d40cd40a43767919dbc9faa68a82faea) ) - hellovai ### Miscellaneous Chores * add nodemon config to typescript/ (#435) - ([231b396](https://github.com/boundaryml/baml/commit/231b3967bc947c4651156bc55fd66552782824c9) ) - Samuel Lijin * finish gloo to BoundaryML renames (#452) - ([88a7fda](https://github.com/boundaryml/baml/commit/88a7fdacc826e78ef21c6b24745ee469d9d02e6a) ) - Samuel Lijin * set up lfs (#511) - ([3a43143](https://github.com/boundaryml/baml/commit/3a431431e8e38dfc68763f15ccdcd1d131f23984) ) - Samuel Lijin * add internal build tooling for sam (#512) - ([9ebacca](https://github.com/boundaryml/baml/commit/9ebaccaa542760cb96382ae2a91d780f1ade613b) ) - Samuel Lijin * delete clients dir, this is now dead code (#652) - ([ec2627f](https://github.com/boundaryml/baml/commit/ec2627f59c7fe9edfff46fcdb65f9b9f0e2e072c) ) - Samuel Lijin * consolidate vscode workspace, bump a bunch of deps (#654) - ([82bf6ab](https://github.com/boundaryml/baml/commit/82bf6ab1ad839f84782a7ef0441f21124c368757) ) - Samuel Lijin * Add RB2B tracking script to propmt fiddle (#681) - ([4cf806b](https://github.com/boundaryml/baml/commit/4cf806bba26563fd8b6ddbd68296ab8bdfac21c4) ) - hellovai * Adding better release script (#688) - ([5bec282](https://github.com/boundaryml/baml/commit/5bec282d39d2250b39ef4aba5d6bba9830a35988) ) - hellovai ### \[AUTO\ \ * patch\] Version bump for nightly release \[NIGHTLY:cli\] \[NIGHTLY:vscode\_ext\] \[NIGHTLY:client-python\] - ([d05a22c](https://github.com/boundaryml/baml/commit/d05a22ca4135887738adbce638193d71abca42ec) ) - GitHub Action ### Build * fix baml-core-ffi script (#521) - ([b1b7f4a](https://github.com/boundaryml/baml/commit/b1b7f4af0991ef6453f888f27930f3faaae337f5) ) - Samuel Lijin * fix engine/ (#522) - ([154f646](https://github.com/boundaryml/baml/commit/154f6468ec0aa6de1b033ee1cbc76e60acc363ea) ) - Samuel Lijin ### Integ-tests * add ruby test - ([c0bc101](https://github.com/boundaryml/baml/commit/c0bc10126ea32d099f1398f2c5faa08b111554ba) ) - Sam Lijin ### Readme * add function calling, collapse the table (#505) - ([2f9024c](https://github.com/boundaryml/baml/commit/2f9024c28ba438267de37ac43c6570a2f0398b5a) ) - Samuel Lijin ### Release * bump versions for everything (#662) - ([c0254ae](https://github.com/boundaryml/baml/commit/c0254ae680365854c51c7a4e58ea68d1901ea033) ) - Samuel Lijin ### Vscode * check for updates on the hour (#434) - ([c70a3b3](https://github.com/boundaryml/baml/commit/c70a3b373cb2346a0df9a1eba0ebacb74d59b53e) ) - Samuel Lijin [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # generator | Boundary Documentation Each `generator` that you define in your BAML project will tell `baml-cli generate` to generate code for a specific target language. You can define multiple `generator` clauses in your BAML project, and `baml-cli generate` will generate code for each of them. If you created your project using `baml-cli init`, then one has already been generated for you! PythonPython (Pydantic 1.x)TypeScriptReact/Next.jsRuby (beta)GoOpenAPI | | | | --- | --- | | 1 | generator target { | | 2 | output\_type "python/pydantic" | | 3 | | | 4 | // Where the generated code will be saved (relative to baml\_src/) | | 5 | output\_dir "../" | | 6 | | | 7 | // What interface you prefer to use for the generated code (sync/async) | | 8 | // Both are generated regardless of the choice, just modifies what is exported | | 9 | // at the top level | | 10 | default\_client\_mode "sync" | | 11 | | | 12 | // Version of runtime to generate code for (should match installed baml-py version) | | 13 | version "0.76.2" | | 14 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Image / Audio / Pdf / Video | Boundary Documentation BAML functions can accept image, audio, Pdf, and video inputs for multimedia processing capabilities. Choose the appropriate type based on your needs: [Image\ \ Create Image objects from URLs, base64 data, or browser-specific sources like File and Blob objects.](https://docs.boundaryml.com/ref/baml_client/image) [Audio\ \ Create Audio objects from URLs, base64 data, or browser-specific sources like File and Blob objects.](https://docs.boundaryml.com/ref/baml_client/audio) [Pdf\ \ Create Pdf objects from URLs, base64 data, or browser-specific sources like File and Blob objects.](https://docs.boundaryml.com/ref/baml_client/pdf) [Video\ \ Create Video objects from URLs, base64 data, or browser-specific sources like File and Blob objects.](https://docs.boundaryml.com/ref/baml_client/video) URL Resolution -------------- BAML automatically handles URL-to-base64 conversion based on provider requirements. You can control this behavior using the `media_url_handler` configuration option in your client definition. By default: * URLs are converted to base64 for providers that don’t support external URLs * Google Cloud Storage URLs (gs://) are preserved when using Google providers * MIME types are added when required by the provider See the client configuration documentation for provider-specific defaults and configuration options. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Keywords AI | Boundary Documentation Keywords AI is a proxying layer that allows you to route requests to hundreds of models. Follow the [Keywords AI + BAML Installation Guide](https://docs.keywordsai.co/integration/development-frameworks/baml) to get started! [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # @assert | Boundary Documentation The `@assert` attribute in BAML is used for strict validations. If a type fails an `@assert` validation, it will not be returned in the response, and an exception will be raised if it’s part of the top-level type. Usage ----- Asserts can be named or unnamed. ### Field Assertion BAML | | | | --- | --- | | 1 | class Foo { | | 2 | // @assert will be applied to the field with the name "bar" | | 3 | bar int @assert(between\_0\_and\_10, {{ this > 0 and this < 10 }}) | | 4 | } | BAML | | | | --- | --- | | 1 | class Foo { | | 2 | // @assert will be applied to the field with no name | | 3 | bar int @assert({{ this > 0 and this < 10 }}) | | 4 | } | BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | // @assert will be applied to each element in the array | | 3 | my\_field (string @assert(is\_valid\_email, {{ this\|regex\_match("@") }}))\[\] | | 4 | } | ### Parameter Assertion Asserts can also be applied to parameters. BAML | | | | --- | --- | | 1 | function MyFunction(x: int @assert(between\_0\_and\_10, {{ this > 0 and this < 10 }})) { | | 2 | client "openai/gpt-4o" | | 3 | prompt #"Hello, world!"# | | 4 | } | ### Block Assertion Asserts can be used in a block definition, referencing fields within the block. BAML | | | | --- | --- | | 1 | class Foo { | | 2 | bar int | | 3 | baz string | | 4 | @@assert(baz\_length\_limit, {{ this.baz\|length < this.bar }}) | | 5 | } | See [Jinja in Attributes](https://docs.boundaryml.com/ref/attributes/jinja-in-attributes) for a longer description of the Jinja syntax available in asserts. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Image | Boundary Documentation Image values to BAML functions can be created in client libraries. This document explains how to use these functions both at compile time and runtime to handle image data. For more details, refer to [image types](https://docs.boundaryml.com/ref/baml/types#image) . Usage Examples -------------- PythonTypeScriptTSXGoRuby | | | | --- | --- | | 1 | from baml\_py import Image | | 2 | from baml\_client import b | | 3 | | | 4 | async def test\_image\_input(): | | 5 | # Create an Image from a URL | | 6 | img = Image.from\_url("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek\_%28character%29.png") | | 7 | res = await b.TestImageInput(img=img) | | 8 | | | 9 | # Create an Image from Base64 data | | 10 | image\_b64 = "iVB0xyz..." | | 11 | img = Image.from\_base64("image/png", image\_b64) | | 12 | res = await b.TestImageInput(img=img) | API Reference ------------- ###### Python ###### TypeScript ###### Go ###### Ruby ### Static Methods from\_url (url: str, media\_type: Optional\[str\] = None) -> Image Creates an Image object from a URL. Optionally specify the media type, otherwise it will be inferred from the URL. from\_base64 (media\_type: str, base64: str) -> Image Creates an Image object using Base64 encoded data along with the given MIME type. ### Instance Methods is\_url () -> bool Check if the image is stored as a URL. as\_url () -> str Get the URL of the image if it’s stored as a URL. Raises an exception if the image is not stored as a URL. as\_base64 () -> list\[str\] Get the base64 data and media type if the image is stored as base64. Returns `[base64_data, media_type]`. Raises an exception if the image is not stored as base64. baml\_serialize () -> dict Convert the image to a dictionary representation. Returns either `{"url": str}` or `{"base64": str, "media_type": str}`. URL Handling ------------ When you create an Image using `from_url`, BAML processes the URL according to your client’s `media_url_handler` configuration: * **[OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai#media_url_handler) **: By default keeps URLs as-is (`send_url`). Set to `send_base64` to convert to base64. * **[Anthropic](https://docs.boundaryml.com/ref/llm-client-providers/anthropic#media_url_handler) **: By default keeps URLs as-is (`send_url`). The provider accepts both formats. * **[Google AI](https://docs.boundaryml.com/ref/llm-client-providers/google-ai-gemini#media_url_handler) **: By default uses `send_base64_unless_google_url` to preserve gs:// URLs while converting others. * **[Vertex AI](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#media_url_handler) **: By default uses `send_url_add_mime_type` to include MIME type information. * **[AWS Bedrock](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock#media_url_handler) **: By default converts to base64 (`send_base64`). You can override these defaults in your client configuration. See the provider-specific documentation linked above for details. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Audio | Boundary Documentation Audio values to BAML functions can be created in client libraries. This document explains how to use these functions both at compile time and runtime to handle audio data. For more details, refer to [audio types](https://docs.boundaryml.com/ref/baml/types#audio) . Usage Examples -------------- PythonTypeScriptTSXGoRuby | | | | --- | --- | | 1 | from baml\_py import Audio | | 2 | from baml\_client import b | | 3 | | | 4 | async def test\_audio\_input(): | | 5 | # Create an Audio object from a URL | | 6 | audio = Audio.from\_url("https://actions.google.com/sounds/v1/emergency/beeper\_emergency\_call.ogg") | | 7 | res = await b.TestAudioInput(audio=audio) | | 8 | | | 9 | # Create an Audio object from Base64 data | | 10 | audio\_b64 = "iVB0xyz..." | | 11 | audio = Audio.from\_base64("audio/ogg", audio\_b64) | | 12 | res = await b.TestAudioInput(audio=audio) | API Reference ------------- ###### Python ###### TypeScript ###### Go ###### Ruby ### Static Methods from\_url (url: str, media\_type: Optional\[str\] = None) -> Audio Creates an Audio object from a URL. Optionally specify the media type, otherwise it will be inferred from the URL. from\_base64 (media\_type: str, base64: str) -> Audio Creates an Audio object using Base64 encoded data along with the given MIME type. ### Instance Methods is\_url () -> bool Check if the audio is stored as a URL. as\_url () -> str Get the URL of the audio if it’s stored as a URL. Raises an exception if the audio is not stored as a URL. as\_base64 () -> list\[str\] Get the base64 data and media type if the audio is stored as base64. Returns `[base64_data, media_type]`. Raises an exception if the audio is not stored as base64. baml\_serialize () -> dict Convert the audio to a dictionary representation. Returns either `{"url": str}` or `{"base64": str, "media_type": str}`. URL Handling ------------ Audio URLs are processed according to your client’s `media_url_handler` configuration: * **[OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai#media_url_handler) **: By default converts to base64 (`send_base64`) for compatibility. * **[Vertex AI](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#media_url_handler) **: By default uses `send_url_add_mime_type` to include MIME type. * **[Anthropic](https://docs.boundaryml.com/ref/llm-client-providers/anthropic#media_url_handler) **: By default keeps URLs as-is (`send_url`). * **[Google AI](https://docs.boundaryml.com/ref/llm-client-providers/google-ai-gemini#media_url_handler) **: By default keeps URLs as-is (`send_url`). * **[AWS Bedrock](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock#media_url_handler) **: By default converts to base64 (`send_base64`). Note: OpenAI requires audio to be base64-encoded, which is why the default is `send_base64`. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Cerebras | Boundary Documentation [Cerebras](https://inference-docs.cerebras.ai/resources/openai) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) provider with an overridden `base_url`. See [OpenAI Generic](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) for more details about parameters. **Example:** BAML | | | | --- | --- | | 1 | client CerebrasLlama { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "https://api.cerebras.ai/v1" | | 5 | api\_key env.CEREBRAS\_API\_KEY | | 6 | model "llama-3.3-70b" | | 7 | } | | 8 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # config (logging / environment variables) | Boundary Documentation Various settings are configurable via environment variables. | Setting | Environment Variable | Description | Default | | --- | --- | --- | --- | | Logging Level | `BAML_LOG` | The logging level to use (`INFO`, `DEBUG`, `TRACE`, `WARN`, `ERROR`, `OFF`) | `INFO` | | Text / JSON Mode | `BAML_LOG_JSON` | Whether to log in JSON format or human-readable format (`1`, `0`) | `0` | | Max Log Chunk Size | `BAML_LOG_MAX_MESSAGE_LENGTH` | How large of a prompt / response will be logged (`0` for no limit) | `64000` | | Log Color Mode | `BAML_LOG_COLOR_MODE` | Whether to color the log output (`auto`, `always`, `never`) | `auto` | Setting can also be modified via functions in `baml_client.config`. ###### python ###### typescript ###### ruby | | | | --- | --- | | 1 | from baml\_client.config import set\_from\_env, set\_log\_level, | | 2 | set\_log\_json\_mode, set\_log\_max\_message\_length, | | 3 | get\_log\_level, reset\_baml\_env\_vars | ### set\_log\_level Environment variable: `BAML_LOG` | | | | --- | --- | | 1 | def set\_log\_level(level: "INFO" \| "DEBUG" \| "TRACE" \| "WARN" \| "ERROR" \| "OFF"): | | 2 | ... | ### set\_log\_json\_mode Environment variable: `BAML_LOG_JSON` Switches the log output between JSON and human-readable format. | | | | --- | --- | | 1 | def set\_log\_json\_mode(enable: bool): | ### set\_log\_max\_message\_length `0` for unlimited Environment variable: `BAML_LOG_MAX_MESSAGE_LENGTH` | | | | --- | --- | | 1 | def set\_log\_max\_message\_length(length: int): | ### get\_log\_level | | | | --- | --- | | 1 | def get\_log\_level() -> "INFO" \| "DEBUG" \| "TRACE" \| "WARN" \| "ERROR" \| "OFF": | ### reset\_baml\_env\_vars `reset_baml_env_vars` is deprecated and is safe to remove, since environment variables are now lazily loaded on each function call Resets the environment variables to the values in the provided dictionary. Will also reset any logging related environment variables to those passed in (if set explicitly). | | | | --- | --- | | 1 | def reset\_baml\_env\_vars(env: Dict\[str, str\]): | * * * Setting Environment Variables ----------------------------- ### In the VSCode Playground Once you open a `.baml` file in VSCode, you should see a small button over every BAML function: `Open Playground`. Then you should be able to set environment variables in the settings tab. ![VSCode Code Lens](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Fvscode%2Fcode-lens.png&w=2048&q=75) Or type `BAML Playground` in the VSCode Command Bar (`CMD + Shift + P` or `CTRL + Shift + P`) to open the playground. ### For Boundary Studio Integration To send logs and traces to Boundary Studio, you need to set the `BOUNDARY_API_KEY` environment variable. This key is provided when you create an API key in your Boundary Studio dashboard. ###### Next.js ###### Express.js ###### Flask ###### Rails | | | | --- | --- | | $ | \# .env.local | | $ | BOUNDARY\_API\_KEY=your\_api\_key\_here | ### For Your App (Default) BAML will do its best to load environment variables from your program. Any of the following strategies for setting env vars are compatible with BAML: * Setting them in your shell before running your program * In your `Dockerfile` * In your `next.config.js` * In your Kubernetes manifest * From `secrets-store.csi.k8s.io` * From a secrets provider such as [Infisical](https://infisical.com/) / [Doppler](https://www.doppler.com/) * From a `.env` file (using `dotenv` CLI) * Using account credentials for ephemeral token generation (e.g., Vertex AI Auth Tokens) * `python-dotenv` package in Python or `dotenv` package in Node.js | | | | --- | --- | | $ | export MY\_SUPER\_SECRET\_API\_KEY="..." | | $ | python my\_program\_using\_baml.py | ###### python ###### typescript ###### ruby | | | | --- | --- | | 1 | from dotenv import load\_dotenv | | 2 | from baml\_client import b | | 3 | | | 4 | load\_dotenv() | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # @skip | Boundary Documentation The `@skip` attribute in BAML is used to exclude certain fields or values from being included in prompts or parsed responses. This can be useful when certain data is not relevant for the LLM’s processing. In the case of class fields, the field type must be nullable if `@skip` is used in order to allow parsing LLM responses that will not include the field. This is valid: OK | | | | --- | --- | | 1 | class MyClass { | | 2 | field1 string | | 3 | field2 string? @skip // OK because field2 is nullable | | 4 | } | This is not: NOT OK | | | | --- | --- | | 1 | class MyClass { | | 2 | field1 string | | 3 | field2 string @skip // Error: Field with @skip attribute must be optional. | | 4 | } | Prompt Impact ------------- ### Without `@skip` BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 | | 3 | Value2 | | 4 | } | | 5 | | | 6 | class MyClass { | | 7 | field1 string | | 8 | field2 string? | | 9 | } | **ctx.output\_format:** * `MyEnum` | | | --- | | MyEnum | | \--- | | Value1 | | Value2 | * `MyClass` | | | --- | | { | | field1: string, | | field2: string or null, | | } | ### With `@skip` BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 | | 3 | Value2 @skip | | 4 | } | | 5 | | | 6 | class MyClass { | | 7 | field1 string | | 8 | field2 string? @skip | | 9 | } | **ctx.output\_format:** * `MyEnum` | | | --- | | MyEnum | | \--- | | Value1 | * `MyClass` | | | --- | | { | | field1: string, | | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # litellm | Boundary Documentation [LiteLLM](https://www.litellm.ai/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) provider with an overridden `base_url`. See [OpenAI Generic](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) for more details about parameters. Set up ------ 1. Set up [LiteLLM Proxy server](https://docs.litellm.ai/docs/proxy/docker_quick_start#21-start-proxy) 2. Set up LiteLLM Client in BAML files 3. Use it in a BAML function! BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "http://0.0.0.0:4000" | | 5 | api\_key env.LITELLM\_API\_KEY | | 6 | model "gpt-5" | | 7 | } | | 8 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # client Option | Boundary Documentation Added in 0.216.0 The `client` option provides a simple way to override which LLM client a function uses at runtime. It’s a shorthand for creating a `ClientRegistry` and calling [`set_primary()`](https://docs.boundaryml.com/ref/baml_client/client-registry#the-set_primary-method) . Quick Start ----------- ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | | | 3 | \# Use shorthand provider/model syntax | | 4 | result = await b.ExtractResume("...", baml\_options={"client": "openai/gpt-4o-mini"}) | | 5 | | | 6 | \# Use OpenRouter for open-source models | | 7 | result = await b.ExtractResume("...", baml\_options={"client": "openrouter/meta-llama/llama-3.1-70b-instruct"}) | | 8 | | | 9 | \# Or reference a client defined in your .baml files | | 10 | result = await b.ExtractResume("...", baml\_options={"client": "MyCustomClient"}) | | 11 | | | 12 | \# Use with\_options to set for multiple calls | | 13 | my\_b = b.with\_options(client="openai/gpt-4o-mini") | | 14 | result1 = await my\_b.ExtractResume("...") | | 15 | result2 = await my\_b.ExtractInvoice("...") | When to Use ----------- Use the `client` option when you want to: * Quickly switch between different LLM providers or models * A/B test different models * Use different clients for different environments (dev vs prod) * Override the default client defined in your `.baml` files Precedence ---------- If you provide both `client` and `client_registry`, the `client` option takes precedence: ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_py import ClientRegistry | | 2 | | | 3 | cr = ClientRegistry() | | 4 | cr.set\_primary("ModelA") | | 5 | | | 6 | \# "ModelB" will be used, not "ModelA" | | 7 | result = await b.ExtractResume("...", baml\_options={ | | 8 | "client": "ModelB", | | 9 | "client\_registry": cr | | 10 | }) | Valid Client Names ------------------ The `client` value can be: 1. **Shorthand provider/model syntax** - Use `provider/model` format for quick access: * `"openai/gpt-4o-mini"` - OpenAI models * `"anthropic/claude-sonnet-4-20250514"` - Anthropic models * `"openrouter/meta-llama/llama-3.1-70b-instruct"` - OpenRouter models * `"google-ai/gemini-2.0-flash"` - Google AI models 2. **Client defined in `.baml` files** - Reference by name (e.g., `"MyCustomClient"`) If the client name is not found, you’ll get a runtime error when the function is called. Comparison with ClientRegistry ------------------------------ | Feature | `client` option | `ClientRegistry` | | --- | --- | --- | | Set primary client | Yes | Yes (`set_primary`) | | Add custom clients | No | Yes (`add_llm_client`) | | Override client options | No | Yes | | Simplicity | Simple string | More complex | Use `client` for simple overrides. Use `ClientRegistry` when you need to add new clients or customize client options at runtime. Related Topics -------------- * [ClientRegistry](https://docs.boundaryml.com/guide/baml-advanced/llm-client-registry) - For advanced client configuration * [with\_options](https://docs.boundaryml.com/ref/baml_client/with-options) - Set default options for a client [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # @check | Boundary Documentation The `@check` attribute in BAML adds validations without raising exceptions if they fail. This allows the validations to be inspected at runtime. Usage ----- ### Field Check BAML | | | | --- | --- | | 1 | class Foo { | | 2 | bar int @check(less\_than\_zero, {{ this < 0 }}) | | 3 | } | ### Block check | | | | --- | --- | | 1 | class Bar { | | 2 | baz int | | 3 | quux string | | 4 | @@check(quux\_limit, {{ this.quux\|length < this.baz }}) | | 5 | } | See [Jinja in Attributes](https://docs.boundaryml.com/ref/attributes/jinja-in-attributes) for a longer description of the Jinja syntax available in checks. Benefits -------- * **Non-Intrusive Validation**: Allows for validation checks without interrupting the flow of data processing. * **Runtime Inspection**: Enables inspection of validation results at runtime. See more in [validations guide](https://docs.boundaryml.com/guide/baml-advanced/checks-and-asserts) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # @description / @@description | Boundary Documentation The `@description` attribute in BAML provides additional context to fields or values in prompts. This can help the LLM understand the intended use or meaning of a field or value. Prompt Impact ------------- ### Without `@description` BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string | | 3 | } | **ctx.output\_format:** | | | --- | | { | | property1: string | | } | ### With `@description` BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string @description("The name of the object") | | 3 | } | **ctx.output\_format:** | | | --- | | { | | // The name of the object | | property1: string | | } | Prompt Impact (enum - value) ---------------------------- ### Without `@description` BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 | | 3 | Value2 | | 4 | } | **ctx.output\_format:** | | | --- | | MyEnum | | \--- | | Value1 | | Value2 | ### With `@description` BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 @description("The first value") | | 3 | Value2 @description("The second value") | | 4 | } | **ctx.output\_format:** | | | --- | | MyEnum | | \--- | | Value1: The first value | | Value2: The second value | Prompt Impact (enum) -------------------- BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 | | 3 | Value2 | | 4 | | | 5 | @@description("This enum represents status codes") | | 6 | } | **ctx.output\_format:** | | | --- | | MyEnum: This enum represents status codes | | \--- | | Value1 | | Value2 | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Jinja in Attributes | Boundary Documentation `@check` and `@assert` use [Jinja](https://docs.boundaryml.com/ref/prompt-syntax/what-is-jinja) syntax to specify the invariants (properties that should always hold true) of a type. ### Checks and Asserts This example demonstrates [@assert](https://docs.boundaryml.com/ref/attributes/assert) and [@check](https://docs.boundaryml.com/ref/attributes/check) on both class fields and the class block itself, and it shows a few examples of Jinja syntax. BAML | | | | --- | --- | | 1 | class Student { | | 2 | first\_name string @assert( {{ this\|length > 0 }}) | | 3 | last\_name string @assert( {{ this\|length > 0 }}) | | 4 | age int @check(old\_enough, {{ this > 5 }}) @check(u8, {{ this\|abs < 255 }}) | | 5 | concentration string @assert( {{ this.regex\_match("\[Math\|Science\]")}}) | | 6 | @@check(age\_threshold, {{ this.concentration != "calculus" or this.age > 12 }}) | | 7 | } | ### `this` keyword Inside a Jinja expression, `this` refers to the value of a class field, if the `@assert` or `@check` is applied to a class field, and it applies to the whole object if it is applied to the whole type with `@@assert()` or `@@check()`. ### Filters In Jinja, functions are called “filters”, and they are applied to arguments by writing `some_argument|some_filter`. Filters can be applied one after the other by chaining them with additional `|`s. * `abs`: Absolote value. * `capitalize`: Make the first letter uppercase * `escape`: Replace special HTML characters with their escaped counterparts * `first`: First item of a list * `last`: Last item of a list * `default(x)`: Returns `x` when applied to something undefined. * `float`: Convert to a float, or 0.0 if conversion fails * `int`: Convert to an int, or 0 if conversion fails * `join`: Concatenate a list of strings * `length`: List length * `lower`: Make the string lowercase * `upper`: Make the string uppercase * `map(filter)`: Apply a filter to each item in a list * `max`: Maximum of a list of numbers or Booleans * `min`: Minimum of a list of numbers or Booleans * `regex_match("regex")`: Return true if argument matches the regex * `reject("test")`: Filter out items that fail the test * `reverse`: Reverse a list or string * `round`: Round a float to the nearest int * `select("test_name")`: Retain the values of a list passing `test_name` * `sum`: Sum of a list of numbers * `title`: Convert a string to “Title Case” * `trim`: Remove leading and trailing whitespace from a string * `unique`: Remove duplicate entries in a list ### Common Patterns #### Test that a substring appears inside some string BAML | | | | --- | --- | | 1 | function GenerateStory(subject: string) -> string { | | 2 | client GPT4 | | 3 | prompt #"Write a story about {{ subject }}"# | | 4 | } | | 5 | | | 6 | test HorseStory { | | 7 | functions \[GenerateStory\] | | 8 | args { | | 9 | subject "Equestrian team coming-of-age story" | | 10 | } | | 11 | @@assert( {{ this\|lower\|regex\_match("horse") }} ) | | 12 | } | We use the `lower` filter to make the whole story lowercase, and pass the result to `regex_match()` to search for an occurrance of “horse”. #### Test that a string is an exact match BAML | | | | --- | --- | | 1 | class Person { | | 2 | first\_name string | | 3 | last\_name string | | 4 | } | | 5 | | | 6 | function ExtractPerson(description: string) -> Person { | | 7 | client GPT4 | | 8 | prompt #" | | 9 | Extract a Person from the description {{ description }}. | | 10 | {{ ctx.output\_format }} | | 11 | "# | | 12 | } | | 13 | | | 14 | test ExtractJohnDoe { | | 15 | functions \[ExtractPerson\] | | 16 | args { | | 17 | description "John Doe is a 5'6\\" man riding a stolen horse." | | 18 | } | | 19 | @@assert( {{ this.first\_name\|regex\_match("^John$") }} ) | | 20 | @@assert( {{ this.last\_name == "Doe" }} ) | | 21 | } | We can use `regex_match` with special control characters indicating the beginning and end of a string, as in the first `@@assert`, or simply check equality with a literal string as in the second `@@assert`. #### Test that item prices add up to a total BAML | | | | --- | --- | | 1 | class Receipt { | | 2 | establishment string | | 3 | items Item\[\] | | 4 | tax\_cents int | | 5 | total\_cents int | | 6 | } | | 7 | | | 8 | class Item { | | 9 | name string | | 10 | price\_cents int | | 11 | } | | 12 | | | 13 | function ExtractReceipt(text\_receipt: string) -> Receipt { | | 14 | client GPT4 | | 15 | prompt #" | | 16 | Extract the details of this receipt: {{ text\_receipt }} | | 17 | {{ ctx.output\_format }} | | 18 | "# | | 19 | } | | 20 | | | 21 | test SmallReceipt { | | 22 | functions \[ExtractReceipt\] | | 23 | args { | | 24 | text\_receipt "Nutty Squirrel. Affogato: $8.50. Kids cone: $6.50. Tax: $1. Total: $16.00" | | 25 | } | | 26 | | | 27 | @@assert( {{ this.items\|map(attribute="price\_cents")\|sum + this.tax\_cents == this.total\_cents }} ) | | 28 | } | To check that the numbers in our `Receipt` add up, we first `map` over the items to get the price of each item, then sum the list of prices, and check the sum of the items and the sales tax against the receipt total. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # AsyncClient / SyncClient | Boundary Documentation BAML generates both a sync client and an async client. They offer the exact same public API but methods are either synchronous or asynchronous. BAML Functions -------------- The generated client exposes all the functions that you’ve defined your BAML files as methods. Suppose we have this file named `baml_src/literature.baml`: baml\_src/literature.baml | | | | --- | --- | | 1 | function TellMeAStory() -> string { | | 2 | client "openai/gpt-4o" | | 3 | prompt #" | | 4 | Tell me a story | | 5 | "# | | 6 | } | | 7 | | | 8 | function WriteAPoemAbout(input: string) -> string { | | 9 | client "openai/gpt-4o" | | 10 | prompt #" | | 11 | Write a poem about {{ input }} | | 12 | "# | | 13 | } | After running `baml-cli generate` you can directly call these functions from your code. Here’s an example using the async client: ###### Python ###### TypeScript ###### Go ###### Ruby | | | | --- | --- | | 1 | from baml\_client.async\_client import b | | 2 | | | 3 | async def example(): | | 4 | # Call your BAML functions. | | 5 | story = await b.TellMeAStory() | | 6 | poem = await b.WriteAPoemAbout("Roses") | The sync client is exactly the same but it doesn’t need an async runtime, instead it just blocks. ###### Python ###### TypeScript ###### Go ###### Ruby | | | | --- | --- | | 1 | from baml\_client.sync\_client import b | | 2 | | | 3 | def example(): | | 4 | # Call your BAML functions. | | 5 | story = b.TellMeAStory() | | 6 | poem = b.WriteAPoemAbout("Roses") | Call Patterns ------------- The client object exposes some references to other objects that call your functions in a different manner. ### `.stream` The `.stream` object is used to stream the response from a function. ###### Python ###### TypeScript ###### Go ###### Ruby | | | | --- | --- | | 1 | from baml\_client.async\_client import b | | 2 | | | 3 | async def example(): | | 4 | stream = b.stream.TellMeAStory() | | 5 | | | 6 | async for partial in stream: | | 7 | print(partial) | | 8 | | | 9 | print(await stream.get\_final\_response()) | ### `.request` This feature was added in: v0.79.0 The `.request` object returns the raw HTTP request but it **does not** send it. However, the async client still returns an awaitable object because we might need to resolve media types like images and convert them to base64 or the required format in order to send them to the LLM. ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client.async\_client import b | | 2 | | | 3 | async def example(): | | 4 | request = await b.request.TellMeAStory() | | 5 | print(request.url) | | 6 | print(request.headers) | | 7 | print(request.body.json()) | ### `.stream_request` This feature was added in: v0.79.0 Same as [`.request`](https://docs.boundaryml.com/ref/baml_client/client#request) but sets the streaming options to `true`. ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client.async\_client import b | | 2 | | | 3 | async def example(): | | 4 | request = await b.stream\_request.TellMeAStory() | | 5 | print(request.url) | | 6 | print(request.headers) | | 7 | print(request.body.json()) | ### `.parse` This feature was added in: v0.79.0 The `.parse` object is used to parse the response returned by the LLM after the function call. Can be used in combination with [`.request`](https://docs.boundaryml.com/ref/baml_client/client#request) . ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | import requests | | 2 | \# requests is not async so for simplicity we'll use the sync client. | | 3 | from baml\_client.sync\_client import b | | 4 | | | 5 | def example(): | | 6 | # Get the HTTP request. | | 7 | request = b.request.TellMeAStory() | | 8 | | | 9 | # Send the HTTP request. | | 10 | response = requests.post(request.url, headers=request.headers, json=request.body.json()) | | 11 | | | 12 | # Parse the LLM response. | | 13 | parsed = b.parse.TellMeAStory(response.json()\["choices"\]\[0\]\["message"\]\["content"\]) | | 14 | | | 15 | # Fully parsed response. | | 16 | print(parsed) | ### `.parse_stream` This feature was added in: v0.79.0 Same as [`.parse`](https://docs.boundaryml.com/ref/baml_client/client#parse) but for streaming responses. Can be used in combination with [`.stream_request`](https://docs.boundaryml.com/ref/baml_client/client#stream_request) . ###### Python ###### TypeScript | | | | --- | --- | | 1 | from openai import AsyncOpenAI | | 2 | from baml\_client.async\_client import b | | 3 | | | 4 | async def example(): | | 5 | client = AsyncOpenAI() | | 6 | | | 7 | request = await b.stream\_request.TellMeAStory() | | 8 | stream = await client.chat.completions.create(\*\*request.body.json()) | | 9 | | | 10 | llm\_response: list\[str\] = \[\] | | 11 | async for chunk in stream: | | 12 | if len(chunk.choices) > 0 and chunk.choices\[0\].delta.content is not None: | | 13 | llm\_response.append(chunk.choices\[0\].delta.content) | | 14 | print(b.parse\_stream.TellMeAStory("".join(llm\_response))) | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # @alias / @@alias | Boundary Documentation The `@alias` attribute in BAML is used to rename fields or values for better understanding by the LLM, while keeping the original name in your code. This is particularly useful for prompt engineering, as it allows you to provide a more intuitive name for the LLM without altering your existing codebase. Prompt Impact (class) --------------------- ### Without `@alias` BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string | | 3 | } | **ctx.output\_format:** | | | --- | | { | | property1: string | | } | ### With `@alias` BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string @alias("name") | | 3 | } | **ctx.output\_format:** | | | --- | | { | | name: string | | } | Prompt Impact (enum) -------------------- BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 | | 3 | // Note that @@alias is applied to the enum itself, not the value | | 4 | @@alias("My Name") | | 5 | } | **ctx.output\_format:** | | | --- | | My Name | | \--- | | Value1 | Prompt Impact (enum value) -------------------------- BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 @alias("Something") | | 3 | } | **ctx.output\_format:** | | | --- | | MyEnum | | \--- | | Something | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Conditionals | Boundary Documentation Use conditional statements to control the flow and output of your templates based on conditions: | | | | --- | --- | | 1 | function MyFunc(user: User) -> string { | | 2 | prompt #" | | 3 | {% if user.is\_active %} | | 4 | Welcome back, {{ user.name }}! | | 5 | {% else %} | | 6 | Please activate your account. | | 7 | {% endif %} | | 8 | "# | | 9 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # groq | Boundary Documentation [Groq](https://groq.com/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. See [https://console.groq.com/docs/openai](https://console.groq.com/docs/openai) for more information. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai-generic | | 3 | options { | | 4 | base\_url "https://api.groq.com/openai/v1" | | 5 | api\_key env.GROQ\_API\_KEY | | 6 | model "llama-3-groq-70b-tool-use" | | 7 | } | | 8 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # huggingface | Boundary Documentation [HuggingFace](https://huggingface.co/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. See [https://huggingface.co/docs/inference-endpoints/index](https://huggingface.co/docs/inference-endpoints/index) for more information on their Inference Endpoints. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai-generic | | 3 | options { | | 4 | base\_url "https://api-inference.huggingface.co/v1" | | 5 | api\_key env.HUGGINGFACE\_API\_KEY | | 6 | } | | 7 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Variables | Boundary Documentation See [template\_string](https://docs.boundaryml.com/ref/baml/template-string) to learn how to add variables in .baml files [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # LMStudio | Boundary Documentation [LMStudio](https://lmstudio.ai/docs) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. See [https://lmstudio.ai/docs/developer/openai-compat/chat-completions](https://lmstudio.ai/docs/developer/openai-compat/chat-completions) for more information. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "http://localhost:1234/v1" | | 5 | model "TheBloke/phi-2-GGUF" | | 6 | } | | 7 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Video | Boundary Documentation Video values to BAML functions can be created in client libraries. This document explains how to use these functions both at compile time and runtime to handle video data. For more details, refer to [video types](https://docs.boundaryml.com/ref/baml/types#video) . When you create a `Video` using `from_url` (Python) or `fromUrl` (TypeScript), the URL is passed directly to the model without any intermediate fetching. If the model cannot access external media, it will fail on such inputs. In these cases, convert the video to Base64 before passing it to the model. For AWS Bedrock models with video support, you can pass `s3://` URIs through `Video.from_url`. BAML forwards the URI as an `s3Location` and includes the `media_type` you provide so Bedrock can fetch the object without uploading it through BAML first. BAML does **not** infer video MIME types for Bedrock requests, so always supply the correct `media_type` (for example, `video/mp4`). Direct video inputs are only supported by Google Gemini, Google Vertex AI, and AWS Bedrock models that advertise video support. Other providers (Anthropic Claude, OpenAI GPT-4o) will error or require you to extract frames as images or provide transcripts. See the model compatibility table below for details. Usage Examples -------------- PythonTypeScriptTSXRuby | | | | --- | --- | | 1 | from baml\_py import Video | | 2 | from baml\_client import b | | 3 | | | 4 | async def test\_video\_input(): | | 5 | # Create a Video object from a URL | | 6 | video = Video.from\_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ") | | 7 | res = await b.TestVideoInput(video=video) | | 8 | | | 9 | # Create a Video object from Base64 data | | 10 | video\_b64 = "AAAAGGZ0eXBpc29t..." | | 11 | video = Video.from\_base64("video/mp4", video\_b64) | | 12 | res = await b.TestVideoInput(video=video) | | 13 | | | 14 | # Pass an S3 video reference directly to an AWS Bedrock model | | 15 | bedrock\_video = Video.from\_url( | | 16 | "s3://baml-test-bucket/example/path/video.mp4", media\_type="video/mp4" | | 17 | ) | | 18 | res = await b.TestAwsVideoDescribe(video\_input=bedrock\_video) | API Reference ------------- ###### Python ###### TypeScript ###### Go ###### Ruby ### Static Methods from\_url (url: str, media\_type: Optional\[str\] = None) -> Video Creates a Video object from a URL. Optionally specify the media type, otherwise it will be inferred from the URL. When targeting AWS Bedrock with an `s3://` URI, pass the media type explicitly so the request includes the expected `format`. from\_base64 (media\_type: str, base64: str) -> Video Creates a Video object using Base64 encoded data along with the given MIME type. ### Instance Methods is\_url () -> bool Check if the video is stored as a URL. as\_url () -> str Get the URL of the video if it’s stored as a URL. Raises an exception if the video is not stored as a URL. as\_base64 () -> list\[str\] Get the base64 data and media type if the video is stored as base64. Returns `[base64_data, media_type]`. Raises an exception if the video is not stored as base64. baml\_serialize () -> dict Convert the video to a dictionary representation. Returns either `{"url": str}` or `{"base64": str, "media_type": str}`. URL Handling ------------ Video URLs are typically passed directly to providers without conversion (default: `never` for all providers). This is because: 1. Video files are often too large for base64 encoding 2. Most providers that support video input can fetch URLs directly 3. Base64 encoding videos significantly increases payload size Provider defaults: * **[OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai#media_url_handler) **: Keeps URLs as-is (`send_url`) * **[Anthropic](https://docs.boundaryml.com/ref/llm-client-providers/anthropic#media_url_handler) **: Keeps URLs as-is (`send_url`) * **[Google AI](https://docs.boundaryml.com/ref/llm-client-providers/google-ai-gemini#media_url_handler) **: Keeps URLs as-is (`send_url`) * **[Vertex AI](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#media_url_handler) **: Keeps URLs as-is (`send_url`) * **[AWS Bedrock](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock#media_url_handler) **: Keeps URLs as-is (`send_url`) For Bedrock, `s3://` URLs are passed through unchanged and encoded in the request body as an `s3Location`, allowing Bedrock to fetch the object directly from S3 without routing bytes through BAML. You can override this behavior using `media_url_handler.video` in your client configuration, but be aware of size limitations when using `send_base64` mode. Model Compatibility ------------------- Different AI models have varying levels of support for video input methods **(As of July 2025)**: | Provider / API | | Video Input Support | | --- | --- | --- | | **Anthropic** | ✗ | No native video support. Only accepts PDF, images, and common docs. | | **AWS Bedrock** | ✓ | Fully multimodal. Accepts video as Base64 bytes in request or S3 URI. JSON must include format (e.g. mp4) and source. | | **Google Gemini** | ✓ | Three options: upload with `ai.files.upload` and use `file_uri`, inline Base64 (<20MB), or YouTube URL (preview). Requires `mime_type`. | | **OpenAI** | ✗ | Video input not yet in public API. Only text and images. Must extract frames and send as images for now. | | **Google Vertex AI** | ✓ | Accepts video via Cloud Storage `gs://` URI (up to 2GB), public HTTP/HTTPS URL (≤15MB), YouTube URL, or inline Base64. Requires `mimeType`. | For most models, direct video input is limited to Google Gemini, Google Vertex AI, and AWS Bedrock models with video support. For other providers, you must extract frames as images or use transcripts. Always specify the correct MIME type (e.g., video/mp4) when required. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Microsoft Foundry / Azure AI Foundry | Boundary Documentation Microsoft Foundry is the new way to use AI models on Azure, which is a simplified version of Azure-on-openai provider. To use the Microsoft Foundry (Azure AI) ([https://ai.azure.com](https://ai.azure.com/) ), you can leverage the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider. Use the **Completions** API setup to make it work with BAML. **Example:** BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | // use the API key it indicates in the 'models' sidebar navigation menu, and clicking on the model you want to use | | 5 | base\_url "https://boundarydev-resource.openai.azure.com/openai/v1/" | | 6 | api\_key env.AZURE\_AI\_FOUNDRY\_API\_KEY | | 7 | model "gpt-5-mini" // use the model you actually deployed | | 8 | } | | 9 | } | See here to see how to get your API key and base url: ![Azure AI Foundry](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Flanguages%2Fazure-ai-foundary.png&w=3840&q=75) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Tinfoil | Boundary Documentation [Tinfoil](https://tinfoil.sh/) is verifiably private AI inference. Tinfoil supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. | | | | --- | --- | | 1 | client TinfoilDeepSeek { | | 2 | provider openai-generic | | 3 | retry\_policy Exponential | | 4 | options { | | 5 | base\_url "https://deepseek-r1-70b-p.model.tinfoil.sh/v1" | | 6 | model "deepseek-r1-70b" | | 7 | api\_key env.TINFOIL\_API\_KEY | | 8 | } | | 9 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # openrouter | Boundary Documentation The `openrouter` provider offers native integration with [OpenRouter](https://openrouter.ai/) , a unified API gateway providing access to 300+ AI models from OpenAI, Anthropic, Google, Meta, and others through a single interface. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openrouter | | 3 | options { | | 4 | model "openai/gpt-4o-mini" | | 5 | } | | 6 | } | You can also use [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) with OpenRouter by manually setting the `base_url`. The `openrouter` provider simplifies this by providing sensible defaults. OpenRouter-specific options --------------------------- The `openrouter` provider extends [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) with OpenRouter-specific defaults. See [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) for the full list of supported options. api\_key string **Default: `env.OPENROUTER_API_KEY`** base\_url string **Default: `https://openrouter.ai/api/v1`** model stringRequired The model to use, in OpenRouter’s `provider/model-name` format. | Model | Description | | --- | --- | | `openai/gpt-4o-mini` | Fast, cost-effective | | `anthropic/claude-3.5-sonnet` | Claude 3.5 Sonnet | | `anthropic/claude-3-haiku` | Fast Claude variant | | `google/gemini-2.0-flash-001` | Gemini 2.0 Flash | | `meta-llama/llama-3.1-70b-instruct` | Llama 3.1 70B | OpenRouter supports model variants for routing preferences (e.g., `:nitro` for high-throughput): BAML | | | | --- | --- | | 1 | client NitroClient { | | 2 | provider openrouter | | 3 | options { | | 4 | model "meta-llama/llama-3.1-70b-instruct:nitro" | | 5 | } | | 6 | } | For the complete list, see [OpenRouter Models](https://openrouter.ai/models) . App attribution headers ----------------------- OpenRouter supports optional headers for app attribution. Pass these via the `headers` option: | Header | Description | | --- | --- | | `X-Title` | Your app name, shown on openrouter.ai rankings | | `HTTP-Referer` | Your site URL for rankings and attribution | BAML | | | | --- | --- | | 1 | client OpenRouterWithAttribution { | | 2 | provider openrouter | | 3 | options { | | 4 | model "anthropic/claude-3-haiku" | | 5 | headers { | | 6 | "X-Title" "My App" | | 7 | "HTTP-Referer" "https://myapp.com" | | 8 | } | | 9 | } | | 10 | } | For all other options (`temperature`, `max_tokens`, `headers`, etc.), see [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) and the [OpenRouter API documentation](https://openrouter.ai/docs/api/reference/overview) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # @@dynamic | Boundary Documentation The `@@dynamic` attribute in BAML allows for the dynamic modification of fields or values at runtime. This is particularly useful when you need to adapt the structure of your data models based on runtime conditions or external inputs. Usage ----- ### Dynamic Classes The `@@dynamic` attribute can be applied to classes, enabling the addition of fields dynamically during runtime. BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string | | 3 | property2 int? | | 4 | | | 5 | @@dynamic // allows adding fields dynamically at runtime | | 6 | } | ### Dynamic Enums Similarly, the `@@dynamic` attribute can be applied to enums, allowing for the modification of enum values at runtime. BAML | | | | --- | --- | | 1 | enum MyEnum { | | 2 | Value1 | | 3 | Value2 | | 4 | | | 5 | @@dynamic // allows modifying enum values dynamically at runtime | | 6 | } | Using `@@dynamic` with TypeBuilder ---------------------------------- To modify dynamic types at runtime, you can use the `TypeBuilder` from the `baml_client`. Below are examples for Python, TypeScript, and Ruby. Read more about the `TypeBuilder` in the [TypeBuilder](https://docs.boundaryml.com/ref/baml_client/type-builder#type-builders) section. ### Python Example | | | | --- | --- | | 1 | from baml\_client.type\_builder import TypeBuilder | | 2 | from baml\_client import b | | 3 | | | 4 | async def run(): | | 5 | tb = TypeBuilder() | | 6 | tb.MyClass.add\_property('email', tb.string()) | | 7 | tb.MyClass.add\_property('address', tb.string()).description("The user's address") | | 8 | res = await b.DynamicUserCreator("some user info", { "tb": tb }) | | 9 | # Now res can have email and address fields | | 10 | print(res) | ### TypeScript Example | | | | --- | --- | | 1 | import TypeBuilder from '../baml\_client/type\_builder' | | 2 | import { b } from '../baml\_client' | | 3 | | | 4 | async function run() { | | 5 | const tb = new TypeBuilder() | | 6 | tb.MyClass.addProperty('email', tb.string()) | | 7 | tb.MyClass.addProperty('address', tb.string()).description("The user's address") | | 8 | const res = await b.DynamicUserCreator("some user info", { tb: tb }) | | 9 | // Now res can have email and address fields | | 10 | console.log(res) | | 11 | } | ### Ruby Example | | | | --- | --- | | 1 | require\_relative 'baml\_client/client' | | 2 | | | 3 | def run | | 4 | tb = Baml::TypeBuilder.new | | 5 | tb.MyClass.add\_property('email', tb.string) | | 6 | tb.MyClass.add\_property('address', tb.string).description("The user's address") | | 7 | | | 8 | res = Baml::Client.dynamic\_user\_creator(input: "some user info", baml\_options: {tb: tb}) | | 9 | # Now res can have email and address fields | | 10 | puts res | | 11 | end | Testing Dynamic Types --------------------- Dynamic classes and enums can be modified in tests using the `type_builder` and `dynamic` blocks. All properties added in the `dynamic` block will be available during the test execution. | | | | --- | --- | | 1 | class DynamicClass { | | 2 | static\_prop string | | 3 | @@dynamic | | 4 | } | | 5 | | | 6 | function ReturnDynamicClass(input: string) -> DynamicClass { | | 7 | // ... | | 8 | } | | 9 | | | 10 | test DynamicClassTest { | | 11 | functions \[ReturnDynamicClass\] | | 12 | type\_builder { | | 13 | dynamic class DynamicClass { | | 14 | new\_prop\_here string | | 15 | } | | 16 | } | | 17 | args { | | 18 | input "test data" | | 19 | } | | 20 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Pdf | Boundary Documentation Pdf values to BAML functions can be created in client libraries. This document explains how to use these functions both at compile time and runtime to handle Pdf data. For more details, refer to [pdf types](https://docs.boundaryml.com/ref/baml/types#pdf) . `Pdf` instances can be created from URLs, Base64 data, or local files. URL processing is controlled by your client’s [`media_url_handler`](https://docs.boundaryml.com/ref/baml_client/pdf#url-handling) configuration. Please note that many websites will block requests to directly fetch PDFs. Some models like Vertex AI require the media type to be explicitly specified. Always provide the `mediaType` parameter when possible for better compatibility. The PDF input may need to be put into the `user` message, not the `system` message in your prompt. Usage Examples -------------- PythonTypeScriptTSXGoRuby | | | | --- | --- | | 1 | from baml\_py import Pdf | | 2 | from baml\_client import b | | 3 | | | 4 | async def test\_pdf\_input(): | | 5 | # Create a Pdf object from URL | | 6 | pdf\_url = Pdf.from\_url("https://example.com/document.pdf") | | 7 | res1 = await b.TestPdfInput(pdf=pdf\_url) | | 8 | | | 9 | # Create a Pdf object from Base64 data | | 10 | pdf\_b64 = "JVBERi0K..." | | 11 | pdf = Pdf.from\_base64(pdf\_b64) | | 12 | res2 = await b.TestPdfInput(pdf=pdf) | Test Pdf in the Playground -------------------------- To test a function that accepts a `pdf` in the VSCode playground using a local file, add a `test` block to your `.baml` file: | | | | --- | --- | | 1 | function AnalyzePdf(myPdf: pdf) -> string { | | 2 | client GPT4o | | 3 | prompt #" | | 4 | Summarize this Pdf: {{myPdf}} | | 5 | "# | | 6 | } | | 7 | | | 8 | test PdfFileTest { | | 9 | functions \[AnalyzePdf\] | | 10 | args { | | 11 | myPdf { | | 12 | file "../documents/report.pdf" | | 13 | } | | 14 | } | | 15 | } | file stringRequired The path to the PDF file. Supports relative paths (resolved from the current BAML file) or absolute paths. The file does not need to be inside `baml_src/`. API Reference ------------- ###### Python ###### TypeScript ###### Go ###### Ruby ### Static Methods from\_url (url: str) -> Pdf Creates a Pdf object from a URL. The media type is automatically set to `application/pdf`. from\_base64 (base64: str) -> Pdf Creates a Pdf object using Base64 encoded data. The media type is automatically set to `application/pdf`. ### Instance Methods is\_url () -> bool Check if the Pdf is stored as a URL. as\_url () -> str Get the URL if the Pdf is stored as a URL. Raises an exception if the Pdf is not stored as a URL. as\_base64 () -> list\[str\] Get the base64 data and media type if the Pdf is stored as base64. Returns `[base64_data, media_type]`. Raises an exception if the Pdf is not stored as base64. baml\_serialize () -> dict Convert the Pdf to a dictionary representation. Returns either `{"url": str}` or `{"base64": str, "media_type": str}`. URL Handling ------------ PDF URLs are processed according to your client’s `media_url_handler` configuration: * **[Anthropic](https://docs.boundaryml.com/ref/llm-client-providers/anthropic#media_url_handler) **: By default converts to base64 (`send_base64`) as required by their API. * **[AWS Bedrock](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock#media_url_handler) **: By default converts to base64 (`send_base64`). * **[OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai#media_url_handler) **: By default keeps URLs as-is (`send_url`). * **[Google AI](https://docs.boundaryml.com/ref/llm-client-providers/google-ai-gemini#media_url_handler) **: By default keeps URLs as-is (`send_url`). * **[Vertex AI](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#media_url_handler) **: By default keeps URLs as-is (`send_url`). Many websites block direct PDF fetching. If you encounter issues with URL-based PDFs, try: 1. Using `media_url_handler.pdf = "send_base64"` to fetch and embed the content 2. Downloading the PDF locally and using `from_file` 3. Using a proxy or authenticated request Configuring Media URL Handlers ------------------------------ You can customize how PDF URLs are processed by configuring the `media_url_handler` in your BAML client definition. This is useful when you need to override provider defaults or ensure compatibility with specific model requirements. | | | | --- | --- | | 1 | // Basic example: OpenAI client with PDF base64 encoding | | 2 | client MyOpenAIClient { | | 3 | provider openai | | 4 | options { | | 5 | model "gpt-4o" | | 6 | api\_key env.OPENAI\_API\_KEY | | 7 | media\_url\_handler { | | 8 | pdf "send\_base64" // Convert PDF URLs to base64 | | 9 | } | | 10 | } | | 11 | } | | 12 | | | 13 | function AnalyzePdf(pdf: pdf) -> string { | | 14 | client MyOpenAIClient | | 15 | prompt #" | | 16 | Analyze this PDF: {{ pdf }} | | 17 | "# | | 18 | } | ### Available Modes The `media_url_handler.pdf` setting accepts the following values: * **`send_base64`**: Fetch the PDF from the URL and convert it to base64 before sending to the model. Use this when the provider requires base64 encoding or when you want to ensure the content is embedded in the request. * **`send_url`**: Keep the PDF as a URL and send it directly to the model. The model provider will fetch the content. Note that many providers don’t support direct URL fetching for PDFs. * **`send_url_add_mime_type`**: Keep the PDF as a URL but add MIME type information (`application/pdf`). Useful for providers like Vertex AI that require explicit MIME types. * **`send_base64_unless_google_url`**: Keep Google Cloud Storage URLs (`gs://`) as-is, but convert all other URLs to base64. Useful when working with Google AI models. ### Provider-Specific Examples | | | | --- | --- | | 1 | // OpenAI: Override default (send\_url) to use base64 | | 2 | client OpenAIClient { | | 3 | provider openai | | 4 | options { | | 5 | model "gpt-4o" | | 6 | api\_key env.OPENAI\_API\_KEY | | 7 | media\_url\_handler { | | 8 | pdf "send\_base64" // OpenAI requires base64 for PDFs | | 9 | } | | 10 | } | | 11 | } | | 12 | | | 13 | // Anthropic: Override default (send\_base64) to use URL | | 14 | client AnthropicClient { | | 15 | provider anthropic | | 16 | options { | | 17 | model "claude-3-5-sonnet-20241022" | | 18 | api\_key env.ANTHROPIC\_API\_KEY | | 19 | media\_url\_handler { | | 20 | pdf "send\_url" // Anthropic supports both URL and base64 | | 21 | } | | 22 | } | | 23 | } | | 24 | | | 25 | // Vertex AI: Use URL with MIME type | | 26 | client VertexClient { | | 27 | provider vertex-ai | | 28 | options { | | 29 | model "gemini-1.5-pro" | | 30 | project "your-project" | | 31 | location "us-central1" | | 32 | media\_url\_handler { | | 33 | pdf "send\_url\_add\_mime\_type" // Vertex requires MIME type | | 34 | } | | 35 | } | | 36 | } | | 37 | | | 38 | // Google AI: Use conditional handling for GCS URLs | | 39 | client GoogleAIClient { | | 40 | provider google-ai | | 41 | options { | | 42 | model "gemini-1.5-pro" | | 43 | api\_key env.GOOGLE\_API\_KEY | | 44 | media\_url\_handler { | | 45 | pdf "send\_base64\_unless\_google\_url" // Keep gs:// URLs, convert others | | 46 | } | | 47 | } | | 48 | } | | 49 | | | 50 | // You can configure multiple media types independently | | 51 | client MultiMediaClient { | | 52 | provider openai | | 53 | options { | | 54 | model "gpt-4o" | | 55 | api\_key env.OPENAI\_API\_KEY | | 56 | media\_url\_handler { | | 57 | image "send\_base64" | | 58 | audio "send\_url" | | 59 | pdf "send\_base64" | | 60 | video "send\_url" | | 61 | } | | 62 | } | | 63 | } | You can configure different handling modes for each media type (`image`, `audio`, `pdf`, `video`) independently in the same client. Model Compatibility ------------------- Different AI models have varying levels of support for PDF input methods **(As of July 2025)**: | Provider / API | | PDF Input Support | | --- | --- | --- | | **Anthropic** | ✓ | Accepts PDFs as a direct https URL or a base‑64 string in a document block. | | **AWS Bedrock** | ✓ | PDF must be supplied as raw bytes (base‑64 in the request) or as an Amazon S3 URI (s3:// style). Ordinary https links are not supported. | | **Google Gemini** | ✓ | Provide as inline base‑64 or upload first with media.upload and use the returned file\_uri. The model does not fetch http/https URLs for you. | | **OpenAI** | ✓ | PDF support (added March 2025) via base‑64 in the request. Supplying a plain URL is not accepted. | | **Google Vertex AI** | ✓ | Accepts either base‑64 data or a Cloud Storage gs:// URI in a file\_data part; you must set mime\_type (for PDFs use application/pdf). Generic https URLs are not allowed. | For most models, direct https URLs are not accepted (except Anthropic). Prefer using base64, file uploads, or the appropriate cloud storage/file upload mechanism for your provider. Always specify the correct MIME type (e.g., application/pdf) when required. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # retry_policy | Boundary Documentation A retry policy can be attached to any `client` and will attempt to retry requests that fail due to a network error. BAML | | | | --- | --- | | 1 | retry\_policy MyPolicyName { | | 2 | max\_retries 3 | | 3 | } | Usage: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider anthropic | | 3 | retry\_policy MyPolicyName | | 4 | options { | | 5 | model "claude-sonnet-4-20250514" | | 6 | api\_key env.ANTHROPIC\_API\_KEY | | 7 | } | | 8 | } | Fields ------ max\_retries intRequired Number of **additional** retries to attempt after the initial request fails. strategy Strategy The strategy to use for retrying requests. Default is `constant_delay(delay_ms=200)`. | Strategy | Docs | Notes | | --- | --- | --- | | `constant_delay` | [Docs](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy#constant-delay) | | | `exponential_backoff` | [Docs](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy#exponential-backoff) | | Example: BAML | | | | --- | --- | | 1 | retry\_policy MyPolicyName { | | 2 | max\_retries 3 | | 3 | strategy { | | 4 | type constant\_delay | | 5 | delay\_ms 200 | | 6 | } | | 7 | } | Strategies ---------- ### constant\_delay type constant\_delayRequired Configures to the constant delay strategy. delay\_ms int The delay in milliseconds to wait between retries. **Default: 200** ### exponential\_backoff type exponential\_backoffRequired Configures to the exponential backoff strategy. delay\_ms int The initial delay in milliseconds to wait between retries. **Default: 200** multiplier float The multiplier to apply to the delay after each retry. **Default: 1.5** max\_delay\_ms int The maximum delay in milliseconds to wait between retries. **Default: 10000** [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # ctx (accessing metadata) | Boundary Documentation If you try rendering `{{ ctx }}` into the prompt (literally just write that out!), you’ll see all the metadata we inject to run this prompt within the playground preview. In the earlier tutorial we mentioned `ctx.output_format`, which contains the schema, but you can also access client information: Usecase: Conditionally render based on client provider ------------------------------------------------------ In this example, we render the list of messages in XML tags if the provider is Anthropic (as they recommend using them as delimiters). See also [template\_string](https://docs.boundaryml.com/ref/baml/template-string) as it’s used in here. | | | | --- | --- | | 1 | template\_string RenderConditionally(messages: Message\[\]) #" | | 2 | {% for message in messages %} | | 3 | {%if ctx.client.provider == "anthropic" %} | | 4 | {{ message.user\_name }}: {{ message.content }} | | 5 | {% else %} | | 6 | {{ message.user\_name }}: {{ message.content }} | | 7 | {% endif %} | | 8 | {% endfor %} | | 9 | "# | | 10 | | | 11 | function MyFuncWithGPT4(messages: Message\[\]) -> string { | | 12 | client GPT4o | | 13 | prompt #" | | 14 | {{ RenderConditionally(messages)}} | | 15 | "# | | 16 | } | | 17 | | | 18 | function MyFuncWithAnthropic(messages: Message\[\]) -> string { | | 19 | client Claude35 | | 20 | prompt #" | | 21 | {{ RenderConditionally(messages )}} | | 22 | #" | | 23 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-18T08%3A08%3A42.149Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-18T08%3A08%3A42.149Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # fallback | Boundary Documentation You can use the `fallback` provider to add more resilience to your application. A fallback will attempt to use the first client, and if it fails, it will try the second client, and so on. You can nest fallbacks inside of other fallbacks. BAML | | | | --- | --- | | 1 | client SuperDuperClient { | | 2 | provider fallback | | 3 | options { | | 4 | strategy \[ |\ | 5 | ClientA |\ | 6 | ClientB |\ | 7 | ClientC |\ | 8 | \] | | 9 | } | | 10 | } | Options ------- strategy List\[string\]Required The list of client names to try in order. Cannot be empty. retry\_policy ------------- Like any other client, you can specify a retry policy for the fallback client. See [retry\_policy](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy) for more information. The retry policy will test the fallback itself, after the entire strategy has failed. BAML | | | | --- | --- | | 1 | client SuperDuperClient { | | 2 | provider fallback | | 3 | retry\_policy MyRetryPolicy | | 4 | options { | | 5 | strategy \[ |\ | 6 | ClientA |\ | 7 | ClientB |\ | 8 | ClientC |\ | 9 | \] | | 10 | } | | 11 | } | Nesting multiple fallbacks -------------------------- You can nest multiple fallbacks inside of each other. The fallbacks will just chain as you would expect. BAML | | | | --- | --- | | 1 | client SuperDuperClient { | | 2 | provider fallback | | 3 | options { | | 4 | strategy \[ |\ | 5 | ClientA |\ | 6 | ClientB |\ | 7 | ClientC |\ | 8 | \] | | 9 | } | | 10 | } | | 11 | | | 12 | client MegaClient { | | 13 | provider fallback | | 14 | options { | | 15 | strategy \[ |\ | 16 | SuperDuperClient |\ | 17 | ClientD |\ | 18 | \] | | 19 | } | | 20 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # _.role | Boundary Documentation BAML prompts are compiled into a `messages` array (or equivalent) that most LLM providers use: BAML Prompt -> `[{ role: "user": content: "hi there"}, { role: "assistant", ...}]` By default, BAML puts everything into a single message with the `system` role if available (or whichever one is best for the provider you have selected). When in doubt, the playground always shows you the current role for each message. To specify a role explicitly, add the `{{ _.role("user")}}` syntax to the prompt | | | | --- | --- | | 1 | prompt #" | | 2 | {{ \_.role("system") }} Everything after | | 3 | this element will be a system prompt! | | 4 | | | 5 | {{ \_.role("user")}} | | 6 | And everything after this | | 7 | will be a user role | | 8 | "# | Try it out in [PromptFiddle](https://www.promptfiddle.com/) BAML may change the default role to `user` if using specific APIs that only support user prompts, like when using prompts with images. We use `_` as the prefix of `_.role()` since we plan on adding more helpers here in the future. Example — Using `_.role()` in for-loops --------------------------------------- Here’s how you can inject a list of user/assistant messages and mark each as a user or assistant role: BAML | | | | --- | --- | | 1 | class Message { | | 2 | role string | | 3 | message string | | 4 | } | | 5 | | | 6 | function ChatWithAgent(input: Message\[\]) -> string { | | 7 | client GPT4o | | 8 | prompt #" | | 9 | {% for m in messages %} | | 10 | {{ \_.role(m.role) }} | | 11 | {{ m.message }} | | 12 | {% endfor %} | | 13 | "# | | 14 | } | BAML | | | | --- | --- | | 1 | function ChatMessages(messages: string\[\]) -> string { | | 2 | client GPT4o | | 3 | prompt #" | | 4 | {% for m in messages %} | | 5 | {{ \_.role("user" if loop.index % 2 == 1 else "assistant") }} | | 6 | {{ m }} | | 7 | {% endfor %} | | 8 | "# | | 9 | } | Example — Using `_.role()` in a template string ----------------------------------------------- BAML | | | | --- | --- | | 1 | template\_string YouAreA(name: string, job: string) #" | | 2 | {{ \_.role("system") }} | | 3 | You are an expert {{ name }}. {{ job }} | | 4 | | | 5 | {{ ctx.output\_format }} | | 6 | {{ \_.role("user") }} | | 7 | "# | | 8 | | | 9 | function CheckJobPosting(post: string) -> bool { | | 10 | client GPT4o | | 11 | prompt #" | | 12 | {{ YouAreA("hr admin", "Your role is to ensure every job posting is bias free.") }} | | 13 | | | 14 | {{ post }} | | 15 | "# | | 16 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # BamlValidationError | Boundary Documentation The `BamlValidationError` class represents an error that occurs when BAML fails to parse or validate LLM output. Type Definition --------------- Type Definition | | | | --- | --- | | 1 | class BamlValidationError extends Error { | | 2 | type: 'BamlValidationError' | | 3 | message: string | | 4 | prompt: string | | 5 | raw\_output: string | | 6 | detailed\_message: string | | 7 | } | Properties ---------- type 'BamlValidationError' Literal type identifier for the error class. message string Error message describing the specific validation failure. prompt string The original prompt sent to the LLM. raw\_output string The raw output from the LLM that failed validation. detailed\_message string Comprehensive error information that includes the complete history of all failed attempts when using fallback clients or retry policies. When multiple attempts are made (via fallback or retry), this field contains formatted details about each failed attempt, making it invaluable for debugging complex client configurations. Type Guards ----------- The error can be identified using TypeScript’s `instanceof` operator: Type Check | | | | --- | --- | | 1 | if (error instanceof BamlValidationError) { | | 2 | // Handle validation error | | 3 | } | Related Errors -------------- * [BamlClientFinishReasonError](https://docs.boundaryml.com/ref/baml_client/errors/baml-client-finish-reason-error) * [BamlClientError](https://docs.boundaryml.com/ref/baml_client/errors/baml-client-finish-reason-error) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # with_options | Boundary Documentation 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 ###### TypeScript ###### Go ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import ClientRegistry, Collector | | 3 | | | 4 | \# Simple: just set the client name | | 5 | my\_b = b.with\_options(client="openai/gpt-5-mini") | | 6 | | | 7 | \# Or with full options for advanced use cases | | 8 | collector = Collector(name="my-collector") | | 9 | client\_registry = ClientRegistry() | | 10 | client\_registry.set\_primary("openai/gpt-5-mini") | | 11 | env = {"BAML\_LOG": "DEBUG", "OPENAI\_API\_KEY": "key-123"} | | 12 | | | 13 | \# Create client with default options | | 14 | my\_b = b.with\_options(collector=collector, client\_registry=client\_registry, env=env) | | 15 | | | 16 | \# Uses the default options | | 17 | result = my\_b.ExtractResume("...") | | 18 | | | 19 | \# Override options for a specific call | | 20 | other\_collector = Collector(name="other-collector") | | 21 | result2 = my\_b.ExtractResume("...", baml\_options={"collector": other\_collector}) | 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 ###### TypeScript ###### Go ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import ClientRegistry, Collector | | 3 | | | 4 | def run(): | | 5 | # Configure options | | 6 | collector = Collector(name="my-collector") | | 7 | client\_registry = ClientRegistry() | | 8 | client\_registry.set\_primary("openai/gpt-5-mini") | | 9 | | | 10 | # Create configured client | | 11 | my\_b = b.with\_options(collector=collector, client\_registry=client\_registry) | | 12 | | | 13 | # All calls will use the configured options | | 14 | res = my\_b.ExtractResume("...") | | 15 | invoice = my\_b.ExtractInvoice("...") | | 16 | | | 17 | # Access configuration | | 18 | print(my\_b.client\_registry) | | 19 | # Access logs from the collector | | 20 | print(collector.logs) | | 21 | print(collector.last) | ### Per-call Tags Add tags to a specific BAML function call. Tags are useful for correlating requests, A/B versions, user IDs, etc. ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | collector = Collector(name="tags-collector") | | 5 | res = b.TestOpenAIGPT4oMini( | | 6 | "hello", | | 7 | baml\_options={ | | 8 | "collector": collector, | | 9 | "tags": {"call\_id": "first", "version": "v1"}, | | 10 | }, | | 11 | ) | | 12 | | | 13 | print(collector.last.tags) | ### Parallel Execution When running functions in parallel, `with_options` helps maintain consistent configuration across all calls. This works seamlessly with the [`Collector`](https://docs.boundaryml.com/ref/baml_client/collector) functionality. ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client.async\_client import b | | 2 | from baml\_py import ClientRegistry, Collector | | 3 | import asyncio | | 4 | | | 5 | async def run(): | | 6 | collector = Collector(name="my-collector") | | 7 | my\_b = b.with\_options(collector=collector, client\_registry=client\_registry) | | 8 | | | 9 | # Run multiple functions in parallel | | 10 | res, invoice = await asyncio.gather( | | 11 | my\_b.ExtractResume("..."), | | 12 | my\_b.ExtractInvoice("...") | | 13 | ) | | 14 | | | 15 | # Access results and logs | | 16 | print(res) | | 17 | print(invoice) | | 18 | # Use tags or iterate logs to correlate specific calls | | 19 | for log in collector.logs: | | 20 | print(log.usage) | ### Streaming Mode `with_options` can be used with streaming functions while maintaining all configured options. ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client.async\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | async def run(): | | 5 | collector = Collector(name="my-collector") | | 6 | my\_b = b.with\_options(collector=collector, client\_registry=client\_registry) | | 7 | | | 8 | stream = my\_b.stream.ExtractResume("...") | | 9 | async for chunk in stream: | | 10 | print(chunk) | | 11 | | | 12 | result = await stream.get\_final\_result() | | 13 | # Use tags or collector.last / collector.logs for usage | | 14 | print(collector.last.usage) | API Reference ------------- ### with\_options Parameters 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`](https://docs.boundaryml.com/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`](https://docs.boundaryml.com/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 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](https://docs.boundaryml.com/ref/baml_client/collector) - Track function calls and usage metrics * [TypeBuilder](https://docs.boundaryml.com/ref/baml_client/type-builder) - Build custom types for your functions * [Client Registry](https://docs.boundaryml.com/ref/baml_client/client-registry) - Manage LLM clients and their configurations * [Environment Variables](https://docs.boundaryml.com/ref/baml/general-baml-syntax/environment-variables) - Set environment variables * [AbortController](https://docs.boundaryml.com/ref/baml_client/abort-signal) - Cancel in-flight operations The configured client maintains the same interface as the base client, so you can use all the same functions and methods. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # What are attributes? | Boundary Documentation In BAML, attributes are used to provide additional metadata or behavior to fields and types. They can be applied at different levels, such as field-level or block-level, depending on their intended use. Field-Level Attributes ---------------------- Field-level attributes are applied directly to individual fields within a class or enum. They modify the behavior or metadata of that specific field. ### Examples of Field-Level Attributes * **`@alias`**: Renames a field for better understanding by the LLM. * **`@description`**: Provides additional context to a field. * **`@skip`**: Excludes a field from prompts or parsing. * **`@assert`**: Applies strict validation to a field. * **`@check`**: Adds non-exception-raising validation to a field. BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string @alias("name") @description("The name of the object") | | 3 | age int? @check(positive, {{ this > 0 }}) | | 4 | } | Block-Level Attributes ---------------------- Block-level attributes are applied to an entire class or enum, affecting all fields or values within that block. They are used to modify the behavior or metadata of the entire block. ### Examples of Block-Level Attributes * **`@@dynamic`**: Allows dynamic modification of fields or values at runtime. BAML | | | | --- | --- | | 1 | class MyClass { | | 2 | property1 string | | 3 | property2 int? | | 4 | | | 5 | @@dynamic // allows adding fields dynamically at runtime | | 6 | } | Key Differences --------------- * **Scope**: Field-level attributes affect individual fields, while block-level attributes affect the entire class or enum. * **Usage**: Field-level attributes are used for specific field modifications, whereas block-level attributes are used for broader modifications affecting the whole block. Understanding the distinction between these types of attributes is crucial for effectively using BAML to define and manipulate data structures. For more detailed information on each attribute, refer to the specific attribute pages in this section. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Unify AI | Boundary Documentation [Unify AI](https://www.unify.ai/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. See [https://docs.unify.ai/universal\_api/making\_queries#openai-python-package](https://docs.unify.ai/universal_api/making_queries#openai-python-package) for more information. BAML | | | | --- | --- | | 1 | client UnifyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "https://api.unify.ai/v0" | | 5 | api\_key env.MY\_UNIFY\_API\_KEY | | 6 | model "llama-3.1-405b-chat@together-ai" | | 7 | } | | 8 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # vercel-ai-gateway | Boundary Documentation [Vercel AI Gateway](https://vercel.com/docs/ai-gateway/openai-compat) supports the OpenAI-compatible API, so you can use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. BAML | | | | --- | --- | | 1 | client VercelClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "https://ai-gateway.vercel.sh/v1" | | 5 | api\_key env.VERCEL\_AI\_GATEWAY\_TOKEN | | 6 | // Example models routed via the gateway | | 7 | // model "anthropic/claude-3-5-sonnet-latest" | | 8 | // model "openai/gpt-5-mini" | | 9 | } | | 10 | } | See the Vercel docs for details on configuring providers and models behind your gateway: [Vercel AI Gateway (OpenAI compatible)](https://vercel.com/docs/ai-gateway/openai-compat) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Together AI | Boundary Documentation [Together AI](https://www.together.ai/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. See [https://docs.together.ai/docs/openai-api-compatibility](https://docs.together.ai/docs/openai-api-compatibility) for more information. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "https://api.together.ai/v1" | | 5 | api\_key env.TOGETHER\_API\_KEY | | 6 | model "meta-llama/Llama-3-70b-chat-hf" | | 7 | } | | 8 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Hook Data Type Reference | Boundary Documentation The `HookData` type represents the non-null data from a BAML React hook. This type is useful when you know the data exists and want to avoid undefined checks. Example UsageExample TypesType Definition | | | | --- | --- | | 1 | function Component() { | | 2 | const hook = useTestAws({ | | 3 | stream: true, // optional, defaults to true | | 4 | }) | | 5 | | | 6 | const data = hook.data; | | 7 | | | 8 | return ( | | 9 |
| | 10 | {data} {/\* No need for null checks \*/} | | 11 |
| | 12 | ) | | 13 | } | Type Parameters --------------- FunctionName generic The name of the BAML function being called. Used to infer input and output types. Options { stream?: boolean } Configuration object that determines streaming behavior. Defaults to `{ stream?: true }`. Type Details ------------ type NonNullable\['data'\]> A utility type that removes undefined from the data property of HookOutput. This means the type will be either FinalDataType or StreamDataType depending on the streaming configuration. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # vLLM | Boundary Documentation [vLLM](https://docs.vllm.ai/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. See [https://docs.vllm.ai/en/latest/serving/openai\_compatible\_server.html](https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html) for more information. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "http://localhost:8000/v1" | | 5 | api\_key "token-abc123" | | 6 | model "NousResearch/Meta-Llama-3-8B-Instruct" | | 7 | default\_role "user" // Required for using VLLM | | 8 | } | | 9 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Loops | Boundary Documentation Here’s how you can iterate over a list of items, accessing each item’s attributes: | | | | --- | --- | | 1 | function MyFunc(messages: Message\[\]) -> string { | | 2 | prompt #" | | 3 | {% for message in messages %} | | 4 | {{ message.user\_name }}: {{ message.content }} | | 5 | {% endfor %} | | 6 | "# | | 7 | } | loop ---- Jinja provides a `loop` object that can be used to access information about the loop. Here are some of the attributes of the `loop` object: | Variable | Description | | --- | --- | | loop.index | The current iteration of the loop. (1 indexed) | | loop.index0 | The current iteration of the loop. (0 indexed) | | loop.revindex | The number of iterations from the end of the loop (1 indexed) | | loop.revindex0 | The number of iterations from the end of the loop (0 indexed) | | loop.first | True if first iteration. | | loop.last | True if last iteration. | | loop.length | The number of items in the sequence. | | loop.cycle | A helper function to cycle between a list of sequences. See the explanation below. | | loop.depth | Indicates how deep in a recursive loop the rendering currently is. Starts at level 1 | | loop.depth0 | Indicates how deep in a recursive loop the rendering currently is. Starts at level 0 | | loop.previtem | The item from the previous iteration of the loop. Undefined during the first iteration. | | loop.nextitem | The item from the following iteration of the loop. Undefined during the last iteration. | | loop.changed(\*val) | True if previously called with a different value (or not called at all). | | | | | --- | --- | | 1 | prompt #" | | 2 | {% for item in items %} | | 3 | {{ loop.index }}: {{ item }} | | 4 | {% endfor %} | | 5 | "# | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # baml.generateCodeOnSave | Boundary Documentation | Type | Default Value | | --- | --- | | `"always" \| "never"` | ”always” | * `always`: Generate code for `baml_client` on every save * `never`: Do not generate `baml_client` on any save If you have a generator of type `rest/*`, `"always"` will not do any code generation. You will have to manually run: path/to/baml-cli generate Usage ----- settings.json | | | | --- | --- | | 1 | { | | 2 | "baml.generateCodeOnSave": "never", | | 3 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-18T08%3A08%3A42.149Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-18T08%3A08%3A42.149Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # baml.syncExtensionToGeneratorVersion | Boundary Documentation | Type | Default Value | | --- | --- | | `"auto" \| "never" \| "always"` | ”auto” | * `auto`: Sync the extension version to match the generator version when a mismatch is detected. This will make the extension download the correct version of the baml-cli to generate the client code — preventing issues with mismatched versions. * `never`: Never sync the extension version to match the generator version * `always`: Always attempt to sync the extension version to match the generator version. Note that on Windows platforms, the extension-sync feature is disabled when the `syncExtensionToGeneratorVersion` setting is set to `auto`. Usage ----- | | | | --- | --- | | 1 | { | | 2 | "baml.syncExtensionToGeneratorVersion": "auto", | | 3 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # baml.enablePlaygroundProxy | Boundary Documentation | Type | Value | | --- | --- | | `boolean \| null` | true | When running VSCode from a remote machine, you likely need to set this to `false`. Many LLM providers don’t accept requests from the browser. This setting enables a proxy that runs in the background and forwards requests to the LLM provider. Usage ----- settings.json | | | | --- | --- | | 1 | { | | 2 | "baml.enablePlaygroundProxy": false | | 3 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # TypeBuilder | Boundary Documentation `TypeBuilder` is used to create or modify output schemas at runtime. It’s particularly useful when you have dynamic output structures that can’t be determined at compile time - like categories from a database or user-provided schemas. Here’s a simple example of using TypeBuilder to add new enum values before calling a BAML function: **BAML Code** | | | | --- | --- | | 1 | enum Category { | | 2 | RED | | 3 | BLUE | | 4 | @@dynamic // Makes this enum modifiable at runtime | | 5 | } | | 6 | | | 7 | function Categorize(text: string) -> Category { | | 8 | prompt #" | | 9 | Categorize this text: | | 10 | {{ text }} | | 11 | | | 12 | {{ ctx.output\_format }} | | 13 | "# | | 14 | } | **Runtime Usage** ###### Python ###### TypeScript ###### Go ###### Ruby | | | | --- | --- | | 1 | from baml\_client.type\_builder import TypeBuilder | | 2 | from baml\_client import b | | 3 | | | 4 | \# Create a TypeBuilder instance | | 5 | tb = TypeBuilder() | | 6 | | | 7 | \# Add new values to the Category enum | | 8 | tb.Category.add\_value('GREEN') | | 9 | tb.Category.add\_value('YELLOW') | | 10 | | | 11 | \# Pass the typebuilder when calling the function | | 12 | result = b.Categorize("The sun is bright", {"tb": tb}) | | 13 | \# result can now be RED, BLUE, GREEN, or YELLOW | Dynamic Types ------------- There are two ways to use TypeBuilder: 1. Modifying existing BAML types marked with `@@dynamic` 2. Creating entirely new types at runtime ### Modifying Existing Types To modify an existing BAML type, mark it with `@@dynamic`: Classes example | | | | --- | --- | | 1 | class User { | | 2 | name string | | 3 | age int | | 4 | @@dynamic // Allow adding more properties | | 5 | } | **Runtime Usage** ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | tb.User.add\_property('email', tb.string()) | | 3 | tb.User.add\_property('address', tb.string()) | Enums example | | | | --- | --- | | 1 | enum Category { | | 2 | VALUE1 | | 3 | VALUE2 | | 4 | @@dynamic // Allow adding more values | | 5 | } | **Runtime Usage** ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | tb.Category.add\_value('VALUE3') | | 3 | tb.Category.add\_value('VALUE4') | ### Creating New Types You can also create entirely new types at runtime: ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | | | 3 | \# Create a new enum | | 4 | hobbies = tb.add\_enum("Hobbies") | | 5 | hobbies.add\_value("Soccer") | | 6 | hobbies.add\_value("Reading") | | 7 | | | 8 | \# Create a new class | | 9 | address = tb.add\_class("Address") | | 10 | address.add\_property("street", tb.string()) | | 11 | address.add\_property("city", tb.string()) | | 12 | | | 13 | \# Attach new types to existing BAML type | | 14 | tb.User.add\_property("hobbies", hobbies.type().list()) | | 15 | tb.User.add\_property("address", address.type()) | Type Builders ------------- TypeBuilder provides methods for building different kinds of types: | Method | Returns | Description | Example | | --- | --- | --- | --- | | `string()` | `FieldType` | Creates a string type | `tb.string()` | | `int()` | `FieldType` | Creates an integer type | `tb.int()` | | `float()` | `FieldType` | Creates a float type | `tb.float()` | | `bool()` | `FieldType` | Creates a boolean type | `tb.bool()` | | `literal_string(value: string)` | `FieldType` | Creates a literal string type | `tb.literal_string("hello")` | | `literal_int(value: int)` | `FieldType` | Creates a literal integer type | `tb.literal_int(123)` | | `literal_bool(value: boolean)` | `FieldType` | Creates a literal boolean type | `tb.literal_bool(true)` | | `list(type: FieldType)` | `FieldType` | Makes a type into a list | `tb.list(tb.string())` | | `union(types: FieldType[])` | `FieldType` | Creates a union of types | `tb.union([tb.string(), tb.int()])` | | `map(key: FieldType, value: FieldType)` | `FieldType` | Creates a map type | `tb.map(tb.string(), tb.int())` | | `add_class(name: string)` | `ClassBuilder` | Creates a new class | `tb.add_class("User")` | | `add_enum(name: string)` | `EnumBuilder` | Creates a new enum | `tb.add_enum("Category")` | | `MyClass` | `FieldType` | Reference an existing BAML class | `tb.MyClass.type()` | In addition to the methods above, all types marked with `@@dynamic` will also appear in the TypeBuilder. | | | | --- | --- | | 1 | class User { | | 2 | name string | | 3 | age int | | 4 | @@dynamic // Allow adding more properties | | 5 | } | | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | tb.User.add\_property("email", tb.string()) | ### FieldType `FieldType` is a type that represents a field in a type. It can be used to add descriptions, constraints, and other metadata to a field. | Method | Returns | Description | Example | | --- | --- | --- | --- | | `list()` | `FieldType` | Makes a type into a list | `tb.string().list()` | | `optional()` | `FieldType` | Makes a type optional | `tb.string().optional()` | ### ClassBuilder `ClassBuilder` is a type that represents a class in a type. It can be used to add properties to a class. | Method | Returns | Description | Example | | --- | --- | --- | --- | | `add_property(name: string, type: FieldType)` | `ClassPropertyBuilder` | Adds a property to the class | `my_cls.add_property("email", tb.string())` | | `description(description: string)` | `ClassBuilder` | Adds a description to the class | `my_cls.description("A user class")` | | `type()` | `FieldType` | Returns the type of the class | `my_cls.type()` | ### ClassPropertyBuilder `ClassPropertyBuilder` is a type that represents a property in a class. It can be used to add descriptions, constraints, and other metadata to a property. | Method | Returns | Description | Example | | --- | --- | --- | --- | | `description(description: string)` | `ClassPropertyBuilder` | Adds a description to the property | `my_prop.description("An email address")` | | `alias(alias: string)` | `ClassPropertyBuilder` | Adds the alias attribute to the property | `my_prop.alias("email_address")` | ### EnumBuilder `EnumBuilder` is a type that represents an enum in a type. It can be used to add values to an enum. | Method | Returns | Description | Example | | --- | --- | --- | --- | | `add_value(value: string)` | `EnumValueBuilder` | Adds a value to the enum | `my_enum.add_value("VALUE1")` | | `description(description: string)` | `EnumBuilder` | Adds a description to the enum value | `my_enum.description("A value in the enum")` | | `type()` | `FieldType` | Returns the type of the enum | `my_enum.type()` | ### EnumValueBuilder `EnumValueBuilder` is a type that represents a value in an enum. It can be used to add descriptions, constraints, and other metadata to a value. | Method | Returns | Description | Example | | --- | --- | --- | --- | | `description(description: string)` | `EnumValueBuilder` | Adds a description to the enum value | `my_value.description("A value in the enum")` | | `alias(alias: string)` | `EnumValueBuilder` | Adds the alias attribute to the enum value | `my_value.alias("VALUE1")` | | `skip()` | `EnumValueBuilder` | Adds the skip attribute to the enum value | `my_value.skip()` | Adding Descriptions ------------------- You can add descriptions to properties and enum values to help guide the LLM: ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | | | 3 | \# Add description to a property | | 4 | tb.User.add\_property("email", tb.string()) \\ | | 5 | .description("User's primary email address") | | 6 | | | 7 | \# Add description to an enum value | | 8 | tb.Category.add\_value("URGENT") \\ | | 9 | .description("Needs immediate attention") | Creating/modyfing dynamic types with the `add_baml` method ---------------------------------------------------------- The `TypeBuilder` has a higher level API for creating dynamic types at runtime. Here’s an example: ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | tb.add\_baml(""" | | 3 | // Creates a new class Address that does not exist in the BAML source. | | 4 | class Address { | | 5 | street string | | 6 | city string | | 7 | state string | | 8 | } | | 9 | | | 10 | // Modifies the existing @@dynamic User class to add the new address property. | | 11 | dynamic class User { | | 12 | address Address | | 13 | } | | 14 | | | 15 | // Modifies the existing @@dynamic Category enum to add a new variant. | | 16 | dynmic enum Category { | | 17 | PURPLE | | 18 | } | | 19 | """) | Common Patterns --------------- Here are some common patterns when using TypeBuilder: 1. **Dynamic Categories**: When categories come from a database or external source PythonTypeScriptRuby | | | | --- | --- | | 1 | categories = fetch\_categories\_from\_db() | | 2 | tb = TypeBuilder() | | 3 | for category in categories: | | 4 | tb.Category.add\_value(category) | 2. **Form Fields**: When extracting dynamic form fields PythonTypeScriptRuby | | | | --- | --- | | 1 | fields = get\_form\_fields() | | 2 | tb = TypeBuilder() | | 3 | form = tb.add\_class("Form") | | 4 | for field in fields: | | 5 | form.add\_property(field.name, tb.string()) | 3. **Optional Properties**: When some fields might not be present PythonTypeScriptRuby | | | | --- | --- | | 1 | tb = TypeBuilder() | | 2 | tb.User.add\_property("middle\_name", tb.string().optional()) | All types added through TypeBuilder must be connected to the return type of your BAML function. Standalone types that aren’t referenced won’t affect the output schema. Testing Dynamic Types --------------------- See the [advanced dynamic types tests guide](https://docs.boundaryml.com/guide/baml-advanced/dynamic-runtime-types#testing-dynamic-types-in-baml) for examples of testing functions that use dynamic types. See also the [reference](https://docs.boundaryml.com/ref/baml/test) for syntax. Future Features --------------- We’re working on additional features for TypeBuilder: * JSON Schema support (awaiting use cases) * OpenAPI schema integration * Pydantic model support If you’re interested in these features, please join the discussion in our GitHub issues. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # BamlClientFinishReasonError | Boundary Documentation The `BamlClientFinishReasonError` class represents an error that occurs when an LLM terminates with a disallowed finish reason. You can allow or disallow finish reasons like this: | | | | --- | --- | | 1 | client OpenAIWithFinishReasonError { | | 2 | provider openai | | 3 | options { | | 4 | api\_key env.OPENAI\_API\_KEY | | 5 | model "gpt-4" | | 6 | // make it very small so model will stop early | | 7 | max\_tokens 10 | | 8 | // throws if the model returns any other finish reason | | 9 | finish\_reason\_allow\_list \["stop"\] | | 10 | // or allow all finish reasons except length | | 11 | // finish\_reason\_deny\_list \["length"\] | | 12 | } | | 13 | } | Type Definition --------------- Type Definition | | | | --- | --- | | 1 | class BamlClientFinishReasonError extends Error { | | 2 | type: 'BamlClientFinishReasonError' | | 3 | message: string | | 4 | prompt: string | | 5 | raw\_output: string | | 6 | detailed\_message: string | | 7 | } | Properties ---------- type 'BamlClientFinishReasonError' Literal type identifier for the error class. message string Error message describing the specific finish reason that caused the termination. prompt string The original prompt sent to the LLM. raw\_output string The partial output received from the LLM before termination. detailed\_message string Comprehensive error information that includes the complete history of all failed attempts when using fallback clients or retry policies. When multiple attempts are made (via fallback or retry), this field contains formatted details about each failed attempt, making it invaluable for debugging complex client configurations. Type Guards ----------- The error can be identified using TypeScript’s `instanceof` operator: Type Check | | | | --- | --- | | 1 | if (error instanceof BamlClientFinishReasonError) { | | 2 | // Handle finish reason error | | 3 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # What is Jinja / Cookbook | Boundary Documentation BAML Prompt strings are essentially [Minijinja](https://docs.rs/minijinja/latest/minijinja/filters/index.html#functions) templates, which offer the ability to express logic and data manipulation within strings. Jinja is a very popular and mature templating language amongst Python developers, so Github Copilot or another LLM can already help you write most of the logic you want. Jinja Cookbook -------------- When in doubt — use the BAML VSCode Playground preview. It will show you the fully rendered prompt, even when it has complex logic. ### Basic Syntax * `{% ... %}`: Use for executing statements such as for-loops or conditionals. * `{{ ... }}`: Use for outputting expressions or variables. * `{# ... #}`: Use for comments within the template, which will not be rendered. ### Loops / Iterating Over Lists Here’s how you can iterate over a list of items, accessing each item’s attributes: Jinja | | | | --- | --- | | 1 | function MyFunc(messages: Message\[\]) -> string { | | 2 | prompt #" | | 3 | {% for message in messages %} | | 4 | {{ message.user\_name }}: {{ message.content }} | | 5 | {% endfor %} | | 6 | "# | | 7 | } | ### Conditional Statements Use conditional statements to control the flow and output of your templates based on conditions: Jinja | | | | --- | --- | | 1 | function MyFunc(user: User) -> string { | | 2 | prompt #" | | 3 | {% if user.is\_active %} | | 4 | Welcome back, {{ user.name }}! | | 5 | {% else %} | | 6 | Please activate your account. | | 7 | {% endif %} | | 8 | "# | | 9 | } | ### Setting Variables You can define and use variables within your templates to simplify expressions or manage data: | | | | --- | --- | | 1 | function MyFunc(items: Item\[\]) -> string { | | 2 | prompt #" | | 3 | {% set total\_price = 0 %} | | 4 | {% for item in items %} | | 5 | {% set total\_price = total\_price + item.price %} | | 6 | {% endfor %} | | 7 | Total price: {{ total\_price }} | | 8 | "# | | 9 | } | ### Including other Templates To promote reusability, you can include other templates within a template. See [template strings](https://docs.boundaryml.com/ref/baml/template-string) : | | | | --- | --- | | 1 | template\_string PrintUserInfo(arg1: string, arg2: User) #" | | 2 | {{ arg1 }} | | 3 | The user's name is: {{ arg2.name }} | | 4 | "# | | 5 | | | 6 | function MyFunc(arg1: string, user: User) -> string { | | 7 | prompt #" | | 8 | Here is the user info: | | 9 | {{ PrintUserInfo(arg1, user) }} | | 10 | "# | | 11 | } | ### Built-in filters See [jinja docs](https://jinja.palletsprojects.com/en/3.1.x/templates/#list-of-builtin-filters) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Hook Input Type Reference | Boundary Documentation The `HookInput` type defines the configuration options for BAML React hooks. Example UsageExample TypesType Definition | | | | --- | --- | | 1 | function Component() { | | 2 | const hook = useTestAws({ | | 3 | stream: true, // optional, defaults to true | | 4 | onStreamData: (text) => console.log("Streaming:", text), | | 5 | onFinalData: (text) => console.log("Complete:", text), | | 6 | onData: (text) => console.log("Any update:", text), | | 7 | onError: (error) => console.error("Error:", error) | | 8 | }) | | 9 | | | 10 | return
{hook.data}
| | 11 | } | Type Parameters --------------- FunctionName generic The name of the BAML function being called. Used to infer the correct types for responses. Options { stream?: boolean } Configuration object that determines streaming behavior. Defaults to `{ stream?: true }`. Properties ---------- stream boolean | undefined Flag to enable or disable streaming mode. When true, enables streaming responses. onStreamData (response?: StreamDataType) => void Callback function for streaming responses. Only available when `Options['stream']` is true. onFinalData (response?: FinalDataType) => void Callback function for the final response. onData (response?: StreamDataType | FinalDataType) => void Unified callback function that receives both streaming and final responses. For non-streaming hooks, only receives final responses. onError (error: BamlErrors) => void Callback function for error handling. See [Error Types](https://docs.boundaryml.com/ref/baml_client/errors/overview) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-18T08%3A08%3A42.149Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-18T08%3A08%3A42.149Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # google-ai | Boundary Documentation The `google-ai` provider supports the `https://generativelanguage.googleapis.com/v1beta/models/{model_id}/generateContent` and `https://generativelanguage.googleapis.com/v1beta/models/{model_id}/streamGenerateContent` endpoints. The use of `v1beta` rather than `v1` aligns with the endpoint conventions established in [Google’s SDKs](https://github.com/google-gemini/generative-ai-python/blob/8a29017e9120f0552ee3ad6092e8545d1aa6f803/google/generativeai/client.py#L60) and offers access to both the existing `v1` models and additional models exclusive to `v1beta`. BAML will automatically pick `streamGenerateContent` if you call the streaming interface. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider google-ai | | 3 | options { | | 4 | model "gemini-2.5-flash" | | 5 | } | | 6 | } | BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. You can use this to modify the `headers` and `base_url` for example. api\_key string Will be passed as the `x-goog-api-key` header. **Default: `env.GOOGLE_API_KEY`** `x-goog-api-key: $api_key` base\_url string The base URL for the API. **Default: `https://generativelanguage.googleapis.com/v1beta`** model string The model to use. **Default: `gemini-2.5-flash`** We don’t have any checks for this field, you can pass any string you wish. | Model | Use Case | Context | Key Features | | --- | --- | --- | --- | | **gemini-2.5-pro** | Complex tasks, coding, STEM | 1M | Adaptive thinking, multimodal | | **gemini-2.5-flash** | Production apps, balanced performance | 1M | Best price/performance | | **gemini-2.5-flash-lite** | High-volume, cost-sensitive | 1M | Lowest cost, fastest | See the [Google Model Docs](https://ai.google.dev/gemini-api/docs/models/gemini) for the latest models. Some parameters, like temperature, for Gemini Models are specified in the `generationConfig` object. [See Docs](https://ai.google.dev/api/generate-content) headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider google-ai | | 3 | options { | | 4 | model "gemini-2.5-flash" | | 5 | headers { | | 6 | "X-My-Header" "my-value" | | 7 | } | | 8 | generationConfig { | | 9 | temperature 0.5 | | 10 | } | | 11 | } | | 12 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Google AI uses `send_base64_unless_google_url` by default for images, which preserves Google Cloud Storage URLs (gs://) while converting other URLs to base64. Provider request parameters --------------------------- These are other `options` that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. Consult the specific provider’s documentation for more information. contents DO NOT USE BAML will auto construct this field for you from the prompt For all other options, see the [official Google Gemini API documentation](https://ai.google.dev/api/rest/v1beta/models/generateContent) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # azure-openai | Boundary Documentation If you are using the new Microsoft Foundry (new) portal, please use: [`microsoft-foundry`](https://docs.boundaryml.com/ref/llm-client-providers/microsoft-foundry) instead. For `azure-openai`, we provide a client that can be used to interact with the OpenAI API hosted on Azure using the `/chat/completions` endpoint. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider azure-openai | | 3 | options { | | 4 | resource\_name "my-resource-name" | | 5 | deployment\_id "my-deployment-id" | | 6 | // Alternatively, you can use the base\_url field | | 7 | // base\_url "https://my-resource-name.openai.azure.com/openai/deployments/my-deployment-id" | | 8 | api\_version "2024-02-01" | | 9 | api\_key env.AZURE\_OPENAI\_API\_KEY | | 10 | } | | 11 | } | `api_version` is required. Azure will return not found if the version is not specified. The options are passed through directly to the API, barring a few. Here’s a shorthand of the options: BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. You can use this to modify the azure api key, base url, and api version for example. api\_key string Will be injected via the header `API-KEY`. **Default: `env.AZURE_OPENAI_API_KEY`** `API-KEY: $api_key` base\_url string The base URL for the API. **Default: `https://${resource_name}.openai.azure.com/openai/deployments/${deployment_id}`** May be used instead of `resource_name` and `deployment_id`. deployment\_id stringRequired See the `base_url` field. resource\_name stringRequired See the `base_url` field. api\_version stringRequired Will be passed via a query parameter `api-version`. headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider azure-openai | | 3 | options { | | 4 | resource\_name "my-resource-name" | | 5 | deployment\_id "my-deployment-id" | | 6 | api\_version "2024-02-01" | | 7 | api\_key env.AZURE\_OPENAI\_API\_KEY | | 8 | headers { | | 9 | "X-My-Header" "my-value" | | 10 | } | | 11 | } | | 12 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | client\_response\_type openai | anthropic | google | vertexDefaults to openai Please let [us know on Discord](https://www.boundaryml.com/discord) if you have this use case! This is in alpha and we’d like to make sure we continue to cover your use cases. The type of response to return from the client. Sometimes you may expect a different response format than the provider default. For example, using Azure you may be proxying to an endpoint that returns a different format than the OpenAI default. **Default: `openai`** ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Provider request parameters --------------------------- These are other `options` that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. Consult the specific provider’s documentation for more information. For reasoning models (like `o1` or `o1-mini`), you must use `max_completion_tokens` instead of `max_tokens`. Please set `max_tokens` to `null` in order to get this to work. See the [OpenAI API documentation](https://platform.openai.com/docs/api-reference/chat/create#chat-create-max_completion_tokens) and [OpenAI Reasoning Docs](https://platform.openai.com/docs/guides/reasoning#controlling-costs) for more details about token handling. Example: BAML | | | | --- | --- | | 1 | client AzureO1 { | | 2 | provider azure-openai | | 3 | options { | | 4 | deployment\_id "o1-mini" | | 5 | max\_tokens null | | 6 | } | | 7 | } | messages DO NOT USE BAML will auto construct this field for you from the prompt stream DO NOT USE BAML will auto construct this field for you based on how you call the client in your code For all other options, see the [official Azure API documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # ollama | Boundary Documentation [Ollama](https://ollama.com/) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. Note that to call Ollama, you must use its OpenAI-compatible `/v1` endpoint. See [Ollama’s OpenAI compatibility documentation](https://ollama.com/blog/openai-compatibility) . You can try out BAML with Ollama at promptfiddle.com, by running `OLLAMA_ORIGINS='*' ollama serve`. Learn more in [here](https://www.boundaryml.com/blog/ollama-structured-output) BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "http://localhost:11434/v1" | | 5 | model llama3 | | 6 | } | | 7 | } | BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. You can use this to modify the `headers` and `base_url` for example. base\_url string The base URL for the API. **Default: `http://localhost:11434/v1`** Note the `/v1` at the end of the URL. See [Ollama’s OpenAI compatability](https://ollama.com/blog/openai-compatibility) headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider ollama | | 3 | options { | | 4 | model "llama3" | | 5 | headers { | | 6 | "X-My-Header" "my-value" | | 7 | } | | 8 | } | | 9 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | Provider request parameters --------------------------- These are other parameters that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. Consult the specific provider’s documentation for more information. messages DO NOT USE BAML will auto construct this field for you from the prompt stream DO NOT USE BAML will auto construct this field for you based on how you call the client in your code model string The model to use. | Model | Description | | --- | --- | | `llama4` | Meta Llama 4: Latest generation with enhanced reasoning capabilities | | `llama3.3` | Meta Llama 3.3: Enhanced version with improved performance | | `llama3` | Meta Llama 3: The most capable openly available LLM to date | | `qwen2` | Qwen2 is a new series of large language models from Alibaba group | | `phi3` | Phi-3 is a family of lightweight 3B (Mini) and 14B (Medium) state-of-the-art open models by Microsoft | | `aya` | Aya 23, released by Cohere, is a new family of state-of-the-art, multilingual models that support 23 languages. | | `mistral` | The 7B model released by Mistral AI, updated to version 0.3. | | `gemma` | Gemma is a family of lightweight, state-of-the-art open models built by Google DeepMind. Updated to version 1.1 | | `mixtral` | A set of Mixture of Experts (MoE) model with open weights by Mistral AI in 8x7b and 8x22b parameter sizes. | For the most up-to-date list of models supported by Ollama, see their [Model Library](https://ollama.com/library) . To use a specific version you would do: `"mixtral:8x22b"` [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # anthropic | Boundary Documentation The `anthropic` provider supports all APIs that use the same interface for the `/v1/messages` endpoint. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider anthropic | | 3 | options { | | 4 | model "claude-sonnet-4-20250514" | | 5 | temperature 0 | | 6 | } | | 7 | } | BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. You can use this to modify the `headers` and `base_url` for example. api\_key string Will be passed as a bearer token. **Default: `env.ANTHROPIC_API_KEY`** `Authorization: Bearer $api_key` base\_url string The base URL for the API. **Default: `https://api.anthropic.com`** headers object Additional headers to send with the request. Unless specified with a different value, we inject in the following headers: "anthropic-version" "2023-06-01" Example: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider anthropic | | 3 | options { | | 4 | api\_key env.MY\_ANTHROPIC\_KEY | | 5 | model "claude-sonnet-4-20250514" | | 6 | headers { | | 7 | "X-My-Header" "my-value" | | 8 | } | | 9 | } | | 10 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["cache_control"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client ClaudeWithCaching { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | allowed\_role\_metadata \["cache\_control"\] | | 8 | headers { | | 9 | "anthropic-beta" "prompt-caching-2024-07-31" | | 10 | } | | 11 | } | | 12 | } | | 13 | | | 14 | client FooWithout { | | 15 | provider anthropic | | 16 | options { | | 17 | } | | 18 | } | | 19 | | | 20 | template\_string Foo() #" | | 21 | {{ \_.role('user', cache\_control={"type": "ephemeral"}) }} | | 22 | This will be cached for ClaudeWithCaching, but not for FooWithout! | | 23 | {{ \_.role('user') }} | | 24 | This will not be cached for Foo or FooWithout! | | 25 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Anthropic’s default behavior is to convert PDFs to base64 (`send_base64`) while keeping other media types as URLs (`send_url`). This is because Anthropic’s API requires PDFs to be base64-encoded. Provider request parameters --------------------------- These are other parameters that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. Consult the specific provider’s documentation for more information. system DO NOT USE BAML will auto construct this field for you from the prompt, if necessary. Only the first system message will be used, all subsequent ones will be cast to the `assistant` role. messages DO NOT USE BAML will auto construct this field for you from the prompt stream DO NOT USE BAML will auto construct this field for you based on how you call the client in your code model string The model to use. | Model | Use Case | Release | Context | Features | | --- | --- | --- | --- | --- | | **claude-opus-4-1-20250805** | Complex coding, AI agents | Aug 2025 | 200K | Most powerful reasoning | | **claude-sonnet-4-20250514** | Default choice, versatile | May 2025 | 200K-1M | Hybrid reasoning modes | | **claude-3-5-haiku-20241022** | Fast, cost-efficient | Oct 2024 | 200K | Speed optimized | ![](https://mintlify.s3-us-west-1.amazonaws.com/anthropic/images/3-5-sonnet-curve.png) See anthropic docs for the latest list of all models. You can pass any model name you wish, we will not check if it exists. max\_tokens int The maximum number of tokens to generate. **Default: `4069`** For all other options, see the [official anthropic API documentation](https://docs.anthropic.com/en/api/messages) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # ctx.output_format | Boundary Documentation `{{ ctx.output_format }}` is used within a prompt template (or in any template\_string) to print out the function’s output schema into the prompt. It describes to the LLM how to generate a structure BAML can parse (usually JSON). Here’s an example of a function with `{{ ctx.output_format }}`, and how it gets rendered by BAML before sending it to the LLM. **BAML Prompt** | | | | --- | --- | | 1 | class Resume { | | 2 | name string | | 3 | education Education\[\] | | 4 | } | | 5 | function ExtractResume(resume\_text: string) -> Resume { | | 6 | prompt #" | | 7 | Extract this resume: | | 8 | --- | | 9 | {{ resume\_text }} | | 10 | --- | | 11 | | | 12 | {{ ctx.output\_format }} | | 13 | "# | | 14 | } | **Rendered prompt** | | | --- | | Extract this resume | | \--- | | Aaron V. | | Bachelors CS, 2015 | | UT Austin | | \--- | | | | Answer in JSON using this schema: | | { | | name: string | | education: \[ |\ | { |\ | school: string |\ | graduation\_year: string |\ | } |\ | \] | | } | Controlling the output\_format ------------------------------ `ctx.output_format` can also be called as a function with parameters to customize how the schema is printed, like this: {{ ctx.output\_format(prefix="If you use this schema correctly and I'll tip $400:\\n", always\_hoist\_enums=true)}} Here’s the parameters: prefix string The prefix instruction to use before printing out the schema. | | | --- | | Answer in this schema correctly I'll tip $400: | | { | | ... | | } | BAML’s default prefix varies based on the function’s return type. | Fuction return type | Default Prefix | | --- | --- | | Primitive (String) | | | Primitive (Int) | `Answer as an` | | Primitive (Other) | `Answer as a` | | Enum | `Answer with any of the categories:\n` | | Class | `Answer in JSON using this schema:\n` | | List | `Answer with a JSON Array using this schema:\n` | | Union | `Answer in JSON using any of these schemas:\n` | | Optional | `Answer in JSON using this schema:\n` | always\_hoist\_enums boolean Whether to inline the enum definitions in the schema, or print them above. **Default: false** Note that setting this to `false` means BAML will use heuristics internally to determine whether or not to hoist. `false` does not mean “never hoist”. **Inlined** | | | --- | | Answer in this json schema: | | { | | categories: "ONE" \| "TWO" \| "THREE" | | } | **hoisted** | | | --- | | MyCategory | | \--- | | ONE | | TWO | | THREE | | | | Answer in this json schema: | | { | | categories: MyCategory | | } | BAML will always hoist if you add a [description](https://docs.boundaryml.com/docs/snippets/enum#aliases-descriptions) to any of the enum values. or\_splitter string **Default: `or`** If a type is a union like `string | int` or an optional like `string?`, this indicates how it’s rendered. BAML renders it as `property: string or null` as we have observed some LLMs have trouble identifying what `property: string | null` means (and are better with plain english). You can always set it to `|` or something else for a specific model you use. hoist\_classes 'auto' | bool | list\[string\] **Default: `"auto"`** Requires BAML Version 0.89+ Controls which classes are hoisted in the prompt. Recursive classes are **always** hoisted because they need to be referenced by name. Let’s use this as an example to visualize the different options: | | | | --- | --- | | 1 | class Example { | | 2 | a string | | 3 | b string | | 4 | c NestedClass | | 5 | d Node | | 6 | } | | 7 | | | 8 | class NestedClass { | | 9 | m int | | 10 | n int | | 11 | } | | 12 | | | 13 | class Node { | | 14 | data int | | 15 | next Node? | | 16 | } | | 17 | | | 18 | function UseExample() -> Example { | | 19 | client GPT4 | | 20 | prompt #"{{ctx.output\_format}}"# | | 21 | } | **“auto”** Only recursive classes are hoisted: | | | | --- | --- | | 1 | Node { | | 2 | data: int, | | 3 | next: Node or null | | 4 | } | | 5 | | | 6 | Answer in JSON using this schema: | | 7 | { | | 8 | a: string, | | 9 | b: string, | | 10 | c: { | | 11 | m: int, | | 12 | n: int, | | 13 | }, | | 14 | d: Node, | | 15 | } | **false** Same as `"auto"`. **true** Hoist all classes. | | | | --- | --- | | 1 | Node { | | 2 | data: int, | | 3 | next: Node or null | | 4 | } | | 5 | | | 6 | Example { | | 7 | a: string, | | 8 | b: string, | | 9 | c: NestedClass, | | 10 | d: Node, | | 11 | } | | 12 | | | 13 | NestedClass { | | 14 | m: int, | | 15 | n: int, | | 16 | } | | 17 | | | 18 | Answer in JSON using this schema: Example | **list\[string\]** Hoist only recursive classes and the classes specified in the list. For example `ctx.output_format(hoist_classes=["NestedClass"])` will hoist `NestedClass`. | | | | --- | --- | | 1 | Node { | | 2 | data: int, | | 3 | next: Node or null | | 4 | } | | 5 | | | 6 | NestedClass { | | 7 | m: int, | | 8 | n: int, | | 9 | } | | 10 | | | 11 | Answer in JSON using this schema: | | 12 | { | | 13 | a: string, | | 14 | b: string, | | 15 | c: NestedClass, | | 16 | d: Node, | | 17 | } | hoisted\_class\_prefix string Prefix of hoisted classes in the prompt. **Default: ``** This parameter controls the prefix used for hoisted classes as well as the word used in the render message to refer to the output type, which defaults to `"schema"`: Answer in JSON using this schema: See examples below. **Recursive BAML Prompt Example** | | | | --- | --- | | 1 | class Node { | | 2 | data int | | 3 | next Node? | | 4 | } | | 5 | | | 6 | class LinkedList { | | 7 | head Node? | | 8 | len int | | 9 | } | | 10 | | | 11 | function BuildLinkedList(input: int\[\]) -> LinkedList { | | 12 | prompt #" | | 13 | Build a linked list from the input array of integers. | | 14 | | | 15 | INPUT: {{ input }} | | 16 | | | 17 | {{ ctx.output\_format }} | | 18 | "# | | 19 | } | **Default `hoisted_class_prefix` (none)** | | | --- | | Node { | | data: int, | | next: Node or null | | } | | | | Answer in JSON using this schema: | | { | | head: Node or null, | | len: int | | } | **Custom Prefix: `hoisted_class_prefix="interface"`** | | | --- | | interface Node { | | data: int, | | next: Node or null | | } | | | | Answer in JSON using this interface: | | { | | head: Node or null, | | len: int | | } | Why BAML doesn’t use JSON schema format in prompts -------------------------------------------------- BAML uses “type definitions” or “jsonish” format instead of the long-winded json-schema format. The tl;dr is that json schemas are 1. 4x more inefficient than “type definitions”. 2. very unreadable by humans (and hence models) 3. perform worse than type definitions (especially on deeper nested objects or smaller models) Read our [full article on json schema vs type definitions](https://www.boundaryml.com/blog/type-definition-prompting-baml) [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # BAML Error Types | Boundary Documentation BAML provides a set of error classes for handling different error scenarios when working with LLMs. Each error type is designed to handle specific failure cases in the BAML runtime. Error Class Hierarchy --------------------- All BAML errors extend the base JavaScript `Error` class and include a literal `type` field for type identification. Type Hierarchy | | | | --- | --- | | 1 | // Base JavaScript Error class | | 2 | class Error { | | 3 | message: string | | 4 | name: string | | 5 | stack?: string | | 6 | } | | 7 | | | 8 | // BAML-specific error classes | | 9 | class BamlValidationError extends Error { | | 10 | type: 'BamlValidationError' | | 11 | message: string | | 12 | prompt: string | | 13 | raw\_output: string | | 14 | detailed\_message: string | | 15 | } | | 16 | | | 17 | class BamlClientFinishReasonError extends Error { | | 18 | type: 'BamlClientFinishReasonError' | | 19 | message: string | | 20 | prompt: string | | 21 | raw\_output: string | | 22 | detailed\_message: string | | 23 | } | | 24 | | | 25 | class BamlAbortError extends Error { | | 26 | type: 'BamlAbortError' | | 27 | message: string | | 28 | reason?: any | | 29 | detailed\_message: string | | 30 | } | Error Types ----------- ### [BamlValidationError](https://docs.boundaryml.com/ref/baml_client/errors/baml-validation-error) Thrown when BAML fails to parse or validate LLM output. Contains the original prompt and raw output for debugging. ### [BamlClientFinishReasonError](https://docs.boundaryml.com/ref/baml_client/errors/baml-client-finish-reason-error) Thrown when an LLM terminates with a disallowed finish reason. Includes the original prompt and partial output received before termination. ### [BamlAbortError](https://docs.boundaryml.com/ref/baml_client/errors/baml-abort-error) Thrown when a BAML operation is cancelled via an abort controller. Contains an optional reason for the cancellation. Fallback Error Aggregation -------------------------- When using [fallback clients](https://docs.boundaryml.com/ref/llm-client-strategies/fallback) or clients with [retry policies](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy) , BAML attempts multiple client calls before finally failing. In these cases: * The error **type** corresponds to the final (last) failed attempt * The `message` field contains the error message from the final attempt * The `detailed_message` field contains the **complete history** of all failed attempts This allows you to debug the entire fallback chain while still getting a specific error type for the final failure. Type Guards ----------- All BAML errors can be identified using TypeScript’s `instanceof` operator: Type Checking | | | | --- | --- | | 1 | try { | | 2 | // BAML operation | | 3 | } catch (error) { | | 4 | if (error instanceof BamlAbortError) { | | 5 | // Handle cancellation | | 6 | } else if (error instanceof BamlValidationError) { | | 7 | // Handle validation error | | 8 | } else if (error instanceof BamlClientFinishReasonError) { | | 9 | // Handle finish reason error | | 10 | } | | 11 | } | Common Properties ----------------- All BAML error classes include: type string Literal type identifier specific to each error class. message string Human-readable error message describing the failure. detailed\_message string Comprehensive error information that includes the complete history of all failed attempts when using fallback clients or retry policies. For single attempts, this typically contains the same information as `message` but may include additional debugging details. For detailed information about each error type, refer to their individual reference pages. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Collector | Boundary Documentation This feature was added in 0.79.0 The `Collector` allows you to inspect the internal state of BAML function calls, including raw HTTP requests, responses, usage metrics, and timing information, so you can always see the raw data, without any abstraction layers. Quick Start ----------- ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | \# Create a collector with optional name | | 5 | collector = Collector(name="my-collector") | | 6 | | | 7 | \# Use it with a function call | | 8 | result = b.ExtractResume("...", baml\_options={"collector": collector}) | | 9 | | | 10 | \# Access logging information | | 11 | print(collector.last.usage) # Print usage metrics | | 12 | print(collector.last.raw\_llm\_response) # Print final response as string | | 13 | \# since there may be retries, print the last http response received | | 14 | print(collector.last.calls\[-1\].http\_response) | Common Use Cases ---------------- ### Basic Logging ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector # Import the Collector class | | 3 | | | 4 | def run(): | | 5 | # Create a collector instance with an optional name | | 6 | collector = Collector(name="my-collector") | | 7 | # collector will be modified by the function to include all internal state | | 8 | res = b.ExtractResume("...", baml\_options={"collector": collector}) | | 9 | # This will print the return type of the function | | 10 | print(res) | | 11 | | | 12 | # This is guaranteed to be set by the function | | 13 | assert collector.last is not None | | 14 | | | 15 | # This will print the id of the last request | | 16 | print(collector.last.id) | | 17 | | | 18 | # This will print the usage of the last request | | 19 | # (This aggregates usage from all retries if there was usage emitted) | | 20 | print(collector.last.usage) | | 21 | | | 22 | # This will print the raw response of the last request | | 23 | print(collector.last.calls\[-1\].http\_response) | | 24 | | | 25 | # This will print the raw text we used to run the parser. | | 26 | print(collector.last.raw\_llm\_response) | ### Tags You can attach custom metadata to function calls using tags. These can come from a parent `trace` context or be specified per call. ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_client.tracing import trace, set\_tags | | 3 | from baml\_py import Collector | | 4 | | | 5 | @trace | | 6 | async def run\_with\_tags(): | | 7 | # Parent trace tags | | 8 | set\_tags(parent\_id="p123", run="xyz") | | 9 | | | 10 | collector = Collector(name="tags-collector") | | 11 | | | 12 | # Per-call tags via baml\_options | | 13 | await b.TestOpenAIGPT4oMini( | | 14 | "hi", | | 15 | baml\_options={"collector": collector, "tags": {"call\_id": "first"}}, | | 16 | ) | | 17 | | | 18 | # Retrieve merged tags from the last log | | 19 | log = collector.last | | 20 | assert log is not None | | 21 | print(log.tags) # {'parent\_id': 'p123', 'run': 'xyz', 'call\_id': 'first'} | ### Managing Collector State ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | def run(): | | 5 | collector = Collector(name="reusable-collector") | | 6 | res = b.ExtractResume("...", baml\_options={"collector": collector}) | | 7 | | | 8 | # Reuse the same collector | | 9 | res = b.TestOpenAIGPT4oMini("Second call", baml\_options={"collector": collector}) | ### Using Multiple Collectors You can use multiple collectors to track different aspects of your application: ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | def run(): | | 5 | # Create separate collectors for different parts of your application | | 6 | collector\_a = Collector(name="collector-a") | | 7 | collector\_b = Collector(name="collector-b") | | 8 | | | 9 | # Use both collectors for the same function call | | 10 | res = b.ExtractResume("...", baml\_options={"collector": \[collector\_a, collector\_b\]}) | | 11 | | | 12 | # Both collectors will have the same logs | | 13 | assert collector\_a.last.usage.input\_tokens == collector\_b.last.usage.input\_tokens | | 14 | | | 15 | # Use only collector\_a for another call | | 16 | res2 = b.TestOpenAIGPT4oMini("another call", baml\_options={"collector": collector\_a}) | | 17 | | | 18 | # collector\_a will have 2 logs, collector\_b will still have 1 | | 19 | assert len(collector\_a.logs) == 2 | | 20 | assert len(collector\_b.logs) == 1 | ### Usage Tracking ###### Python ###### TypeScript ###### Ruby | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | def run(): | | 5 | collector\_a = Collector(name="collector-a") | | 6 | res = b.ExtractResume("...", baml\_options={"collector": collector\_a}) | | 7 | | | 8 | collector\_b = Collector(name="collector-b") | | 9 | res = b.ExtractResume("...", baml\_options={"collector": collector\_b}) | | 10 | | | 11 | # The total usage of both logs is now available | | 12 | print(collector\_a.usage) | | 13 | print(collector\_b.usage) | ### Accessing SSE Responses (Streaming) When using streaming, you can access the raw Server-Sent Events (SSE) responses received from the LLM provider. This is useful for debugging, logging, or accessing provider-specific data not exposed in the standard response. ###### Python ###### TypeScript | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | async def run(): | | 5 | collector = Collector(name="stream-collector") | | 6 | | | 7 | # Use streaming | | 8 | stream = b.stream.ExtractResume("...", baml\_options={"collector": collector}) | | 9 | async for chunk in stream: | | 10 | print(chunk) # Process streamed chunks | | 11 | | | 12 | # After streaming completes, access the raw SSE responses | | 13 | log = collector.last | | 14 | if log and log.selected\_call: | | 15 | sse\_responses = log.selected\_call.sse\_responses() | | 16 | if sse\_responses: | | 17 | for sse in sse\_responses: | | 18 | # Raw text of the SSE data field | | 19 | print(f"Raw: {sse.text}") | | 20 | # Parse as JSON if valid (returns None if not valid JSON) | | 21 | parsed = sse.json() | | 22 | if parsed: | | 23 | print(f"JSON: {parsed}") | SSE responses capture the raw streaming data from the provider. For HTTP-based providers (OpenAI, Anthropic, Google, etc.), this is the actual SSE event data. For AWS Bedrock, which uses a binary protocol, the responses contain a JSON wrapper with the Debug representation of the SDK types (see [AWS SDK serialization issue](https://github.com/awslabs/aws-sdk-rust/issues/645) ). ### Cached Token Tracking When using providers that support prompt caching (like Anthropic, OpenAI, Google, or Vertex), you can track cached input tokens via the `cached_input_tokens` field: ###### Python ###### TypeScript | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import Collector | | 3 | | | 4 | async def run(): | | 5 | collector = Collector(name="cache-tracker") | | 6 | | | 7 | # First call - content will be cached by the provider | | 8 | res = await b.TestCaching(large\_content, "Question 1", baml\_options={"collector": collector}) | | 9 | | | 10 | # Second call with same content - should use cached tokens | | 11 | res2 = await b.TestCaching(large\_content, "Question 2", baml\_options={"collector": collector}) | | 12 | | | 13 | # Access cached token counts | | 14 | first\_log = collector.logs\[0\] | | 15 | second\_log = collector.logs\[1\] | | 16 | | | 17 | print(f"First call cached tokens: {first\_log.usage.cached\_input\_tokens}") | | 18 | print(f"Second call cached tokens: {second\_log.usage.cached\_input\_tokens}") | | 19 | | | 20 | # Collector aggregates cached tokens across all calls | | 21 | print(f"Total cached tokens: {collector.usage.cached\_input\_tokens}") | | 22 | | | 23 | # You can also access cached tokens per LLM call (including retries) | | 24 | print(f"Per-call cached tokens: {first\_log.calls\[0\].usage.cached\_input\_tokens}") | Cached token tracking is supported for Anthropic, OpenAI, Google AI, and Vertex AI providers. AWS Bedrock does not currently support cached token reporting and will return `null` for this field. API Reference ------------- ### Collector Class The Collector class provides properties to introspect the internal state of BAML function calls. | Property | Type | Description | | --- | --- | --- | | `logs` | `List[FunctionLog]` | A list of all function calls (ordered from oldest to newest) | | `last` | `FunctionLog \| null` | The most recent function log. | | `usage` | `Usage` | The cumulative total usage of all requests this collector has tracked. This includes all retries and fallbacks, if those did use any tokens. | The Collector class provides the following methods: | Method | Type | Description | | --- | --- | --- | | (removed) | | IDs are not exposed in the client. Use tags to correlate calls. | | `clear()` | `void` | Clears all logs. | ### FunctionLog Class The `FunctionLog` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `id` | `string` | The id of the request. | | `function_name` | `string` | The name of the function. | | `log_type` | `"call" \| "stream"` | The manner in which the function was called. | | `timing` | `Timing` | The timing of the request. | | `usage` | `Usage` | The usage of the request (aggregated from all calls). | | `calls` | `(LLMCall \| LLMStreamCall)[]` | Every call made to the LLM (including fallbacks and retries). Sorted from oldest to newest. | | `selected_call` | `(LLMCall \| LLMStreamCall)?` | The call used by BAML for parsing the response (there may be many due to fallbacks and retries). | | `raw_llm_response` | `string \| null` | The raw text from the best matching LLM. | | `tags` | `Map[str, any]` | Any user provided metadata. | ### Timing Class The `Timing` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `start_time_utc_ms` | `int` | The start time of the request in milliseconds since epoch. | | `duration_ms` | `int \| null` | The duration of the request in milliseconds. | #### StreamTiming Class (extends Timing) No unique properties. ### Usage Class The `Usage` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `input_tokens` | `int \| null` | The cumulative number of tokens used in the inputs. | | `output_tokens` | `int \| null` | The cumulative number of tokens used in the outputs. | | `cached_input_tokens` | `int \| null` | The number of cached input tokens (e.g., Anthropic’s `cache_read_input_tokens`). | Note: Usage may not include all provider-specific token types like “thinking\_tokens” or “cache\_creation\_input\_tokens”. For those, you may need to look at the raw HTTP response and build your own adapters. ### LLMCall Class The `LLMCall` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `client_name` | `str` | The name of the client used. | | `provider` | `str` | The provider of the client used. | | `timing` | `Timing` | The timing of the request. | | `http_request` | `HttpRequest` | The raw HTTP request sent to the client. | | `http_response` | `HttpResponse \| null` | The raw HTTP response from the client (null for streaming). | | `usage` | `Usage \| null` | The usage of the request (if available). | | `selected` | `bool` | Whether this call was selected and used for parsing. | ### LLMStreamCall Class (extends LLMCall) The `LLMStreamCall` includes the same properties as `LLMCall` plus the following: | Property | Type | Description | | --- | --- | --- | | `timing` | `StreamTiming` | The timing of the request. | | `sse_responses()` | `SSEResponse[] \| null` | The raw SSE responses received during streaming. Returns null if not available. | ### HttpRequest Class The `HttpRequest` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `url` | `str` | The URL of the request. | | `method` | `str` | The HTTP method of the request. | | `headers` | `object` | The request headers. | | `body` | `HTTPBody` | The request body. | ### HttpResponse Class The `HttpResponse` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `status` | `int` | The HTTP status code. | | `headers` | `object` | The response headers. | | `body` | `HTTPBody` | The response body. | ### HTTPBody Class The `HTTPBody` class has the following properties: | Property | Type | Description | | --- | --- | --- | | `text()` | `string` | The body as a string. | | `json()` | `object` | The body as a JSON object. | ### SSEResponse Class The `SSEResponse` class represents a single Server-Sent Event received during streaming. | Property/Method | Type | Description | | --- | --- | --- | | `text` | `string` | The raw text content of the SSE `data` field. | | `json()` | `object \| null` | Parses and returns the text as JSON. Returns null if the text is not valid JSON. | The SSE event type (e.g., “message\_delta”, “content\_block\_delta”) and event ID are not currently exposed. Only the data payload is available via `text` and `json()`. Related Topics -------------- * [Using with\_options](https://docs.boundaryml.com/ref/baml_client/with-options) - Learn how to configure logging globally * [TypeBuilder](https://docs.boundaryml.com/ref/baml_client/type-builder) - Build custom types for your BAML functions * [Client Registry](https://docs.boundaryml.com/ref/baml_client/client-registry) - Manage LLM clients and their configurations Best Practices -------------- 1. Use a single collector instance when tracking related function calls in a chain. 2. Clear the collector when reusing it for unrelated operations. 3. Consider using multiple collectors to track different parts of your application. 4. Use function IDs when tracking specific calls in parallel operations. 5. For streaming calls, be aware that `http_response` will be null, but you can still access usage information. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # openai-responses | Boundary Documentation The `openai-responses` provider supports OpenAI’s `/responses` endpoint which uses the newer Responses API instead of the traditional Chat Completions API. Read more about the differences between the Chat Completions API and the Responses API in [OpenAI’s comparison guide](https://platform.openai.com/docs/guides/responses-vs-chat-completions) . If you’re a new user, OpenAI recommends using the `openai-responses` provider instead of the `openai` provider. `o1-mini` is not supported with the `openai-responses` provider. Example: BAML | | | | --- | --- | | 1 | client MyResponsesClient { | | 2 | provider "openai-responses" | | 3 | options { | | 4 | api\_key env.MY\_OPENAI\_KEY | | 5 | model "gpt-5" | | 6 | reasoning { | | 7 | effort "medium" | | 8 | } | | 9 | } | | 10 | } | BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. api\_key stringDefaults to env.OPENAI\_API\_KEY Will be used to build the `Authorization` header, like so: `Authorization: Bearer $api_key` **Default: `env.OPENAI_API_KEY`** base\_url string The base URL for the API. **Default: `https://api.openai.com/v1`** headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyResponsesClient { | | 2 | provider openai-responses | | 3 | options { | | 4 | api\_key env.MY\_OPENAI\_KEY | | 5 | model "gpt-4.1" | | 6 | headers { | | 7 | "X-My-Header" "my-value" | | 8 | } | | 9 | } | | 10 | } | client\_response\_type string Override the response format type. When using `openai-responses` provider, this defaults to `"openai-responses"`. You can also use the standard `openai` provider with `client_response_type: "openai-responses"` to format the response as a `openai-responses` response. Example: BAML | | | | --- | --- | | 1 | client StandardOpenAIWithResponses { | | 2 | provider openai | | 3 | options { | | 4 | api\_key env.MY\_OPENAI\_KEY | | 5 | model "gpt-4.1" | | 6 | client\_response\_type "openai-responses" | | 7 | } | | 8 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Provider request parameters --------------------------- These are parameters specific to the OpenAI Responses API that are passed through to the provider. reasoning.effort string Controls the amount of reasoning effort the model should use. | Value | Description | | --- | --- | | `low` | Minimal reasoning effort | | `medium` | Balanced reasoning effort | | `high` | Maximum reasoning effort | Example: BAML | | | | --- | --- | | 1 | client HighReasoningClient { | | 2 | provider openai-responses | | 3 | options { | | 4 | model "o4-mini" | | 5 | reasoning { | | 6 | effort "high" | | 7 | } | | 8 | } | | 9 | } | model string Most models support the Responses API, some of the most popular models are: | Model | Use Case | Context | Key Features | | --- | --- | --- | --- | | **gpt-5** | Coding, agentic tasks, expert reasoning | 400K total | Built-in reasoning, 45% fewer errors | | **gpt-5-mini** | Well-defined tasks, cost-efficient | 400K total | Faster alternative to GPT-5 | | **o4-mini** | Fast reasoning tasks | Standard | 92.7% AIME, cost-efficient reasoning | `o1-mini` is not supported with the `openai-responses` provider. See OpenAI’s Responses API documentation for the latest available models. tools array Tools that the model can use during reasoning. Supports function calling and web search. Example with web search: BAML | | | | --- | --- | | 1 | client WebSearchClient { | | 2 | provider openai-responses | | 3 | options { | | 4 | model "gpt-4.1" | | 5 | tools \[ |\ | 6 | { |\ | 7 | type "web\_search\_preview" |\ | 8 | } |\ | 9 | \] | | 10 | } | | 11 | } | Additional Use Cases -------------------- ### Image Input Support The `openai-responses` provider supports image inputs for vision-capable models: BAML | | | | --- | --- | | 1 | client OpenAIResponsesVision { | | 2 | provider openai-responses | | 3 | options { | | 4 | model "gpt-4.1" | | 5 | } | | 6 | } | | 7 | | | 8 | function AnalyzeImage(image: image\|string) -> string { | | 9 | client OpenAIResponsesVision | | 10 | prompt #" | | 11 | {{ \_.role("user") }} | | 12 | What is in this image? | | 13 | {{ image }} | | 14 | "# | | 15 | } | ### Advanced Reasoning Using reasoning models with high effort for complex problem solving: BAML | | | | --- | --- | | 1 | client AdvancedReasoningClient { | | 2 | provider openai-responses | | 3 | options { | | 4 | model "o4-mini" | | 5 | reasoning { | | 6 | effort "high" | | 7 | } | | 8 | } | | 9 | } | | 10 | | | 11 | function SolveComplexProblem(problem: string) -> string { | | 12 | client AdvancedReasoningClient | | 13 | prompt #" | | 14 | {{ \_.role("user") }} | | 15 | Solve this step by step: {{ problem }} | | 16 | "# | | 17 | } | Modular API Support ------------------- The `openai-responses` provider works with the [Modular API](https://docs.boundaryml.com/guide/baml-advanced/modular-api) for custom integrations: Python | | | | --- | --- | | 1 | from openai import AsyncOpenAI | | 2 | from openai.types.responses import Response | | 3 | import typing | | 4 | | | 5 | client = AsyncOpenAI() | | 6 | req = await b.request.MyFunction("input") | | 7 | res = typing.cast(Response, await client.responses.create(\*\*req.body.json())) | | 8 | parsed = b.parse.MyFunction(res.output\_text) | For all other options, see the [official OpenAI Responses API documentation](https://platform.openai.com/docs/api-reference/responses) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # baml.cliPath | Boundary Documentation | Type | Value | | --- | --- | | `string \| null` | null | If set, all generated code will use this instead of the packaged generator shipped with the extension. We recommend this setting! This prevents mismatches between the VSCode Extension and the installed BAML package. Usage ----- If you use unix, you can run `where baml-cli` in your project to figure out what the path is. settings.json | | | | --- | --- | | 1 | { | | 2 | "baml.cliPath": "/path/to/baml-cli" | | 3 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Hook Output Type Reference | Boundary Documentation The `HookOutput` type defines the return type for BAML React hooks. Example UsageExample TypesType Definition | | | | --- | --- | | 1 | function Component() { | | 2 | const hook = useTestAws({ | | 3 | stream: true, // optional, defaults to true | | 4 | }) | | 5 | | | 6 | return ( | | 7 |
| | 8 | {hook.error &&
Error: {hook.error.message}
} | | 9 | | | 12 |
| | 13 | ) | | 14 | } | Type Parameters --------------- FunctionName generic The name of the BAML function being called. Used to infer input and output types. Options { stream?: boolean } Configuration object that determines streaming behavior. Defaults to `{ stream?: true }`. Properties ---------- data FinalDataType | StreamDataType | undefined The current response data. For streaming hooks, this contains either the latest streaming response or the final response. For non-streaming hooks, this only contains the final response. finalData FinalDataType | undefined The final response data. Only set when the request completes successfully. streamData StreamDataType | undefined The latest streaming response. Only available when `Options['stream']` is true. error BamlErrors | undefined Any error that occurred during the request. See [Error Types](https://docs.boundaryml.com/ref/baml_client/errors/overview) . isError boolean True if the request resulted in an error. isLoading boolean True if the request is in progress (either pending or streaming). isPending boolean True if the request is pending (not yet streaming or completed). isSuccess boolean True if the request completed successfully. isStreaming boolean True if the request is currently streaming data. Only available when `Options['stream']` is true. status HookStatus The current status of the request. For streaming hooks: ‘idle’ | ‘pending’ | ‘streaming’ | ‘success’ | ‘error’. For non-streaming hooks: ‘idle’ | ‘pending’ | ‘success’ | ‘error’. mutate (...args: Parameters) => Promise Function to trigger the BAML action. Returns a ReadableStream for streaming hooks, or a Promise of the final response for non-streaming hooks. reset () => void Function to reset the hook state back to its initial values. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # openai-generic | Boundary Documentation The `openai-generic` provider supports all APIs that use OpenAI’s request and response formats, such as Groq, HuggingFace, Ollama, OpenRouter, and Together AI. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "https://api.provider.com" | | 5 | model "" | | 6 | } | | 7 | } | A non-exhaustive list of providers you can use with `openai-generic`: | Inference Provider | Docs | | --- | --- | | Azure AI Foundry | [Azure AI Foundry](https://docs.boundaryml.com/ref/llm-client-providers/azure-ai-foundary) | | Cerebras | [Cerebras](https://docs.boundaryml.com/ref/llm-client-providers/cerebras) | | Groq | [Groq](https://docs.boundaryml.com/ref/llm-client-providers/groq) | | Hugging Face | [Hugging Face](https://docs.boundaryml.com/ref/llm-client-providers/huggingface) | | Keywords AI | [Keywords AI](https://docs.boundaryml.com/ref/llm-client-providers/keywordsai) | | Llama API | [Llama API](https://docs.boundaryml.com/ref/llm-client-providers/llama-api) | | Litellm | [Litellm](https://docs.boundaryml.com/ref/llm-client-providers/litellm) | | LM Studio | [LM Studio](https://docs.boundaryml.com/ref/llm-client-providers/lmstudio) | | Ollama | [Ollama](https://docs.boundaryml.com/ref/llm-client-providers/ollama) | | OpenRouter | [OpenRouter](https://docs.boundaryml.com/ref/llm-client-providers/openrouter) | | Vercel AI Gateway | [Vercel AI Gateway](https://docs.boundaryml.com/ref/llm-client-providers/vercel-ai-gateway) | | Tinfoil | [Tinfoil](https://docs.boundaryml.com/ref/llm-client-providers/tinfoil) | | TogetherAI | [TogetherAI](https://docs.boundaryml.com/ref/llm-client-providers/together) | | Unify AI | [Unify AI](https://docs.boundaryml.com/ref/llm-client-providers/unify) | | vLLM | [vLLM](https://docs.boundaryml.com/ref/llm-client-providers/vllm) | BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. You can use this to modify the `headers` and `base_url` for example. base\_url string The base URL for the API. **Default: `https://api.openai.com/v1`** api\_key stringDefaults to Will be used to build the `Authorization` header, like so: `Authorization: Bearer $api_key` If `api_key` is not set, or is set to an empty string, the `Authorization` header will not be sent. **Default: ``** headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | base\_url "https://api.provider.com" | | 5 | model "" | | 6 | headers { | | 7 | "X-My-Header" "my-value" | | 8 | } | | 9 | } | | 10 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | client\_response\_type openai | anthropic | google | vertexDefaults to openai Please let [us know on Discord](https://www.boundaryml.com/discord) if you have this use case! This is in alpha and we’d like to make sure we continue to cover your use cases. The type of response to return from the client. Sometimes you may expect a different response format than the provider default. For example, using Azure you may be proxying to an endpoint that returns a different format than the OpenAI default. **Default: `openai`** ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Provider request parameters --------------------------- These are other parameters that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. For reasoning models (like `o1` or `o1-mini`), you must use `max_completion_tokens` instead of `max_tokens`. Please set `max_tokens` to `null` in order to get this to work. See the [OpenAI API documentation](https://platform.openai.com/docs/api-reference/chat/create#chat-create-max_completion_tokens) and [OpenAI Reasoning Docs](https://platform.openai.com/docs/guides/reasoning#controlling-costs) for more details about token handling. Example: BAML | | | | --- | --- | | 1 | client OpenAIo1 { | | 2 | provider "openai-generic" | | 3 | options { | | 4 | model "o4-mini" | | 5 | max\_tokens null | | 6 | } | | 7 | } | Consult the specific provider’s documentation for more information. messages DO NOT USE BAML will auto construct this field for you from the prompt stream DO NOT USE BAML will auto construct this field for you based on how you call the client in your code model string The model to use. For OpenAI, this might be `"gpt-5-mini"`; for Ollama, this might be `"llama2"`. The exact syntax will depend on your API provider’s documentation: we’ll just forward it to them as-is. For all other options, see the [official OpenAI API documentation](https://platform.openai.com/docs/api-reference/chat/create) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Generated Hooks Reference | Boundary Documentation BAML automatically generates a type-safe React hook for each BAML function. Each hook follows the naming pattern `use{FunctionName}` and supports both streaming and non-streaming modes. Example UsageBAML Function | | | | --- | --- | | 1 | import { useWriteMeAStory } from "@/baml\_client/react/hooks"; | | 2 | | | 3 | // Basic usage with streaming enabled by default | | 4 | const hook = useWriteMeAStory(); | | 5 | | | 6 | // Access streaming and final data | | 7 | const { data, streamData, finalData } = hook; | | 8 | | | 9 | // Track request state | | 10 | const { isLoading, isStreaming, isPending, isSuccess, isError } = hook; | | 11 | | | 12 | // Execute the function | | 13 | await hook.mutate("A story about a brave AI"); | | 14 | | | 15 | // Reset state if needed | | 16 | hook.reset(); | HookInput --------- The hook accepts an optional configuration object. See [Hook Input](https://docs.boundaryml.com/ref/baml_client/react-next-js/hook-input) for complete details. stream boolean Enable streaming mode for real-time updates. Defaults to true. onStreamData (response?: StreamDataType) => void Callback for streaming updates. Only available when streaming is enabled. onFinalData (response?: FinalDataType) => void Callback when the request completes. onData (response?: StreamDataType | FinalDataType) => void Unified callback for both streaming and final responses. onError (error: BamlErrors) => void Callback when an error occurs. See [Error Types](https://docs.boundaryml.com/ref/baml_client/errors/overview) . HookOutput ---------- The hook returns an object with the following properties. See [Hook Output](https://docs.boundaryml.com/ref/baml_client/react-next-js/hook-output) for complete details. data FinalDataType | StreamDataType | undefined The current response data. Contains either streaming or final data depending on the request state. finalData FinalDataType | undefined The final response data. Only available when the request completes. streamData StreamDataType | undefined Latest streaming update. Only available in streaming mode. error BamlErrors | undefined Error information if the request fails. See [Error Types](https://docs.boundaryml.com/ref/baml_client/errors/overview) . isLoading boolean True while the request is in progress (either pending or streaming). isPending boolean True if the request is pending (not yet streaming or completed). isStreaming boolean True if the request is currently streaming data. Only available in streaming mode. isSuccess boolean True if the request completed successfully. isError boolean True if the request failed. status HookStatus Current state of the request. For streaming hooks: ‘idle’ | ‘pending’ | ‘streaming’ | ‘success’ | ‘error’. For non-streaming hooks: ‘idle’ | ‘pending’ | ‘success’ | ‘error’. mutate (...args: Parameters) => Promise Function to execute the BAML function. Returns a ReadableStream for streaming hooks, or a Promise of the final response for non-streaming hooks. reset () => void Function to reset the hook state back to its initial values. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Timeout Configuration | Boundary Documentation Configure timeouts on any BAML client to prevent requests from hanging indefinitely. Overview -------- Timeouts can be configured on leaf clients (OpenAI, Anthropic, etc.). Timeout Options --------------- All timeout values are specified in **milliseconds** as positive integers. connect\_timeout\_ms int Maximum time to establish a network connection to the provider. **Default:** No timeout (infinite) | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | model "gpt-4" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | http { | | 7 | connect\_timeout\_ms 5000 // 5 seconds | | 8 | } | | 9 | } | | 10 | } | time\_to\_first\_token\_timeout\_ms int Maximum time to receive the first token after sending the request. **Default:** No timeout (infinite) Particularly useful for detecting when a provider accepts the request but takes too long to start generating. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | model "gpt-4" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | http { | | 7 | time\_to\_first\_token\_timeout\_ms 10000 // 10 seconds | | 8 | } | | 9 | } | | 10 | } | idle\_timeout\_ms int Maximum time between receiving consecutive data chunks. **Default:** No timeout (infinite) Important for detecting stalled streaming connections. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | model "gpt-4" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | http { | | 7 | idle\_timeout\_ms 15000 // 15 seconds | | 8 | } | | 9 | } | | 10 | } | request\_timeout\_ms int Maximum total time for the entire request-response cycle. **Default:** No timeout (infinite) For streaming responses, this applies to the entire stream duration (first token to last token). | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | model "gpt-4" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | http { | | 7 | request\_timeout\_ms 60000 // 60 seconds | | 8 | } | | 9 | } | | 10 | } | Timeout Composition ------------------- When composite clients reference subclients with their own timeouts, the **minimum (most restrictive) timeout wins**. ### Example | | | | --- | --- | | 1 | client FastClient { | | 2 | provider openai | | 3 | options { | | 4 | model "gpt-3.5-turbo" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | http { | | 7 | connect\_timeout\_ms 3000 | | 8 | request\_timeout\_ms 20000 | | 9 | } | | 10 | } | | 11 | } | | 12 | | | 13 | client SlowClient { | | 14 | provider openai | | 15 | options { | | 16 | model "gpt-4" | | 17 | api\_key env.OPENAI\_API\_KEY | | 18 | http { | | 19 | request\_timeout\_ms 60000 | | 20 | } | | 21 | } | | 22 | } | | 23 | | | 24 | client MyFallback { | | 25 | provider fallback | | 26 | options { | | 27 | strategy \[FastClient, SlowClient\] | | 28 | http { | | 29 | connect\_timeout\_ms 5000 // Parent timeout | | 30 | idle\_timeout\_ms 15000 // Parent timeout | | 31 | } | | 32 | } | | 33 | } | **Effective timeouts:** When calling `FastClient`: * `connect_timeout_ms`: `min(5000, 3000)` = **3000ms** (FastClient is stricter) * `request_timeout_ms`: `min(∞, 20000)` = **20000ms** (only FastClient defines it) * `idle_timeout_ms`: `min(15000, ∞)` = **15000ms** (only parent defines it) When calling `SlowClient`: * `connect_timeout_ms`: `min(5000, ∞)` = **5000ms** (only parent defines it) * `request_timeout_ms`: `min(∞, 60000)` = **60000ms** (only SlowClient defines it) * `idle_timeout_ms`: `min(15000, ∞)` = **15000ms** (only parent defines it) Timeout Evaluation ------------------ All timeouts are evaluated concurrently. A request fails when **any** timeout is exceeded: 1. **Connection phase:** `connect_timeout_ms` applies 2. **After connection:** * `time_to_first_token_timeout_ms` starts when request is sent * `request_timeout_ms` starts when request is sent * `idle_timeout_ms` starts after each chunk is received Interaction with Retry Policies ------------------------------- When a client has both timeouts and a retry policy: * Each retry attempt gets the **full timeout duration** * A timeout triggers the retry mechanism (if configured) * Total elapsed time = (number of attempts) × (timeout per attempt) + (retry delays) Example: | | | | --- | --- | | 1 | retry\_policy Exponential { | | 2 | max\_retries 3 | | 3 | strategy { | | 4 | type exponential\_backoff | | 5 | } | | 6 | } | | 7 | | | 8 | client MyClient { | | 9 | provider openai | | 10 | retry\_policy Exponential | | 11 | options { | | 12 | model "gpt-4" | | 13 | api\_key env.OPENAI\_API\_KEY | | 14 | http { | | 15 | request\_timeout\_ms 30000 // Each attempt gets 30 seconds | | 16 | } | | 17 | } | | 18 | } | Maximum possible time: ~30s × 4 attempts + exponential backoff delays Runtime Overrides ----------------- Override timeout values at runtime using the client registry: TypeScriptPythonRuby | | | | --- | --- | | 1 | import { b } from './baml\_client' | | 2 | | | 3 | const result = await b.MyFunction(input, { | | 4 | clientRegistry: b.ClientRegistry.override({ | | 5 | "MyClient": { | | 6 | options: { | | 7 | http: { | | 8 | request\_timeout\_ms: 10000, | | 9 | idle\_timeout\_ms: 5000 | | 10 | } | | 11 | } | | 12 | } | | 13 | }) | | 14 | }) | Runtime overrides follow the same composition rules: the minimum timeout wins when composing runtime values with config file values. Error Handling -------------- Timeout errors are represented by `BamlTimeoutError`, a subclass of `BamlClientError`: | | | --- | | BamlError | | └── BamlClientError | | └── BamlTimeoutError | Timeout errors include structured fields: * `client`: The client name that timed out * `timeout_type`: The specific timeout that was exceeded * `configured_value_ms`: The configured timeout value in milliseconds * `elapsed_ms`: The actual elapsed time in milliseconds * `message`: A human-readable error message PythonTypeScriptRuby | | | | --- | --- | | 1 | from baml\_py.errors import BamlTimeoutError | | 2 | | | 3 | try: | | 4 | result = await b.MyFunction(input) | | 5 | except BamlTimeoutError as e: | | 6 | print(f"Timeout: {e.timeout\_type}") | | 7 | print(f"Configured: {e.configured\_value\_ms}ms") | | 8 | print(f"Elapsed: {e.elapsed\_ms}ms") | Validation Rules ---------------- BAML validates timeout configurations at compile time: 1. **Positive values:** All timeout values must be positive integers 2. **Logical constraints:** `request_timeout_ms` must be ≥ `time_to_first_token_timeout_ms` (if both are specified) Invalid configurations will cause BAML to raise validation errors with helpful messages. See Also -------- * [Configuring Timeouts Guide](https://docs.boundaryml.com/guide/baml-basics/timeouts) - User guide with examples * [Fallback Strategy](https://docs.boundaryml.com/ref/llm-client-strategies/fallback) - Using timeouts with fallback clients * [Retry Policies](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy) - Using timeouts with retries * [Error Handling](https://docs.boundaryml.com/guide/baml-basics/error-handling) - Handling timeout errors [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # llama-api | Boundary Documentation [Llama API](https://llama.developer.meta.com/docs) supports the OpenAI client, allowing you to use the [`openai-generic`](https://docs.boundaryml.com/docs/snippets/clients/providers/openai) provider with an overridden `base_url`. Note that to call Llama, you must use its OpenAI-compatible `/compat/v1` endpoint. See [Llama’s OpenAI compatibility documentation](https://llama.developer.meta.com/docs/features/compatibility) . | | | | --- | --- | | 1 | client LlamaAPI { | | 2 | provider openai-generic | | 3 | retry\_policy Exponential | | 4 | options { | | 5 | base\_url "https://llama-api.meta.com/compat/v1" | | 6 | model "Llama-3.3-8B-Instruct" | | 7 | api\_key env.LLAMA\_API\_KEY | | 8 | // see openai-generic docs for more options | | 9 | } | | 10 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # BamlAbortError | Boundary Documentation Overview -------- `BamlAbortError` is thrown when a BAML function call is cancelled via an abort controller. This error indicates that the operation was intentionally stopped rather than failing due to an actual error condition. Class Definition ---------------- ###### TypeScript ###### Python ###### Go ###### Ruby | | | | --- | --- | | 1 | export class BamlAbortError extends Error { | | 2 | public readonly name: string = 'BamlAbortError' | | 3 | public readonly reason?: any | | 4 | public readonly detailed\_message: string | | 5 | | | 6 | constructor(message: string, reason?: any, detailed\_message: string = '') { | | 7 | super(message) | | 8 | this.reason = reason | | 9 | this.detailed\_message = detailed\_message | | 10 | } | | 11 | } | Properties ---------- ### `message` **Type**: `string` Description of why the operation was aborted. This is typically a generic message like “Operation aborted” unless a specific message was provided during cancellation. ### `reason` **Type**: `any` (TypeScript/Python) / `interface{}` (Go) / `Object` (Ruby) Optional additional context about the cancellation. This can be any value provided when calling the `abort()` method. ### `name` **Type**: `string` Always returns `"BamlAbortError"` for easy error type identification. ### `detailed_message` **Type**: `string` Comprehensive error information that includes the complete history of all failed attempts when using fallback clients or retry policies. For abort errors, this typically contains the same information as `message` but may include additional debugging details about the cancellation context. Error Detection --------------- ### TypeScript | | | | --- | --- | | 1 | import { BamlAbortError } from '@/baml\_client' | | 2 | | | 3 | try { | | 4 | const result = await b.FunctionName(input, { | | 5 | abortController: controller | | 6 | }) | | 7 | } catch (error) { | | 8 | // Method 1: instanceof check (recommended) | | 9 | if (error instanceof BamlAbortError) { | | 10 | console.log('Operation was cancelled') | | 11 | } | | 12 | | | 13 | // Method 2: name check (works with minification) | | 14 | if (error.name === 'BamlAbortError') { | | 15 | console.log('Operation was cancelled') | | 16 | } | | 17 | } | ### Python | | | | --- | --- | | 1 | from baml\_py import BamlAbortError | | 2 | | | 3 | try: | | 4 | result = await b.FunctionName( | | 5 | input, | | 6 | baml\_options={"abort\_controller": controller} | | 7 | ) | | 8 | except BamlAbortError as e: | | 9 | print(f"Operation was cancelled: {e}") | | 10 | if e.reason: | | 11 | print(f"Reason: {e.reason}") | | 12 | except Exception as e: | | 13 | # Handle other errors | | 14 | raise | ### Go | | | | --- | --- | | 1 | import ( | | 2 | "context" | | 3 | "errors" | | 4 | ) | | 5 | | | 6 | result, err := b.FunctionName(ctx, input) | | 7 | if err != nil { | | 8 | if errors.Is(err, context.Canceled) { | | 9 | // Direct cancellation | | 10 | fmt.Println("Operation was cancelled") | | 11 | } else if errors.Is(err, context.DeadlineExceeded) { | | 12 | // Timeout-based cancellation | | 13 | fmt.Println("Operation timed out") | | 14 | } else { | | 15 | // Other error | | 16 | return err | | 17 | } | | 18 | } | ### Ruby | | | | --- | --- | | 1 | begin | | 2 | result = b.function\_name( | | 3 | input, | | 4 | baml\_options: { abort\_controller: controller } | | 5 | ) | | 6 | rescue Baml::AbortError => e | | 7 | puts "Operation was cancelled: #{e.message}" | | 8 | puts "Reason: #{e.reason}" if e.reason | | 9 | rescue => e | | 10 | # Handle other errors | | 11 | raise | | 12 | end | Common Patterns --------------- ### Distinguishing Cancellation Types | | | | --- | --- | | 1 | try { | | 2 | const result = await b.FunctionName(input, { | | 3 | abortController: controller | | 4 | }) | | 5 | } catch (error) { | | 6 | if (error instanceof BamlAbortError) { | | 7 | if (error.reason === 'user\_cancelled') { | | 8 | // User explicitly cancelled | | 9 | showMessage('You cancelled the operation') | | 10 | } else if (error.reason === 'timeout') { | | 11 | // Timeout occurred | | 12 | showMessage('Operation timed out. Please try again.') | | 13 | } else { | | 14 | // Generic cancellation | | 15 | showMessage('Operation was cancelled') | | 16 | } | | 17 | } else { | | 18 | // Handle other errors | | 19 | throw error | | 20 | } | | 21 | } | ### Cleanup After Cancellation | | | | --- | --- | | 1 | const controller = new AbortController() | | 2 | let cleanup = null | | 3 | | | 4 | try { | | 5 | // Set up resources | | 6 | cleanup = await setupResources() | | 7 | | | 8 | const result = await b.FunctionName(input, { | | 9 | abortController: controller | | 10 | }) | | 11 | | | 12 | return result | | 13 | } catch (error) { | | 14 | if (error instanceof BamlAbortError) { | | 15 | console.log('Operation cancelled, cleaning up...') | | 16 | } | | 17 | throw error | | 18 | } finally { | | 19 | // Always cleanup, whether cancelled or not | | 20 | if (cleanup) { | | 21 | await cleanup() | | 22 | } | | 23 | } | ### Retry Logic with Abort Errors | | | | --- | --- | | 1 | async function retryableOperation(input: any, maxRetries: number = 3) { | | 2 | for (let attempt = 1; attempt <= maxRetries; attempt++) { | | 3 | const controller = new AbortController() | | 4 | | | 5 | try { | | 6 | // Set timeout for each attempt | | 7 | setTimeout(() => controller.abort('timeout'), 30000) | | 8 | | | 9 | return await b.FunctionName(input, { | | 10 | abortController: controller | | 11 | }) | | 12 | } catch (error) { | | 13 | if (error instanceof BamlAbortError) { | | 14 | if (error.reason === 'timeout' && attempt < maxRetries) { | | 15 | console.log(\`Attempt ${attempt} timed out, retrying...\`) | | 16 | continue | | 17 | } | | 18 | // Don't retry for user cancellations | | 19 | throw error | | 20 | } | | 21 | // Don't retry for other errors | | 22 | throw error | | 23 | } | | 24 | } | | 25 | } | Integration with Streaming -------------------------- When streaming operations are cancelled, the error behavior differs slightly: ###### TypeScript ###### Python | | | | --- | --- | | 1 | const controller = new AbortController() | | 2 | const stream = b.stream.FunctionName(input, { | | 3 | abortController: controller | | 4 | }) | | 5 | | | 6 | try { | | 7 | for await (const chunk of stream) { | | 8 | // Process chunk | | 9 | if (shouldCancel) { | | 10 | controller.abort('user\_request') | | 11 | } | | 12 | } | | 13 | } catch (error) { | | 14 | if (error instanceof BamlAbortError) { | | 15 | // Stream was cancelled | | 16 | console.log('Stream cancelled:', error.reason) | | 17 | } | | 18 | } | Best Practices -------------- ### 1\. Always Handle Abort Errors Explicitly | | | | --- | --- | | 1 | // Good: Explicit handling | | 2 | try { | | 3 | await operation() | | 4 | } catch (error) { | | 5 | if (error instanceof BamlAbortError) { | | 6 | // Handle cancellation specifically | | 7 | return { cancelled: true } | | 8 | } | | 9 | // Re-throw unexpected errors | | 10 | throw error | | 11 | } | | 12 | | | 13 | // Bad: Generic error handling | | 14 | try { | | 15 | await operation() | | 16 | } catch (error) { | | 17 | // All errors treated the same | | 18 | console.error('Failed:', error) | | 19 | } | ### 2\. Provide Meaningful Cancellation Reasons | | | | --- | --- | | 1 | // Good: Clear reason | | 2 | controller.abort('user\_clicked\_cancel') | | 3 | controller.abort({ type: 'timeout', duration: 30000 }) | | 4 | | | 5 | // Bad: No reason | | 6 | controller.abort() | ### 3\. Don’t Retry Cancelled Operations | | | | --- | --- | | 1 | // Good: Check error type before retry | | 2 | if (error instanceof BamlAbortError) { | | 3 | // Don't retry - it was intentionally cancelled | | 4 | return | | 5 | } | | 6 | | | 7 | // Bad: Retry everything | | 8 | for (let i = 0; i < 3; i++) { | | 9 | try { | | 10 | return await operation() | | 11 | } catch (error) { | | 12 | // This might retry a cancelled operation! | | 13 | continue | | 14 | } | | 15 | } | Related Documentation --------------------- * [AbortController](https://docs.boundaryml.com/ref/baml_client/abort-signal) - API reference for abort controllers * [Error Overview](https://docs.boundaryml.com/ref/baml_client/errors/overview) - Complete error hierarchy * [User Guide: Abort Controllers](https://docs.boundaryml.com/guide/baml-basics/abort-signal) - Learn how to use abort controllers * [Error Handling Guide](https://docs.boundaryml.com/guide/baml-basics/error-handling) - General error handling patterns [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # round-robin | Boundary Documentation The `round_robin` provider allows you to distribute requests across multiple clients in a round-robin fashion. After each call, the next client in the list will be used. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider round-robin | | 3 | options { | | 4 | strategy \[ |\ | 5 | ClientA |\ | 6 | ClientB |\ | 7 | ClientC |\ | 8 | \] | | 9 | } | | 10 | } | Options ------- strategy List\[string\]Required The list of client names to try in order. Cannot be empty. start int The index of the client to start with. **Default is `random(0, len(strategy))`** In the [BAML Playground](https://docs.boundaryml.com/docs/get-started/quickstart/editors-vscode) , Default is `0`. retry\_policy ------------- When using a retry\_policy with a round-robin client, it will rotate the strategy list after each retry. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider round-robin | | 3 | retry\_policy MyRetryPolicy | | 4 | options { | | 5 | strategy \[ |\ | 6 | ClientA |\ | 7 | ClientB |\ | 8 | ClientC |\ | 9 | \] | | 10 | } | | 11 | } | Nesting multiple round-robin clients ------------------------------------ You can nest multiple round-robin clients inside of each other. The round-robin as you would expect. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider round-robin | | 3 | options { | | 4 | strategy \[ |\ | 5 | ClientA |\ | 6 | ClientB |\ | 7 | ClientC |\ | 8 | \] | | 9 | } | | 10 | } | | 11 | | | 12 | client MegaClient { | | 13 | provider round-robin | | 14 | options { | | 15 | strategy \[ |\ | 16 | MyClient |\ | 17 | ClientD |\ | 18 | ClientE |\ | 19 | \] | | 20 | } | | 21 | } | | 22 | | | 23 | // Calling MegaClient will call: | | 24 | // MyClient(ClientA) | | 25 | // ClientD | | 26 | // ClientE | | 27 | // MyClient(ClientB) | | 28 | // etc. | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Jinja Filters | Boundary Documentation Jinja filters allow you to transform and format values within your BAML prompts. Filters are applied using the pipe operator (`|`). Basic Usage ----------- | | | | --- | --- | | 1 | {{ value\|filter\_name }} | | 2 | {{ value\|filter\_name(arg1, arg2) }} | BAML Custom Filters ------------------- ### format Serializes values into structured text while preserving all BAML-specific aliases. Use the required `type` argument to choose the output representation. **Signature**: `value|format(type="yaml" | "json" | "toon", **kwargs)` **Required arguments**: * `type` (string): `"yaml"`, `"json"`, or `"toon"` (alias for TOON serializer) **Format-specific behavior**: | Format | Description | Extra kwargs | | --- | --- | --- | | `yaml` | Human-friendly YAML string with enum/class aliases | None | | `json` | Standard JSON string (minified) with alias-safe serialization | None | | `toon` | Compact TOON format for uniform arrays | `indent`, `delimiter`, `length_marker` | All formats reuse the same alias-aware serializer, so enums emit their `@alias` values and class properties honor `@alias` names at every nesting level (lists, maps, nested classes, etc.). **Examples**: | | | | --- | --- | | 1 | {# YAML for readability #} | | 2 | {{ organization\|format(type="yaml") }} | | 3 | | | 4 | {# JSON for API interop #} | | 5 | {{ organization\|format(type="json") }} | | 6 | | | 7 | {# TOON with custom options #} | | 8 | {{ organization\|format(type="toon", indent=4, delimiter="tab") }} | **TOON options** (only when `format="toon"`): * `indent` (int, default 2): spaces per indent level * `delimiter` (`"comma" | "tab" | "pipe"`, default `"comma"`): column separator for arrays * `length_marker` (single char, optional): prefix to annotate array lengths Invalid combinations raise a template error (e.g., missing `type` or an unknown delimiter for TOON). **About TOON:** TOON (Token-Oriented Object Notation) combines YAML’s indentation with CSV-style tabular layout. It’s designed for uniform arrays of objects (multiple fields per row, same structure across items), where it can provide significant token savings while maintaining LLM-friendly structure validation through explicit array lengths and field headers. **When TOON works best:** * Uniform arrays of objects (e.g., lists of users, transactions, products) * Highly structured, tabular data **When other formats may be better:** * Deeply nested structures (compact JSON may use fewer tokens) * Semi-uniform or mixed data * Pure flat tables (CSV is more compact) For benchmarks, detailed comparisons, and the full specification, see the [TOON repository](https://github.com/toon-format/toon) . ### regex\_match Tests if a string matches a regular expression pattern. **Signature**: `value|regex_match(pattern)` **Example**: | | | | --- | --- | | 1 | {% if phone\_number\|regex\_match("\\\\(?\\\\d{3}\\\\)?\[-.\\\\s\]?\\\\d{3}\[-.\\\\s\]?\\\\d{4}") %} | | 2 | Valid phone number | | 3 | {% endif %} | ### sum Sums all numeric values in an array. **Signature**: `array|sum` **Example**: | | | | --- | --- | | 1 | Total: {{ prices\|sum }} | Standard Jinja Filters ---------------------- BAML supports all standard Minijinja filters. Here are some commonly used ones: ### length Returns the length of a string, array, or object. | | | | --- | --- | | 1 | {{ items\|length }} items | ### upper / lower Converts string to uppercase or lowercase. | | | | --- | --- | | 1 | {{ name\|upper }} | | 2 | {{ name\|lower }} | ### title Converts string to title case. | | | | --- | --- | | 1 | {{ title\|title }} | ### trim Removes whitespace from both ends of a string. | | | | --- | --- | | 1 | {{ text\|trim }} | ### default Provides a default value if the variable is undefined or empty. | | | | --- | --- | | 1 | {{ user\_name\|default("Guest") }} | ### join Joins array elements into a string with a separator. | | | | --- | --- | | 1 | {{ tags\|join(", ") }} | ### first / last Returns the first or last element of an array. | | | | --- | --- | | 1 | {{ items\|first }} | | 2 | {{ items\|last }} | ### sort Sorts an array. | | | | --- | --- | | 1 | {% for item in items\|sort %} | | 2 | {{ item }} | | 3 | {% endfor %} | ### unique Removes duplicate values from an array. | | | | --- | --- | | 1 | {{ values\|unique }} | ### reverse Reverses an array or string. | | | | --- | --- | | 1 | {{ items\|reverse }} | ### replace Replaces occurrences of a substring. | | | | --- | --- | | 1 | {{ text\|replace("old", "new") }} | ### round Rounds a number to a specified precision. | | | | --- | --- | | 1 | {{ price\|round(2) }} | ### abs Returns the absolute value of a number. | | | | --- | --- | | 1 | {{ value\|abs }} | Chaining Filters ---------------- You can chain multiple filters together: | | | | --- | --- | | 1 | {{ name\|trim\|lower\|title }} | | 2 | {{ items\|unique\|sort\|join(", ") }} | More Information ---------------- For a complete list of standard Jinja filters, see the [Minijinja documentation](https://docs.rs/minijinja/latest/minijinja/filters/index.html#functions) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # OnTick | Boundary Documentation The `onTick` feature allows you to receive real-time callbacks during BAML function execution, providing access to internal state, streaming responses, and progress updates. This is particularly useful for monitoring function progress, debugging, and accessing intermediate data like “thinking” content from streaming LLM responses. Quick Start ----------- ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import baml\_py | | 3 | | | 4 | def on\_tick(reason: str, log: baml\_py.FunctionLog): | | 5 | print(f"Tick received: {reason}") | | 6 | print(f"Function calls: {len(log.calls) if log else 0}") | | 7 | | | 8 | \# Use with async function | | 9 | result = await b.TestFunction("Hello world", baml\_options={"on\_tick": on\_tick}) | Common Use Cases ---------------- ### Progress Monitoring Track the progress of long-running BAML function calls: ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import baml\_py | | 3 | | | 4 | def progress\_monitor(reason: str, log: baml\_py.FunctionLog): | | 5 | tick\_count = getattr(progress\_monitor, 'count', 0) | | 6 | progress\_monitor.count = tick\_count + 1 | | 7 | | | 8 | print(f"Progress tick #{progress\_monitor.count}: {reason}") | | 9 | | | 10 | if log and log.calls: | | 11 | latest\_call = log.calls\[-1\] | | 12 | print(f"Latest call to: {latest\_call.client\_name}") | | 13 | | | 14 | result = await b.ExtractResume( | | 15 | resume\_text, | | 16 | baml\_options={"on\_tick": progress\_monitor} | | 17 | ) | ### Accessing Streaming “Thinking” Content Extract intermediate “thinking” content from streaming LLM responses: ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | import json | | 2 | from baml\_client import b | | 3 | from baml\_py import baml\_py | | 4 | | | 5 | def extract\_thinking(reason: str, log: baml\_py.FunctionLog): | | 6 | thinking\_content = "" | | 7 | | | 8 | if log and log.calls: | | 9 | last\_call = log.calls\[-1\] | | 10 | | | 11 | # Check if it's a streaming call | | 12 | if hasattr(last\_call, "sse\_responses"): | | 13 | sse\_responses = last\_call.sse\_responses() | | 14 | if sse\_responses: | | 15 | for response in sse\_responses: | | 16 | try: | | 17 | data = json.loads(response.text) | | 18 | if "delta" in data and "thinking" in data\["delta"\]: | | 19 | thinking\_content += data\["delta"\]\["thinking"\] | | 20 | except (json.JSONDecodeError, AttributeError): | | 21 | pass | | 22 | | | 23 | if thinking\_content: | | 24 | print(f"Thinking content: {thinking\_content}") | | 25 | | | 26 | \# Use with streaming function | | 27 | stream = b.stream.TestThinking( | | 28 | "Write a story about AI", | | 29 | baml\_options={"on\_tick": extract\_thinking} | | 30 | ) | | 31 | | | 32 | async for msg in stream: | | 33 | pass | | 34 | | | 35 | result = await stream.get\_final\_response() | ### Debugging and Logging Use onTick for comprehensive debugging and logging: ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import baml\_py | | 3 | | | 4 | def debug\_logger(reason: str, log: baml\_py.FunctionLog): | | 5 | print(f"=== DEBUG TICK: {reason} ===") | | 6 | | | 7 | if log: | | 8 | print(f"Function: {log.function\_name}") | | 9 | print(f"Log type: {log.log\_type}") | | 10 | print(f"Number of calls: {len(log.calls)}") | | 11 | | | 12 | if log.usage: | | 13 | print(f"Input tokens: {log.usage.input\_tokens}") | | 14 | print(f"Output tokens: {log.usage.output\_tokens}") | | 15 | | | 16 | if log.calls: | | 17 | latest\_call = log.calls\[-1\] | | 18 | print(f"Latest provider: {latest\_call.provider}") | | 19 | print(f"Latest client: {latest\_call.client\_name}") | | 20 | | | 21 | if latest\_call.usage: | | 22 | print(f"Call usage - Input: {latest\_call.usage.input\_tokens}, Output: {latest\_call.usage.output\_tokens}") | | 23 | | | 24 | print("=== END DEBUG ===\\n") | | 25 | | | 26 | result = await b.TestFunction("Debug this call", baml\_options={"on\_tick": debug\_logger}) | Using with Collectors --------------------- OnTick can be used alongside [Collectors](https://docs.boundaryml.com/ref/baml_client/collector) for comprehensive logging: ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import baml\_py, Collector | | 3 | | | 4 | def on\_tick\_with\_collector(reason: str, log: baml\_py.FunctionLog): | | 5 | print(f"OnTick fired: {reason}") | | 6 | | | 7 | \# Create a collector alongside onTick | | 8 | collector = Collector("my-collector") | | 9 | | | 10 | result = await b.TestFunction( | | 11 | "Hello world", | | 12 | baml\_options={ | | 13 | "on\_tick": on\_tick\_with\_collector, | | 14 | "collector": collector | | 15 | } | | 16 | ) | | 17 | | | 18 | \# Access data through both mechanisms | | 19 | print(f"Collector usage: {collector.last.usage}") | Error Handling -------------- OnTick callbacks should handle errors gracefully. If an onTick callback throws an error, the function execution will continue: ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | from baml\_client import b | | 2 | from baml\_py import baml\_py | | 3 | | | 4 | def error\_prone\_tick(reason: str, log: baml\_py.FunctionLog): | | 5 | # Simulate an error condition | | 6 | if hasattr(error\_prone\_tick, 'count'): | | 7 | error\_prone\_tick.count += 1 | | 8 | else: | | 9 | error\_prone\_tick.count = 1 | | 10 | | | 11 | if error\_prone\_tick.count == 5: | | 12 | raise ValueError("Intentional error in onTick") | | 13 | | | 14 | print(f"Tick #{error\_prone\_tick.count}: {reason}") | | 15 | | | 16 | \# Function will complete despite callback errors | | 17 | result = await b.TestFunction("Hello world", baml\_options={"on\_tick": error\_prone\_tick}) | | 18 | print("Function completed successfully despite onTick error") | Limitations ----------- Keep these limitations in mind when using onTick: 1. **Synchronous Functions**: OnTick is **not supported** for synchronous function calls. Attempting to use onTick with sync functions will throw an error. 2. **Error Isolation**: Errors in onTick callbacks do not stop function execution, but they may not be explicitly surfaced. API Reference ------------- ### OnTick Callback Signature ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | def on\_tick(reason: str, log: baml\_py.FunctionLog \| None) -> None: | | 2 | """ | | 3 | OnTick callback function | | 4 | | | 5 | Args: | | 6 | reason: The reason for the tick (currently always "Unknown") | | 7 | log: The current function log with call information | | 8 | """ | | 9 | pass | ### Integration with Function Calls OnTick is passed via the `baml_options` parameter (Python) or options object (TypeScript/Go): ###### Python ###### TypeScript ###### Go | | | | --- | --- | | 1 | \# Async function call | | 2 | result = await b.FunctionName(input, baml\_options={"on\_tick": callback}) | | 3 | | | 4 | \# Streaming function call | | 5 | stream = b.stream.FunctionName(input, baml\_options={"on\_tick": callback}) | Related Topics -------------- * [Collector](https://docs.boundaryml.com/ref/baml_client/collector) - Learn about comprehensive logging with Collectors * [Using with\_options](https://docs.boundaryml.com/ref/baml_client/with-options) - Configure global options for BAML functions * [Streaming](https://docs.boundaryml.com/docs/calling-baml/streaming) - Understand streaming function calls Best Practices -------------- 1. **Keep Callbacks Light**: OnTick callbacks should be fast and non-blocking 2. **Handle Errors Gracefully**: Always include error handling in your callbacks 3. **Use with Collectors**: Combine onTick with Collectors for comprehensive logging 4. **Monitor Performance**: Test the performance impact for your specific use case 5. **Async Only**: Remember that onTick only works with async function calls, not sync calls [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # openai | Boundary Documentation The `openai` provider supports the OpenAI `/chat` endpoint, setting OpenAI-specific default configuration options. For Azure, we recommend using [`azure-openai`](https://docs.boundaryml.com/ref/llm-client-providers/azure) instead. For all other OpenAI-compatible API providers, such as Groq, HuggingFace, Ollama, OpenRouter, Together AI, and others, we recommend using [`openai-generic`](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) instead. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | api\_key env.MY\_OPENAI\_KEY | | 5 | model "gpt-5-mini" | | 6 | temperature 0.1 | | 7 | } | | 8 | } | BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) are modify the API request sent to the provider. You can use this to modify the `headers` and `base_url` for example. api\_key stringDefaults to env.OPENAI\_API\_KEY Will be used to build the `Authorization` header, like so: `Authorization: Bearer $api_key` **Default: `env.OPENAI_API_KEY`** base\_url string The base URL for the API. **Default: `https://api.openai.com/v1`** headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | api\_key env.MY\_OPENAI\_KEY | | 5 | model "gpt-5-mini" | | 6 | headers { | | 7 | "X-My-Header" "my-value" | | 8 | } | | 9 | } | | 10 | } | default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: ``** | Model | Supports Streaming | | --- | --- | | `o1-preview` | false | | `o1-mini` | false | | `o1-*` | false | | `gpt-5` | true | | `gpt-5-mini` | true | | `*` | true | Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider openai | | 3 | options { | | 4 | model gpt-5 | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | supports\_streaming false | | 7 | } | | 8 | } | | 9 | | | 10 | function MyFunction() -> string { | | 11 | client MyClientWithoutStreaming | | 12 | prompt #"Write a short story"# | | 13 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | client\_response\_type openai | anthropic | google | vertexDefaults to openai Please let [us know on Discord](https://www.boundaryml.com/discord) if you have this use case! This is in alpha and we’d like to make sure we continue to cover your use cases. The type of response to return from the client. Sometimes you may expect a different response format than the provider default. For example, using Azure you may be proxying to an endpoint that returns a different format than the OpenAI default. **Default: `openai`** ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Provider request parameters --------------------------- These are other parameters that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. For reasoning models (like `o1` or `o1-mini`), you must use `max_completion_tokens` instead of `max_tokens`. Please set `max_tokens` to `null` in order to get this to work. See the [OpenAI API documentation](https://platform.openai.com/docs/api-reference/chat/create#chat-create-max_completion_tokens) and [OpenAI Reasoning Docs](https://platform.openai.com/docs/guides/reasoning#controlling-costs) for more details about token handling. Example: BAML | | | | --- | --- | | 1 | client OpenAIo1 { | | 2 | provider openai | | 3 | options { | | 4 | model "o1-mini" | | 5 | max\_tokens null | | 6 | } | | 7 | } | Consult the specific provider’s documentation for more information. messages DO NOT USE BAML will auto construct this field for you from the prompt stream DO NOT USE BAML will auto construct this field for you based on how you call the client in your code model string The model to use. | Model | Use Case | Context | Key Features | | --- | --- | --- | --- | | **gpt-5** | Coding, agentic tasks, expert reasoning | 400K total | Built-in reasoning, 45% fewer errors | | **gpt-5-mini** | Well-defined tasks, cost-efficient | 400K total | Faster alternative to GPT-5 | | **gpt-5-nano** | Lightweight tasks, maximum efficiency | 400K total | Most cost-effective GPT-5 variant | | **gpt-4.1** | Large-scale technical work | 1M | Enhanced coding, instruction following | | **gpt-4.1-mini** | Balanced performance and cost | 1M | Replaces GPT-4o mini | | **gpt-4.1-nano** | Lightweight variant | 1M | Budget-friendly option | | **gpt-4o** | General purpose, multimodal | 200K | Updated knowledge cutoff June 2024 | Note: While GPT-5 is available through this provider, we recommend using the `openai-responses` provider for GPT-5 models to access enhanced response formatting features. See openai docs for the list of openai models. You can pass any model name you wish, we will not check if it exists. For all other options, see the [official OpenAI API documentation](https://platform.openai.com/docs/api-reference/chat/create) . Changing Regions ---------------- To access OpenAI’s API in a different region, you can set the `base_url` option to the appropriate endpoint. For example, to access the API in the EU region, you can set the `base_url` option to `https://eu.api.openai.com/v1`. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # vertex-ai | Boundary Documentation The `vertex-ai` provider is used to interact with the Google Vertex AI services. As of BAML 0.85.0, `vertex-ai` now supports Anthropic models! Example using a Vertex API Key (Express Mode): BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location us-central1 // or "global" | | 6 | project\_id my-project-id | | 7 | query\_params { | | 8 | key env.VERTEX\_API\_KEY | | 9 | } | | 10 | } | | 11 | } | Authentication -------------- ### Using a Vertex API Key (Express Mode) To get started quickly, we recommend using Express Mode with a Vertex API Key. This avoids service account setup and works well for prototyping. See Google’s guide: [Use Vertex API keys (Express Mode)](https://cloud.google.com/vertex-ai/generative-ai/docs/start/api-keys?usertype=expressmode) . See also [Express mode overview](https://cloud.google.com/vertex-ai/generative-ai/docs/start/express-mode/overview) . When using a Vertex API Key, set the `key` query parameter and specify your `project_id` and `location`: BAML | | | | --- | --- | | 1 | client VertexApiKeyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location us-central1 // you can also use "global" | | 6 | project\_id my-project-id | | 7 | query\_params { | | 8 | key env.VERTEX\_API\_KEY | | 9 | } | | 10 | } | | 11 | } | **When in doubt, check the ‘cURL’ tab in the playground to see the exact request being sent!** Notes: * `project_id` cannot be inferred when using an API key; set it explicitly. * Keep `credentials` unset when using an API key, so BAML does not prefer service account auth. #### Using a Vertex API Key in the playground You should see the `VERTEX_API_KEY` environment variable in the playground API Keys dialog. You can set it there and you’re all set! ### Using Google Application Credentials If no vertex api key is set, BAML will by default try to authenticate using [application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials) | | | --- | | client MyClient { | | provider vertex-ai | | options { | | model gemini-2.5-pro | | location us-central1 | | project\_id my-project-id | | // we will by default try to use this form of authentication. | | credentials env.MY\_APPLICATION\_CREDENTIALS\_CONTENT | | } | | } | This is what the MY\_APPLICATION\_CREDENTIALS\_CONTENT environment variable looks like: | | | | --- | --- | | 1 | MY\_APPLICATION\_CREDENTIALS\_CONTENT={ | | 2 | "type": "service\_account", | | 3 | "project\_id": "my-project-id", | | 4 | "private\_key\_id": "string", | | 5 | "private\_key": "-----BEGIN PRIVATE KEY-----string\\n-----END PRIVATE KEY-----\\n" | | 6 | ...other fields... | | 7 | } | BAML accepts this blob as a string, a path to a file, or a JSON object. #### More details on Google Application Credentials Here is the order of authentication: * If `GOOGLE_APPLICATION_CREDENTIALS` environment variable is set, it will use the specified service account * If you have run `gcloud auth application-default login`, it will find the credentials generated by `gcloud` by the path convention. Note that you will still need to set either `options.project_id` or the `GOOGLE_CLOUD_PROJECT` environment variable. * If running in GCP, it will query the metadata server to use the attached service account * If `gcloud` is available on the `PATH`, it will use `gcloud auth print-access-token` ### Requirements You need to use an account with a ProjectID that has been authorized to use Vertex. When administering your Google Cloud account, be sure to enable Vertex, and set up ADC: | | | | --- | --- | | $ | gcloud auth application-default login | If you’re using Google Cloud [application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials) , you can expect authentication to work out of the box. Setting [`options.credentials`](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#credentials) will take precedence and force `vertex-ai` to load service account credentials from that file path. ### Playground To use a `vertex-ai` client in the playground, you need to run `gcloud auth application-default login` in the terminal and set the `GOOGLE_CLOUD_PROJECT` environment variable in the “API Keys” dialog. The playground will then use these credentials to auth all Vertex API calls. Debugging --------- ###### Authentication If you’re having issues with `vertex-ai` authentication, you can try setting `BAML_INTERNAL_LOG=debug` to see more detailed logs. To understand these logs, it’ll help to understand the auth implementation of the `vertex-ai` provider. The `vertex-ai` provider uses one of 3 strategies to authenticate with Google Cloud: * `AuthStrategy::JsonString(value: String)` - parse `value` as a JSON object, and use that to resolve a service account * `AuthStrategy::JsonFile(path: String)` - read the file at `path` (relative to the process’ current working directory), parse it as a JSON object, and use that to resolve a service account * `AuthStrategy::SystemDefault` - try 3 strategies in order: * resolve credentials from `.config/gcloud/application_default_credentials.json`; else * use the service account from the GCP compute environment by querying the metadata server; else * check if `gcloud` is available on the `PATH` and if so, use `gcloud auth print-access-token` We choose one of the three strategies based on the following rules, in order: 1. Is `credentials` provided? * If so, and it’s a string containing a JSON object, we use `AuthStrategy::JsonString` with `credentials`. * If so, and it’s a JSON object, we use `AuthStrategy::JsonObject` with `credentials` (this is probably only relevant if you’re using the [`ClientRegistry`](https://docs.boundaryml.com/ref/baml_client/client-registry) API in `baml_client`). * If so, but it’s just a regular string, use `AuthStrategy::JsonFile` with `credentials`. 2. Is `GOOGLE_APPLICATION_CREDENTIALS` set? * If so, and it looks like a JSON object, we use `AuthStrategy::JsonString` with `GOOGLE_APPLICATION_CREDENTIALS` * If so, but it’s just a regular string, use `AuthStrategy::JsonFile` with `GOOGLE_APPLICATION_CREDENTIALS` 3. Else, we use `AuthStrategy::SystemDefault` ###### Request protocol We use the REST API to send requests to Vertex AI, and you can debug these using the BAML playground and switch from showing “Prompt Preview” to “Raw cURL”, which will show you the exact request the BAML runtime will construct and send. Non-streaming requests will use `{base_url}:generateContent`: https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT\_ID}/locations/${LOCATION}/publishers/google/models/${MODEL\_ID}:generateContent Streaming requests will use `{base_url}:streamGenerateContent?alt=sse`: https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT\_ID}/locations/${LOCATION}/publishers/google/models/${MODEL\_ID}:streamGenerateContent ###### Model not found errors If you encounter an error like: \[modelname\] was not found or your project does not have access to it. Please ensure you are using a valid model version. Try setting `location: global` in your client options: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location global | | 6 | project\_id my-project-id | | 7 | } | | 8 | } | Some models may only be available in specific regions or through the global endpoint. BAML-specific request `options` ------------------------------- These unique parameters (aka `options`) modify the API request sent to the provider. You can use this to modify the `headers` and `base_url` for example. base\_url string The base URL for the API. **Default**: inferred from the `project_id` and `location` using the following format: https://{LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT\_ID}/locations/{LOCATION}/publishers/google/models/ If the location is `global`, the base URL will be: https://aiplatform.googleapis.com/v1/projects/${PROJECT\_ID}/locations/global/publishers/google/models/ Can be used in lieu of the **`project_id`** and **`location`** fields, to manually set the request URL. project\_id string The Google Cloud project ID hosting the Vertex AI service you want to call. **Default**: inferred from the provided credentials (see [`Authentication`](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#authentication) ). [](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex) location stringRequired Vertex requires you to specify the location you want to serve your models from. Some models may only be available in certain locations. Common locations include: * `us-central1` * `us-west1` * `us-east1` * `us-south1` See the [Vertex AI docs](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations#united-states) for all locations and supported models. [](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex) credentials string | object This field supports any of 3 formats: * A string containing service account credentials in JSON format. * Path to a file containing service account credentials in JSON format. * A JSON object containing service account credentials. See [Authentication](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#authentication) and [Debugging](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#debugging) for more information. **Default: `env.GOOGLE_APPLICATION_CREDENTIALS`** ###### Example: string BAML | | | | --- | --- | | 1 | client Vertex { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location us-central1 | | 6 | // credentials can be a block string containing service account credentials in JSON format | | 7 | credentials #" | | 8 | { | | 9 | "type": "service\_account", | | 10 | "project\_id": "my-project-id", | | 11 | "private\_key\_id": "string", | | 12 | "private\_key": "-----BEGIN PRIVATE KEY-----string\\n-----END PRIVATE KEY-----\\n", | | 13 | "client\_email": "john\_doe@gmail.com", | | 14 | "client\_id": "123456", | | 15 | "auth\_uri": "https://accounts.google.com/o/oauth2/auth", | | 16 | "token\_uri": "https://oauth2.googleapis.com/token", | | 17 | "auth\_provider\_x509\_cert\_url": "https://www.googleapis.com/oauth2/v1/certs", | | 18 | "client\_x509\_cert\_url": "https://www.googleapis.com/robot/v1/metadata/...", | | 19 | "universe\_domain": "googleapis.com" | | 20 | } | | 21 | "# | | 22 | } | | 23 | } | ###### Example: file path In this case, the path is resolved relative to the CWD of your process. BAML | | | | --- | --- | | 1 | client Vertex { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location us-central1 | | 6 | credentials "path/to/credentials.json" | | 7 | } | | 8 | } | ###### Example: JSON object BAML | | | | --- | --- | | 1 | client Vertex { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location us-central1 | | 6 | // credentials can be a block string containing service account credentials in JSON format | | 7 | credentials { | | 8 | type "service\_account", | | 9 | project\_id "my-project-id", | | 10 | private\_key\_id "string", | | 11 | private\_key "-----BEGIN PRIVATE KEY-----string\\n-----END PRIVATE KEY-----\\n", | | 12 | client\_email "john\_doe@gmail.com", | | 13 | client\_id "123456", | | 14 | auth\_uri "https://accounts.google.com/o/oauth2/auth", | | 15 | token\_uri "https://oauth2.googleapis.com/token", | | 16 | auth\_provider\_x509\_cert\_url "https://www.googleapis.com/oauth2/v1/certs", | | 17 | client\_x509\_cert\_url "https://www.googleapis.com/robot/v1/metadata/...", | | 18 | universe\_domain "googleapis.com" | | 19 | } | | 20 | } | | 21 | } | credentials\_content string Since the BAML playground now allows using `gcloud auth application-default login`, to authenticate wih GCP, we will soon be deprecating `credentials_content`. A string containing service account credentials in JSON format. See [Authentication](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#authentication) and [Debugging](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex#debugging) for more information. **Default: `env.GOOGLE_APPLICATION_CREDENTIALS_CONTENT`** ###### Example BAML | | | | --- | --- | | 1 | client Vertex { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | location us-central1 | | 6 | // credentials\_content is a block string containing service account credentials in JSON format | | 7 | credentials\_content #" | | 8 | { | | 9 | "type": "service\_account", | | 10 | "project\_id": "my-project-id", | | 11 | "private\_key\_id": "string", | | 12 | "private\_key": "-----BEGIN PRIVATE KEY-----string\\n-----END PRIVATE KEY-----\\n", | | 13 | "client\_email": "john\_doe@gmail.com", | | 14 | "client\_id": "123456", | | 15 | "auth\_uri": "https://accounts.google.com/o/oauth2/auth", | | 16 | "token\_uri": "https://oauth2.googleapis.com/token", | | 17 | "auth\_provider\_x509\_cert\_url": "https://www.googleapis.com/oauth2/v1/certs", | | 18 | "client\_x509\_cert\_url": "https://www.googleapis.com/robot/v1/metadata/...", | | 19 | "universe\_domain": "googleapis.com" | | 20 | } | | 21 | "# | | 22 | } | | 23 | } | model stringRequired The Google model to use for the request. | Model | Input(s) | Optimized for | | --- | --- | --- | | `gemini-2.5-pro` | Audio, images, videos, and text | Complex reasoning tasks such as code and text generation, text editing, problem solving, data extraction and generation | | `gemini-2.5-flash` | Audio, images, videos, and text | Fast and versatile performance across a diverse variety of tasks | | `gemini-1.0-pro` | Text | Natural language tasks, multi-turn text and code chat, and code generation | See the [Google Model Docs](https://ai.google.dev/gemini-api/docs/models/gemini) for the latest models. headers object Additional headers to send with the request. Example: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | project\_id my-project-id | | 6 | location us-central1 | | 7 | // Additional headers | | 8 | headers { | | 9 | "X-My-Header" "my-value" | | 10 | } | | 11 | } | | 12 | } | query\_params object Query string parameters appended to the request URL. Example (use a Vertex API Key with Express Mode): BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | project\_id my-project-id | | 6 | location us-central1 | | 7 | query\_params { | | 8 | key env.VERTEX\_API\_KEY | | 9 | } | | 10 | } | | 11 | } | When using an API key, omit `credentials` and set `project_id` explicitly. default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. Vertex AI uses `send_url_add_mime_type` by default for images and audio, which ensures MIME type information is included. This may require downloading the content to detect the MIME type if not provided. Provider request parameters --------------------------- These are other parameters that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. Consult the specific provider’s documentation for more information. safetySettings object Safety settings to apply to the request. You can stack different safety settings with a new `safetySettings` header for each one. See the [Google Vertex API Request Docs](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference) for more information on what safety settings can be set. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | project\_id my-project-id | | 6 | location us-central1 | | 7 | | | 8 | safetySettings { | | 9 | category HARM\_CATEGORY\_HATE\_SPEECH | | 10 | threshold BLOCK\_LOW\_AND\_ABOVE | | 11 | method SEVERITY | | 12 | } | | 13 | } | | 14 | } | generationConfig object Generation configurations to apply to the request. See the [Google Vertex API Request Docs](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference) for more information on what properties can be set. BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model gemini-2.5-pro | | 5 | project\_id my-project-id | | 6 | location us-central1 | | 7 | | | 8 | generationConfig { | | 9 | maxOutputTokens 100 | | 10 | temperature 1 | | 11 | } | | 12 | } | | 13 | } | For all other options, see the [official Vertex AI documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/start/quickstarts/quickstart-multimodal) . Publishers Other Than Google ---------------------------- If you are using models from publishers other than Google, such as Llama from Meta, use your project endpoint as the `base_url` in BAML: | | | | --- | --- | | 1 | client VertexLlama { | | 2 | provider vertex-ai | | 3 | options { | | 4 | base\_url "https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT\_ID}/locations/${LOCATION}/endpoints/" | | 5 | location us-central1 | | 6 | } | | 7 | } | For anthropic | | | | --- | --- | | 1 | client VertexClaudeSonnet { | | 2 | provider vertex-ai | | 3 | options { | | 4 | model "claude-sonnet-4" | | 5 | anthropic\_version "${ANTHROPIC\_VERSION}" | | 6 | base\_url "https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT\_ID}/locations/${LOCATION}/publishers/anthropic/models" | | 7 | } | | 8 | } | [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T00%3A55%3A11.460Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # aws-bedrock | Boundary Documentation The `aws-bedrock` provider supports all text-output models available via the [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html) . Quick Start ----------- BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | model "anthropic.claude-3-sonnet-20240229-v1:0" | | 5 | inference\_configuration { | | 6 | max\_tokens 100 | | 7 | temperature 0.7 | | 8 | } | | 9 | // Pass any other parameters that are model specific, | | 10 | // like with claude thinking models. | | 11 | additional\_model\_request\_fields { | | 12 | thinking { | | 13 | type "enabled" | | 14 | budget\_tokens 1030 | | 15 | } | | 16 | } | | 17 | } | | 18 | } | Authentication -------------- AWS Bedrock uses standard AWS authentication methods. We recommend using AWS profiles in development and AWS services’ IAM roles in production, but all of the following are supported: ###### AWS Profile ###### AWS Services (Lambda/ECS/EC2) ###### Environment Variables ###### Explicit Credentials When developing locally, you can use the AWS CLI in combination with profiles to manage your credentials. For example, if you run `aws sso login` with a default profile, BAML will automatically pick up those credentials: ~/.aws/config | | | | --- | --- | | 1 | \[default\] | | 2 | sso\_start\_url = https://your-sso-start-url.awsapps.com/start | | 3 | sso\_region = us-west-2 | | 4 | sso\_account\_id = 123456789012 | | 5 | sso\_role\_name = YourSSORole | | 6 | region = us-west-2 | | 7 | output = json | You can also choose a specific profile by setting the `AWS_PROFILE` environment variable. In the BAML playground, you can set this by clicking the “API Keys” button in the top right (you’ll also need to set `AWS_REGION` to the same region as your profile). The BAML-generated clients will also respect `AWS_PROFILE` if it is set: | | | | --- | --- | | $ | export AWS\_PROFILE=staging-profile | Alternatively, you can also explicitly specify the profile directly in the BAML config itself (this will take precedence over the environment variable): | | | | --- | --- | | $ | \# First, login with SSO | | $ | aws sso login --profile staging-profile | | $ | | | $ | \# Then use the profile in your BAML config | | $ | client MyClient { | | \> | provider aws-bedrock | | \> | options { | | \> | profile "staging-profile" | | \> | model "anthropic.claude-3-sonnet-20240229-v1:0" | | \> | } | | \> | } | Credential Resolution --------------------- BAML follows a specific order when resolving AWS credentials: 1. **Explicit BAML Configuration** BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | access\_key\_id env.MY\_ACCESS\_KEY // Highest precedence | | 5 | secret\_access\_key env.MY\_SECRET\_KEY | | 6 | region "us-east-1" | | 7 | } | | 8 | } | 2. **Environment Variables** | | | | --- | --- | | $ | AWS\_ACCESS\_KEY\_ID | | $ | AWS\_SECRET\_ACCESS\_KEY | | $ | AWS\_SESSION\_TOKEN # Optional | | $ | AWS\_REGION | | $ | AWS\_PROFILE | 3. **AWS Configuration Files** | | | | --- | --- | | 1 | \# ~/.aws/credentials | | 2 | \[default\] | | 3 | aws\_access\_key\_id = ... | | 4 | aws\_secret\_access\_key = ... | | 5 | | | 6 | \# ~/.aws/config | | 7 | \[default\] | | 8 | region = us-east-1 | 4. **Instance Metadata** (EC2/ECS only) * IAM Role credentials * Instance profile credentials ### Important Rules 1. **All or Nothing** * If you provide any credential explicitly, you must provide all required credentials * This won’t work: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | access\_key\_id env.AWS\_ACCESS\_KEY\_ID | | 5 | // Error: secret\_access\_key is required when access\_key\_id is provided | | 6 | model "anthropic.claude-3-sonnet-20240229-v1:0" | | 7 | } | | 8 | } | 2. **Session Token Requirements** * When using `session_token`, you must provide all three: * `access_key_id` * `secret_access_key` * `session_token` 3. **Profile Exclusivity** * When using `profile`, you cannot specify other credentials: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | profile "my-profile" | | 5 | access\_key\_id env.AWS\_ACCESS\_KEY\_ID // Error: Cannot mix profile with explicit credentials | | 6 | model "anthropic.claude-3-sonnet-20240229-v1:0" | | 7 | } | | 8 | } | 4. **Environment Variable Override** * Explicit values in BAML always override environment variables: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | access\_key\_id "AKIAXXXXXXXX" // This will be used even if AWS\_ACCESS\_KEY\_ID exists | | 5 | secret\_access\_key env.AWS\_SECRET\_ACCESS\_KEY | | 6 | model "anthropic.claude-3-sonnet-20240229-v1:0" | | 7 | } | | 8 | } | 5. **AWS Lambda/ECS/EC2** * In AWS services, credentials are automatically provided by the runtime * Explicitly provided credentials will override the automatic ones * Best practice: Don’t specify credentials in AWS environments, use IAM roles instead ### Using Custom Environment Variables You can map your own environment variable names: ###### BAML ###### Environment BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | access\_key\_id env.MY\_CUSTOM\_AWS\_KEY\_ID | | 5 | secret\_access\_key env.MY\_CUSTOM\_AWS\_SECRET | | 6 | session\_token env.MY\_CUSTOM\_AWS\_SESSION // Optional | | 7 | region env.MY\_CUSTOM\_AWS\_REGION | | 8 | model "anthropic.claude-3-sonnet-20240229-v1:0" | | 9 | } | | 10 | } | Cross-Account Access -------------------- To use Bedrock from a different AWS account: 1. **Set up the target account role** (where Bedrock is): | | | | --- | --- | | 1 | { | | 2 | "Version": "2012-10-17", | | 3 | "Statement": \[ |\ | 4 | { |\ | 5 | "Effect": "Allow", |\ | 6 | "Principal": { |\ | 7 | "AWS": "arn:aws:iam::SOURCE\_ACCOUNT\_ID:root" |\ | 8 | }, |\ | 9 | "Action": "sts:AssumeRole", |\ | 10 | "Condition": { |\ | 11 | "StringEquals": { |\ | 12 | "sts:ExternalId": "YOUR\_EXTERNAL\_ID" |\ | 13 | } |\ | 14 | } |\ | 15 | } |\ | 16 | \] | | 17 | } | 2. **Configure the source account** (where your application runs): ###### AWS Profile ###### Environment Variables ###### ClientRegistry | | | | --- | --- | | 1 | \# ~/.aws/config | | 2 | \[profile target-role\] | | 3 | role\_arn = arn:aws:iam::TARGET\_ACCOUNT\_ID:role/ROLE\_NAME | | 4 | source\_profile = default | | 5 | region = us-east-1 | BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | profile "target-role" | | 5 | model "anthropic.claude-3-sonnet-20240229-v1:0" | | 6 | } | | 7 | } | IAM Permissions --------------- ### Basic Permissions The following IAM permissions are required for basic Bedrock access: | | | | --- | --- | | 1 | { | | 2 | "Version": "2012-10-17", | | 3 | "Statement": \[ |\ | 4 | { |\ | 5 | "Effect": "Allow", |\ | 6 | "Action": \[ |\ | 7 | "bedrock:InvokeModel", |\ | 8 | "bedrock:InvokeModelWithResponseStream" |\ | 9 | \], |\ | 10 | "Resource": "arn:aws:bedrock:\*:\*:model/\*" |\ | 11 | } |\ | 12 | \] | | 13 | } | ### Additional Permissions Depending on your setup, you might need additional permissions: ###### Cross-Account Access ###### VPC Endpoints ###### Resource-Based See [Cross-Account Access](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock#cross-account-access) section for the required trust relationships and permissions. ### Best Practices * Follow the principle of least privilege * Use resource-based policies when possible * Consider using AWS Organizations SCPs for enterprise-wide controls * Regularly audit IAM permissions using AWS IAM Access Analyzer Configuration Options --------------------- ### BAML-specific request `options` These unique parameters (aka `options`) are modify the API request sent to the provider. You can use this to modify the `region`, `access_key_id`, `secret_access_key`, and `session_token` sent to the provider. region string The AWS region to use. **Default: `AWS_REGION` environment variable** access\_key\_id string AWS access key ID. **Default: `AWS_ACCESS_KEY_ID` environment variable** secret\_access\_key string AWS secret access key. **Default: `AWS_SECRET_ACCESS_KEY` environment variable** session\_token string Temporary session token. Required if using temporary credentials. **Default: `AWS_SESSION_TOKEN` environment variable** profile string AWS profile name from credentials file. **Default: `AWS_PROFILE` environment variable** endpoint\_url string AWS endpoint URL. Useful for using a VPC endpoint. default\_role string The role to use if the role is not in the allowed\_roles. **Default: `"user"` usually, but some models like OpenAI’s `gpt-5` will use `"system"`** Picked the first role in `allowed_roles` if not “user”, otherwise “user”. allowed\_roles string\[\] Which roles should we forward to the API? **Default: `["system", "user", "assistant"]` usually, but some models like OpenAI’s `o1-mini` will use `["user", "assistant"]`** When building prompts, any role not in this list will be set to the `default_role`. remap\_roles map A mapping to transform role names before sending to the API. **Default: `{}`** (no remapping) For google-ai provider, the default is: `{ "assistant": "model" }` This allows you to use standard role names in your prompts (like “user”, “assistant”, “system”) but send different role names to the API. The remapping happens after role validation and default role assignment. **Example:** | | | | --- | --- | | 1 | { | | 2 | "user": "human", | | 3 | "assistant": "ai", | | 4 | } | With this configuration, `{{ _.role("user") }}` in your prompt will result in a message with role “human” being sent to the API. allowed\_role\_metadata string\[\] Which role metadata should we forward to the API? **Default: `[]`** For example you can set this to `["foo", "bar"]` to forward the cache policy to the API. If you do not set `allowed_role_metadata`, we will not forward any role metadata to the API even if it is set in the prompt. Then in your prompt you can use something like: | | | | --- | --- | | 1 | client Foo { | | 2 | provider openai | | 3 | options { | | 4 | allowed\_role\_metadata: \["foo", "bar"\] | | 5 | } | | 6 | } | | 7 | | | 8 | client FooWithout { | | 9 | provider openai | | 10 | options { | | 11 | } | | 12 | } | | 13 | template\_string Foo() #" | | 14 | {{ \_.role('user', foo={"type": "ephemeral"}, bar="1", cat=True) }} | | 15 | This will be have foo and bar, but not cat metadata. But only for Foo, not FooWithout. | | 16 | {{ \_.role('user') }} | | 17 | This will have none of the role metadata for Foo or FooWithout. | | 18 | "# | You can use the playground to see the raw curl request to see what is being sent to the API. supports\_streaming boolean Whether the internal LLM client should use the streaming API. **Default: `true`** Then in your prompt you can use something like: | | | | --- | --- | | 1 | client MyClientWithoutStreaming { | | 2 | provider anthropic | | 3 | options { | | 4 | model claude-3-5-haiku-20241022 | | 5 | api\_key env.ANTHROPIC\_API\_KEY | | 6 | max\_tokens 1000 | | 7 | supports\_streaming false | | 8 | } | | 9 | } | | 10 | | | 11 | function MyFunction() -> string { | | 12 | client MyClientWithoutStreaming | | 13 | prompt #"Write a short story"# | | 14 | } | | | | | --- | --- | | 1 | \# This will be streamed from your python code perspective, | | 2 | \# but under the hood it will call the non-streaming HTTP API | | 3 | \# and then return a streamable response with a single event | | 4 | b.stream.MyFunction() | | 5 | | | 6 | \# This will work exactly the same as before | | 7 | b.MyFunction() | finish\_reason\_allow\_list string\[\] Which finish reasons are allowed? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is not in the allow list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["stop"]` to only allow the stop finish reason, all other finish reasons (e.g. `length`) will treated as failures that PREVENT fallbacks and retries (similar to parsing errors). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason allow list will only allow the stop finish reason | | 7 | finish\_reason\_allow\_list \["stop"\] | | 8 | } | | 9 | } | finish\_reason\_deny\_list string\[\] Which finish reasons are denied? **Default: `null`** version 0.73.0 onwards: This is case insensitive. Will raise a `BamlClientFinishReasonError` if the finish reason is in the deny list. See [Exceptions](https://docs.boundaryml.com/guide/baml-basics/error-handling#bamlclientfinishreasonerror) for more details. Note, only one of `finish_reason_allow_list` or `finish_reason_deny_list` can be set. For example you can set this to `["length"]` to stop the function from continuing if the finish reason is `length`. (e.g. LLM was cut off because it was too long). Then in your code you can use something like: | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5-mini" | | 5 | api\_key env.OPENAI\_API\_KEY | | 6 | // Finish reason deny list will allow all finish reasons except length | | 7 | finish\_reason\_deny\_list \["length"\] | | 8 | } | | 9 | } | Modular API ----------- * `b.request` returns a fully signed SigV4 `HTTPRequest` pointing at the Converse API. * Forward the request as-is. Do not mutate the headers; they already include `Authorization`, `X-Amz-Date`, and (if needed) `X-Amz-Security-Token`. * Send the request immediately after building it. The signature is computed at request time, so rebuilding gives you a fresh signature. * Streaming modular calls are not yet supported for Bedrock. TypeScript | | | | --- | --- | | 1 | import { SignatureV4 } from "@aws-sdk/signature-v4" | | 2 | import { defaultProvider } from "@aws-sdk/credential-provider-node" | | 3 | import { HttpRequest } from "@aws-sdk/protocol-http" | | 4 | import { b } from 'baml\_client' | | 5 | | | 6 | async function callBedrock() { | | 7 | const req = await b.request.ExtractResume("John Doe \| Software Engineer \| BSc in CS") | | 8 | | | 9 | const body = req.body.json() as any | | 10 | const bodyString = JSON.stringify(body) | | 11 | const url = new URL(req.url) | | 12 | const region = (req.client\_details.options?.region as string) ?? process.env.AWS\_REGION ?? "us-east-1" | | 13 | | | 14 | const signer = new SignatureV4({ | | 15 | service: "bedrock", | | 16 | region, | | 17 | credentials: defaultProvider(), | | 18 | }) | | 19 | | | 20 | const unsigned = new HttpRequest({ | | 21 | protocol: url.protocol, | | 22 | hostname: url.hostname, | | 23 | path: url.pathname, | | 24 | method: req.method, | | 25 | headers: { | | 26 | ...req.headers, | | 27 | host: url.host, | | 28 | "content-type": "application/json", | | 29 | }, | | 30 | body: bodyString, | | 31 | }) | | 32 | | | 33 | const signed = await signer.sign(unsigned) | | 34 | | | 35 | const res = await fetch(req.url, { | | 36 | method: req.method, | | 37 | headers: signed.headers as Record, | | 38 | body: bodyString, | | 39 | }) | | 40 | | | 41 | if (!res.ok) { | | 42 | throw new Error(\`Bedrock request failed: ${res.status}\`) | | 43 | } | | 44 | | | 45 | const payload = await res.json() | | 46 | const message = payload.output.message.content.find((block: any) => block.text)?.text ?? '' | | 47 | | | 48 | return b.parse.ExtractResume(message) | | 49 | } | Python | | | | --- | --- | | 1 | import json | | 2 | import requests | | 3 | from botocore.auth import SigV4Auth | | 4 | from botocore.awsrequest import AWSRequest | | 5 | import boto3 | | 6 | from baml\_client import b | | 7 | | | 8 | def call\_bedrock(): | | 9 | req = b.request.ExtractResume("John Doe \| Software Engineer \| BSc in CS") | | 10 | | | 11 | body = req.body.json() | | 12 | body\_bytes = json.dumps(body).encode("utf-8") | | 13 | | | 14 | session = boto3.Session() | | 15 | credentials = session.get\_credentials().get\_frozen\_credentials() | | 16 | region = req.client\_details.options.get("region") or session.region\_name or "us-east-1" | | 17 | | | 18 | aws\_request = AWSRequest( | | 19 | method=req.method, | | 20 | url=req.url, | | 21 | data=body\_bytes, | | 22 | headers=dict(req.headers), | | 23 | ) | | 24 | SigV4Auth(credentials, "bedrock", region).add\_auth(aws\_request) | | 25 | | | 26 | response = requests.post( | | 27 | req.url, | | 28 | headers=dict(aws\_request.headers.items()), | | 29 | data=body\_bytes, | | 30 | ) | | 31 | response.raise\_for\_status() | | 32 | | | 33 | payload = response.json() | | 34 | message = payload\["output"\]\["message"\]\["content"\]\[0\]\["text"\] | | 35 | return b.parse.ExtractResume(message) | ### `media_url_handler` Controls how media URLs are processed before sending to the provider. This allows you to override the default behavior for handling images, audio, PDFs, and videos. | | | | --- | --- | | 1 | client MyClient { | | 2 | provider openai | | 3 | options { | | 4 | media\_url\_handler { | | 5 | image "send\_base64" // Options: send\_base64 \| send\_url \| send\_url\_add\_mime\_type \| send\_base64\_unless\_google\_url | | 6 | audio "send\_url" | | 7 | pdf "send\_url\_add\_mime\_type" | | 8 | video "send\_url" | | 9 | } | | 10 | } | | 11 | } | #### Options Each media type can be configured with one of these modes: * **`send_base64`** - Always download URLs and convert to base64 data URIs * **`send_url`** - Pass URLs through unchanged to the provider * **`send_url_add_mime_type`** - Ensure MIME type is present (may require downloading to detect) * **`send_base64_unless_google_url`** - Only process non-gs:// URLs (keep Google Cloud Storage URLs as-is) #### Provider Defaults If not specified, each provider uses these defaults: | Provider | Image | Audio | PDF | Video | | --- | --- | --- | --- | --- | | OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | | Anthropic | `send_url` | `send_url` | `send_base64` | `send_url` | | Google AI | `send_base64_unless_google_url` | `send_url` | `send_url` | `send_url` | | Vertex AI | `send_url_add_mime_type` | `send_url_add_mime_type` | `send_url` | `send_url` | | AWS Bedrock | `send_base64` | `send_base64` | `send_base64` | `send_url` | | Azure OpenAI | `send_url` | `send_base64` | `send_url` | `send_url` | #### When to Use * **Use `send_base64`** when your provider doesn’t support external URLs and you need to embed media content * **Use `send_url`** when your provider handles URL fetching and you want to avoid the overhead of base64 conversion * **Use `send_url_add_mime_type`** when your provider requires MIME type information (e.g., Vertex AI) * **Use `send_base64_unless_google_url`** when working with Google Cloud Storage and want to preserve gs:// URLs URL fetching happens at request time and may add latency. Consider caching or pre-converting frequently used media when using `send_base64` mode. AWS Bedrock converts most media to base64 by default (`send_base64` for images, audio, and PDFs). Consider using S3 presigned URLs with `send_url` mode for large files to avoid base64 overhead. Provider request parameters --------------------------- These are other `options` that are passed through to the provider, without modification by BAML. For example if the request has a `temperature` field, you can define it in the client here so every call has that set. Consult the specific provider’s documentation for more information. model (or model\_id) stringRequired The model to use. | Model | Description | | --- | --- | #### Anthropic Claude (Latest Generation) * `anthropic.claude-opus-4-1-20250805-v1:0` - Most powerful coding * `anthropic.claude-sonnet-4-20250514-v1:0` - Best default, 1M context available * `anthropic.claude-3-5-haiku-20241022-v1:0` - Fast and efficient #### Meta Llama (Latest Generation) * `meta.llama4-maverick-17b-instruct-v1:0` - Latest Llama 4 * `meta.llama3-3-70b-instruct-v1:0` - Enhanced Llama 3.3 Run `aws bedrock list-foundation-models | jq '.modelSummaries.[].modelId'` to see available models. Note: You must [request model access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) before use. inference\_configuration object Model-specific inference parameters. See [AWS Bedrock documentation](https://docs.rs/aws-sdk-bedrockruntime/latest/aws_sdk_bedrockruntime/types/struct.InferenceConfiguration.html) . BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider aws-bedrock | | 3 | options { | | 4 | inference\_configuration { | | 5 | max\_tokens 1000 | | 6 | temperature 1.0 | | 7 | top\_p 0.8 | | 8 | } | | 9 | } | | 10 | } | Troubleshooting --------------- ### Common Errors ###### AccessDeniedException | | | | --- | --- | | 1 | { | | 2 | "Error": "AccessDeniedException", | | 3 | "Message": "User is not authorized to perform: bedrock:InvokeModel" | | 4 | } | **Solution:** * Check IAM permissions * Verify execution role permissions in Lambda/ECS * Ensure credentials have Bedrock access ###### UnrecognizedClientException | | | | --- | --- | | 1 | { | | 2 | "Error": "UnrecognizedClientException", | | 3 | "Message": "The security token included in the request is invalid" | | 4 | } | **Solution:** * Verify credentials are set correctly * Check if session token is required and provided * Ensure credentials haven’t expired ###### ValidationException (Region) | | | | --- | --- | | 1 | { | | 2 | "Error": "ValidationException", | | 3 | "Message": "Model is not supported in this Region" | | 4 | } | **Solution:** * Check model availability in your region * Request model access if needed * Consider using a different region ###### ValidationException (Model Access) | | | | --- | --- | | 1 | { | | 2 | "Error": "ValidationException", | | 3 | "Message": "Account is not authorized to use model" | | 4 | } | **Solution:** * Request model access through AWS Console * Wait for approval (1-2 business days) * Verify model ID is correct ### Environment-Specific Setup ###### Lambda * Set appropriate memory and timeout * Configure execution role with Bedrock permissions * Consider VPC endpoints for private subnets ###### ECS/EC2 * Use task roles (ECS) or instance profiles (EC2) * Configure VPC endpoints if needed * Check security group outbound rules ###### Local Development * Set AWS credentials in environment or config files * Use `AWS_PROFILE` to manage multiple profiles * Run `aws configure list` to verify configuration [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Claude Code | Boundary Documentation Add a `CLAUDE.md` file to your project with [these BAML instructions](https://gist.github.com/aaronvg/75596a0063588440d47f5db1361c8a5f) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # Client Registry | Boundary Documentation If you need to modify the model / parameters for an LLM client at runtime, you can modify the `ClientRegistry` for any specified function. **Quick Override**: If you just need to change which client a function uses, you can use the simpler [`client` option](https://docs.boundaryml.com/ref/baml_client/client-option) instead of creating a full `ClientRegistry`: | | | | --- | --- | | 1 | result = await b.ExtractResume("...", baml\_options={"client": "GPT4"}) | ###### Python ###### TypeScript ###### Ruby ###### Go ###### OpenAPI | | | | --- | --- | | 1 | import os | | 2 | from baml\_py import ClientRegistry | | 3 | | | 4 | async def run(): | | 5 | cr = ClientRegistry() | | 6 | # Creates a new client | | 7 | cr.add\_llm\_client(name='MyAmazingClient', provider='openai', options={ | | 8 | "model": "gpt-5-mini", | | 9 | "temperature": 0.7, | | 10 | "api\_key": os.environ.get('OPENAI\_API\_KEY') | | 11 | }) | | 12 | | | 13 | # Creates a client using the OpenAI Responses API | | 14 | cr.add\_llm\_client(name='MyResponsesClient', provider='openai-responses', options={ | | 15 | "model": "gpt-4.1", | | 16 | "api\_key": os.environ.get('OPENAI\_API\_KEY') | | 17 | }) | | 18 | | | 19 | # Sets MyAmazingClient as the client | | 20 | cr.set\_primary('MyAmazingClient') | | 21 | | | 22 | # ExtractResume will now use MyAmazingClient as the calling client | | 23 | res = await b.ExtractResume("...", { "client\_registry": cr }) | ### The `set_primary` Method The `set_primary` method can be called with either one of the clients added to the `ClientRegistry` at runtime using `add_llm_client` or a client defined in BAML files. `set_primary` simply selects a client from all the available clients in the `ClientRegistry`, but it does not mean there will be a “secondary” client used anywhere. You can, however, define a fallback client and then use `ClientRegistry` to set that client as the calling client for BAML functions. Here’s a simple example: example.baml | | | | --- | --- | | 1 | function ExtractResume(input: string) -> Resume { | | 2 | client "openai/gpt-5-mini" // Uses GPT-5 Mini by default | | 3 | prompt #" | | 4 | Extract from this content: {{ resume }} | | 5 | | | 6 | {{ ctx.output\_format }} | | 7 | "# | | 8 | } | | 9 | | | 10 | // This client uses GPT-5 first and if it fails it will use Opus 4 as a fallback. | | 11 | client GptOpusFallback { | | 12 | provider fallback | | 13 | options { | | 14 | strategy \["openai/gpt-5", "anthropic/claude-opus-4-1-20250805"\] | | 15 | } | | 16 | } | Then, in your code, you can use the `ClientRegistry` to set the `GptOpusFallback` at runtime, which will try to use GPT 5 and if it fails Opus 4: ###### Python ###### TypeScript ###### Ruby ###### Go | | | | --- | --- | | 1 | cr = ClientRegistry() | | 2 | cr.set\_primary("GptOpusFallback") | | 3 | res = await b.ExtractResume("...", { "client\_registry": cr }) | Now the calling client will be `GptOpusFallback`, **nothing else**. ClientRegistry Interface ------------------------ Note: `ClientRegistry` is imported from `baml_py` in Python and `@boundaryml/baml` in TypeScript, not `baml_client`. As we mature `ClientRegistry`, we will add a more type-safe and ergonomic interface directly in `baml_client`. See [Github issue #766](https://github.com/BoundaryML/baml/issues/766) . Methods use `snake_case` in Python and `camelCase` in TypeScript. ### add\_llm\_client / addLlmClient A function to add an LLM client to the registry. name stringRequired The name of the client. Using the exact same name as a client also defined in .baml files overwrites the existing client whenever the ClientRegistry is used. provider stringRequired This configures which provider to use. The provider is responsible for handling the actual API calls to the LLM service. The provider is a required field. The configuration modifies the URL request BAML runtime makes. | Provider Name | Docs | Notes | | --- | --- | --- | | `anthropic` | [Anthropic](https://docs.boundaryml.com/ref/llm-client-providers/anthropic) | Supports [/v1/messages](https://docs.anthropic.com/en/api/messages)
endpoint | | `aws-bedrock` | [AWS Bedrock](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock) | Supports [Converse](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)
and [ConverseStream](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)
endpoint | | `google-ai` | [Google AI](https://docs.boundaryml.com/ref/llm-client-providers/google-ai-gemini) | Supports Google AI’s [generateContent](https://ai.google.dev/api/generate-content)
and [streamGenerateContent](https://ai.google.dev/api/generate-content#method:-models.streamgeneratecontent)
endpoints | | `vertex-ai` | [Vertex AI](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex) | Supports Vertex’s [generateContent](https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.publishers.models/generateContent)
and [streamGenerateContent](https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.publishers.models/streamGenerateContent)
endpoints | | `openai` | [OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai) | Supports [/chat/completions](https://platform.openai.com/docs/api-reference/chat)
endpoint | | `openai-responses` | [OpenAI Responses API](https://docs.boundaryml.com/ref/llm-client-providers/open-ai-responses-api) | Supports OpenAI’s most advanced [/responses](https://platform.openai.com/docs/api-reference/responses)
endpoint | | `azure-openai` | [Azure OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai-from-azure) | Supports Azure’s [/chat/completions](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions)
endpoint | | `openai-generic` | [OpenAI (generic)](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) | Any other provider that supports OpenAI’s `/chat/completions` endpoint | A non-exhaustive list of providers you can use with `openai-generic`: | Inference Provider | Docs | | --- | --- | | Azure AI Foundry | [Azure AI Foundry](https://docs.boundaryml.com/ref/llm-client-providers/azure-ai-foundary) | | Groq | [Groq](https://docs.boundaryml.com/ref/llm-client-providers/groq) | | Hugging Face | [Hugging Face](https://docs.boundaryml.com/ref/llm-client-providers/huggingface) | | Keywords AI | [Keywords AI](https://docs.boundaryml.com/ref/llm-client-providers/keywordsai) | | Litellm | [Litellm](https://docs.boundaryml.com/ref/llm-client-providers/litellm) | | LM Studio | [LM Studio](https://docs.boundaryml.com/ref/llm-client-providers/lmstudio) | | Ollama | [Ollama](https://docs.boundaryml.com/ref/llm-client-providers/ollama) | | OpenRouter | [OpenRouter](https://docs.boundaryml.com/ref/llm-client-providers/openrouter) | | Vercel AI Gateway | [Vercel AI Gateway](https://docs.boundaryml.com/ref/llm-client-providers/vercel-ai-gateway) | | TogetherAI | [TogetherAI](https://docs.boundaryml.com/ref/llm-client-providers/together) | | Unify AI | [Unify AI](https://docs.boundaryml.com/ref/llm-client-providers/unify) | | vLLM | [vLLM](https://docs.boundaryml.com/ref/llm-client-providers/vllm) | We also have some special providers that allow composing clients together: | Provider Name | Docs | Notes | | --- | --- | --- | | `fallback` | [Fallback](https://docs.boundaryml.com/ref/llm-client-strategies/fallback) | Used to chain models conditional on failures | | `round-robin` | [Round Robin](https://docs.boundaryml.com/ref/llm-client-strategies/round-robin) | Used to load balance | options dict\[str, Any\]Required These vary per provider. Please see provider specific documentation for more information. Generally they are pass through options to the POST request made to the LLM. retry\_policy string The name of a retry policy that is already defined in a .baml file. See [Retry Policies](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy) . ### set\_primary / setPrimary This sets the client for the function to use. (i.e. replaces the `client` property in a function) The name “primary” does not imply that there will be a “secondary” or fallback client used anywhere. It simply means that you choose one client from all the available clients in your `ClientRegistry`. See [The `set_primary` Method](https://docs.boundaryml.com/ref/baml_client/client-registry#the-set_primary-method) section for more details. name stringRequired The name of the client to use. This can be a new client that was added with `add_llm_client` or an existing client that is already in a .baml file. [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) --- # LLM Clients (client) | Boundary Documentation Clients are used to configure how LLMs are called, like so: BAML | | | | --- | --- | | 1 | function MakeHaiku(topic: string) -> string { | | 2 | client "openai/gpt-4o" | | 3 | prompt #" | | 4 | Write a haiku about {{ topic }}. | | 5 | "# | | 6 | } | `/` shorthand for the Named Client version of `MyClient`: BAML | | | | --- | --- | | 1 | client MyClient { | | 2 | provider "openai" | | 3 | options { | | 4 | model "gpt-5" | | 5 | // api\_key defaults to env.OPENAI\_API\_KEY | | 6 | } | | 7 | } | | 8 | | | 9 | function MakeHaiku(topic: string) -> string { | | 10 | client MyClient | | 11 | prompt #" | | 12 | Write a haiku about {{ topic }}. | | 13 | "# | | 14 | } | Consult the [provider documentation](https://docs.boundaryml.com/ref/llm-client-providers/overview#fields) for a list of supported providers and models, and the default options. If you want to override options like `api_key` to use a different environment variable, or you want to point `base_url` to a different endpoint, you should use the latter form. If you want to specify which client to use at runtime, in your Python/TS/Ruby code, you can use the [client registry](https://docs.boundaryml.com/ref/baml_client/client-registry) to do so. This can come in handy if you’re trying to, say, send 10% of your requests to a different model. Fields ------ provider stringRequired This configures which provider to use. The provider is responsible for handling the actual API calls to the LLM service. The provider is a required field. The configuration modifies the URL request BAML runtime makes. | Provider Name | Docs | Notes | | --- | --- | --- | | `anthropic` | [Anthropic](https://docs.boundaryml.com/ref/llm-client-providers/anthropic) | Supports [/v1/messages](https://docs.anthropic.com/en/api/messages)
endpoint | | `aws-bedrock` | [AWS Bedrock](https://docs.boundaryml.com/ref/llm-client-providers/aws-bedrock) | Supports [Converse](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)
and [ConverseStream](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)
endpoint | | `google-ai` | [Google AI](https://docs.boundaryml.com/ref/llm-client-providers/google-ai-gemini) | Supports Google AI’s [generateContent](https://ai.google.dev/api/generate-content)
and [streamGenerateContent](https://ai.google.dev/api/generate-content#method:-models.streamgeneratecontent)
endpoints | | `vertex-ai` | [Vertex AI](https://docs.boundaryml.com/ref/llm-client-providers/google-vertex) | Supports Vertex’s [generateContent](https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.publishers.models/generateContent)
and [streamGenerateContent](https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.publishers.models/streamGenerateContent)
endpoints | | `openai` | [OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai) | Supports [/chat/completions](https://platform.openai.com/docs/api-reference/chat)
endpoint | | `openai-responses` | [OpenAI Responses API](https://docs.boundaryml.com/ref/llm-client-providers/open-ai-responses-api) | Supports OpenAI’s most advanced [/responses](https://platform.openai.com/docs/api-reference/responses)
endpoint | | `azure-openai` | [Azure OpenAI](https://docs.boundaryml.com/ref/llm-client-providers/open-ai-from-azure) | Supports Azure’s [/chat/completions](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions)
endpoint | | `openai-generic` | [OpenAI (generic)](https://docs.boundaryml.com/ref/llm-client-providers/openai-generic) | Any other provider that supports OpenAI’s `/chat/completions` endpoint | A non-exhaustive list of providers you can use with `openai-generic`: | Inference Provider | Docs | | --- | --- | | Azure AI Foundry | [Azure AI Foundry](https://docs.boundaryml.com/ref/llm-client-providers/azure-ai-foundary) | | Groq | [Groq](https://docs.boundaryml.com/ref/llm-client-providers/groq) | | Hugging Face | [Hugging Face](https://docs.boundaryml.com/ref/llm-client-providers/huggingface) | | Keywords AI | [Keywords AI](https://docs.boundaryml.com/ref/llm-client-providers/keywordsai) | | Litellm | [Litellm](https://docs.boundaryml.com/ref/llm-client-providers/litellm) | | LM Studio | [LM Studio](https://docs.boundaryml.com/ref/llm-client-providers/lmstudio) | | Ollama | [Ollama](https://docs.boundaryml.com/ref/llm-client-providers/ollama) | | OpenRouter | [OpenRouter](https://docs.boundaryml.com/ref/llm-client-providers/openrouter) | | Vercel AI Gateway | [Vercel AI Gateway](https://docs.boundaryml.com/ref/llm-client-providers/vercel-ai-gateway) | | TogetherAI | [TogetherAI](https://docs.boundaryml.com/ref/llm-client-providers/together) | | Unify AI | [Unify AI](https://docs.boundaryml.com/ref/llm-client-providers/unify) | | vLLM | [vLLM](https://docs.boundaryml.com/ref/llm-client-providers/vllm) | We also have some special providers that allow composing clients together: | Provider Name | Docs | Notes | | --- | --- | --- | | `fallback` | [Fallback](https://docs.boundaryml.com/ref/llm-client-strategies/fallback) | Used to chain models conditional on failures | | `round-robin` | [Round Robin](https://docs.boundaryml.com/ref/llm-client-strategies/round-robin) | Used to load balance | options dict\[str, Any\]Required These vary per provider. Please see provider specific documentation for more information. Generally they are pass through options to the POST request made to the LLM. retry\_policy The name of the retry policy. See [Retry Policy](https://docs.boundaryml.com/ref/llm-client-strategies/retry-policy) . [![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)![Logo](https://app.buildwithfern.com/_next/image?url=https%3A%2F%2Ffiles.buildwithfern.com%2Fhttps%3A%2F%2Fboundary.docs.buildwithfern.com%2F2026-02-19T14%3A19%3A05.366Z%2Fassets%2Ffavicon.ico&w=32&q=100)](https://docs.boundaryml.com/) ---