Skip to main content
BAML (Basically A Made-up Language) is a domain-specific language designed for building type-safe AI applications. It provides a clean syntax for defining functions, types, and configurations that bridge your application code with AI models.

Language Fundamentals

File Structure

BAML code is organized into .baml files within your baml_src directory. Each file can contain:
  • Functions: AI function definitions with prompts and return types
  • Classes: Structured data types for inputs and outputs
  • Enums: Enumerated values for classification tasks
  • Clients: LLM client configurations
  • Tests: Test cases for your AI functions
  • Template Strings: Reusable prompt templates
  • Retry Policies: Retry strategies for client requests

Comments

Single-line comments
//
Standard single-line comments that are ignored during compilation.
// This is a comment
function MyFunc() -> string { } // Trailing comment
Docstrings
///
Documentation comments that are carried through to generated code.
/// This docstring appears in generated types
class Person {
  /// The person's full name
  name string
}
Block comments
{# #}
Multi-line comments within block strings.
prompt #"
  My string content
  {# This is a comment inside a block string #}
  More content
"#

String Syntax

Quoted Strings

Standard double-quoted strings for inline values:
"Hello World"
"Line with \n escape"
Quoted strings cannot contain template variables. Use block strings for templating.

Unquoted Strings

Simple strings without quotes for configuration values:
model gpt-4o
provider openai
Restrictions: Cannot contain quotes, @, , #, (), [], commas, or newlines.

Block Strings

Multi-line strings with automatic dedentation and Jinja templating support:
#"
  This is a block string
  It preserves formatting
  {{ variable_name }}
"#
Block strings are dedented automatically and stripped of first/last newlines.

Escape Sequences

To include "# within a block string, use different hash counts:
###"
  This contains #"escaped quotes"#
"###

Type System

BAML supports a rich type system for defining inputs and outputs:
TypeExampleDescription
stringname stringText data
intage intInteger numbers
floatscore floatDecimal numbers
boolisActive boolBoolean values
nullvalue nullNull value
enumstatus StatusUser-defined enums
classuser UserUser-defined classes
imagephoto imageImage media
audioclip audioAudio media
videorecording videoVideo media
pdfdocument pdfPDF documents
Type?age int?Optional type
Type[]tags string[]Array/list
Type1 | Type2int | stringUnion types
map<K, V>map<string, int>Key-value maps
Literals"red" | "blue"Literal values

Type Aliases

Define reusable type aliases:
type Graph = map<string, string[]>
type JsonValue = int | float | bool | string | null | JsonValue[] | map<string, JsonValue>

Core Language Elements

Function

Define AI functions with typed inputs and outputs:
function ExtractInfo(text: string) -> Person {
  client GPT4
  prompt #"
    Extract person information from:
    {{ text }}
    
    {{ ctx.output_format }}
  "#
}
Learn more →

Class

Define structured data types:
class Person {
  name string
  age int?
  email string @description("Contact email")
}
Learn more →

Enum

Define enumerated values:
enum Priority {
  Low
  Medium
  High @description("Urgent priority")
}
Learn more →

Client

Configure LLM clients:
client<llm> GPT4 {
  provider openai
  options {
    model gpt-4o
    api_key env.OPENAI_API_KEY
  }
}
Learn more →

Test

Define test cases:
test TestExtraction {
  functions [ExtractInfo]
  args {
    text "John Doe, age 30"
  }
}
Learn more →

Naming Conventions

ElementConventionExample
FunctionsPascalCase (must start with capital)ExtractData
ClassesPascalCaseUserProfile
EnumsPascalCaseStatus
Propertiessnake_case or camelCaseuser_name, userName
Enum valuesPascalCaseActive, Inactive
ClientsPascalCaseGPT4Turbo

Environment Variables

Access environment variables using the env. prefix:
client<llm> MyClient {
  provider openai
  options {
    api_key env.OPENAI_API_KEY
    base_url env.CUSTOM_BASE_URL
  }
}

Jinja Templating

BAML uses Jinja syntax for dynamic prompt generation:
prompt #"
  {{ ctx.output_format }}
  
  {% if condition %}
    Conditional content
  {% endif %}
  
  {% for item in items %}
    - {{ item }}
  {% endfor %}
  
  {{ _.role('user') }}
  {{ input_text }}
"#

Special Variables

VariableDescription
ctx.output_formatAuto-generated format instructions
ctx.clientCurrent client and model name
_.role(name)Set message role for chat models

Best Practices

  1. Type Safety: Always use explicit types for function parameters and return values
  2. Reusability: Use template strings for common prompt patterns
  3. Documentation: Add docstrings to classes and properties for better generated code
  4. Validation: Use tests to validate AI function behavior
  5. Error Handling: Leverage optional types (?) for fields that may not always be present
  6. Composition: Prefer composition over complex nested structures

Unsupported Features

  • any/json type - Use specific types or dynamic types instead
  • datetime - Use string with description specifying format
  • duration - Use string with ISO8601 format description
  • Set - Use arrays ([]) instead
  • Tuple - Use classes instead
  • Class inheritance - Use composition pattern

Next Steps

Functions

Define AI functions with prompts and types

Classes

Create structured data types

Enums

Define classification values

Clients

Configure LLM providers

Build docs developers (and LLMs) love