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