# Baml

> Use when working with BAML (BoundaryML) - a domain-specific language for type-safe LLM function calls, structured extraction, prompt engineering, or building AI applications with guaranteed type safety across Python, TypeScript, Ruby, and Go

- Skill: `ferymad/baml` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ferymad/baml`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ferymad/baml/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Ferymad (https://skillmd.com/u/ferymad)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/ferymad/baml

---


# BAML (BoundaryML) Skill

> BAML is a domain-specific language for building AI applications with type-safe LLM calls. It provides guaranteed type safety, automatic JSON parsing, retry logic, and streaming support across multiple languages.

## When to Use This Skill

Use this skill when:
- Building AI applications with structured LLM outputs
- Need type-safe LLM function calls across Python/TypeScript/Ruby/Go
- Implementing complex prompt engineering with validation
- Extracting structured data from unstructured text (resumes, documents, etc.)
- Need streaming responses with partial parsing
- Working with multiple LLM providers (OpenAI, Anthropic, Google AI, etc.)
- Switching between LLM providers without code changes
- Testing LLM functions with the VSCode Playground
- Handling classification, extraction, or generation tasks with LLMs

## Quick Reference

### 1. Define a BAML Function

```baml
// baml_src/extraction.baml
class Resume {
  name string
  skills string[]
  education Education[]
  seniority SeniorityLevel
}

class Education {
  school string
  degree string
  year int
}

enum SeniorityLevel {
  JUNIOR
  MID
  SENIOR
  STAFF
}

function ExtractResume(resume_text: string) -> Resume {
  client "openai/gpt-4o"
  prompt #"
    Extract the following information from this resume:
    {{ resume_text }}

    Classify seniority as:
    - JUNIOR: 0-2 years experience
    - MID: 2-5 years experience
    - SENIOR: 5-10 years experience
    - STAFF: 10+ years experience
  "#
}
```

### 2. Generate Client Code

```bash
baml-cli generate
```

This generates type-safe client code in your language with:
- Automatic JSON parsing and validation
- Retry logic and error handling
- Streaming support
- Type safety and autocomplete

### 3. Call from Your Code

**Python:**
```python
from baml_client import b
from baml_client.types import Resume

# Async client
resume = await b.ExtractResume(resume_text="John Doe, Python expert...")

# Sync client
resume = b.sync.ExtractResume(resume_text="John Doe, Python expert...")

# Streaming
stream = b.stream.ExtractResume(resume_text="...")
async for partial in stream:
    print(partial.name)  # Type-safe partial results
```

**TypeScript:**
```typescript
import { b } from './baml_client'

// Async client
const resume = await b.ExtractResume({ resume_text: "John Doe..." })

// Streaming
const stream = b.stream.ExtractResume({ resume_text: "..." })
for await (const partial of stream) {
    console.log(partial.name)  // Type-safe partials
}
```

### 4. Common Client Configurations

```baml
// Multiple providers with fallbacks
client<llm> GPT4 {
  provider "openai"
  options {
    model "gpt-4o"
    api_key env.OPENAI_API_KEY
    temperature 0.7
  }
}

client<llm> Claude {
  provider "anthropic"
  options {
    model "claude-sonnet-4-5"
    api_key env.ANTHROPIC_API_KEY
  }
}

client<llm> Gemini {
  provider "google-ai"
  options {
    model "gemini-2.5-flash"
    api_key env.GOOGLE_API_KEY
  }
}

// Fallback chain
client<llm> MyAI {
  provider "fallback"
  options {
    strategy [GPT4, Claude, Gemini]
  }
}
```

### 5. Array Syntax

```baml
{
  // Single-line arrays
  skills ["Python", "Rust", "Go"],

  // Multi-line arrays
  cities [
    "New York",
    "Los Angeles",
    "Chicago"
  ],

  // Nested objects in arrays
  education [
    {
      school "UC Berkeley",
      degree "B.S. Computer Science",
      year 2020
    },
    {
      school "MIT",
      degree "M.S. AI",
      year 2022
    }
  ]
}
```

### 6. Test Your Functions

```baml
test ExtractJohnDoe {
  functions [ExtractResume]
  args {
    resume_text "John Doe
    Skills: Python, Machine Learning, TypeScript
    Education: UC Berkeley, B.S. Computer Science, 2020"
  }
}
```

Run tests:
```bash
# Run all tests
baml-cli test

# Run specific test
baml-cli test ExtractJohnDoe

# Run from specific directory
baml-cli test --from /path/to/baml_src
```

## Core Concepts

### Type System

BAML provides a rich type system that maps to your target language:

**Primitives:**
- `string` - Text data
- `int` - Integers
- `float` - Floating point numbers
- `bool` - Boolean values
- `null` - Null/None/nil

**Collections:**
- `string[]` - Arrays/Lists
- `map<string, int>` - Dictionaries/Maps

**Custom Types:**
- `class` - Structured objects
- `enum` - Enumerated values (automatically explained to LLM)

**Example:**
```baml
class Person {
  name string
  age int?  // Optional field
  tags string[]
  metadata map<string, string>
}
```

### Client Methods

Every BAML function generates these methods:

**Direct Call:**
```python
result = await b.MyFunction(arg1="value")
```

**Streaming:**
```python
stream = b.stream.MyFunction(arg1="value")
async for partial in stream:
    print(partial)
```

**Get Request (without sending):**
```python
request = await b.request.MyFunction(arg1="value")
# Returns HTTP request object, doesn't send it
```

**Parse Response:**
```python
request = await b.request.MyFunction(arg1="value")
# Send request yourself...
parsed = b.parse.MyFunction(response)
```

### Providers Supported

- **OpenAI** - GPT-4, GPT-4o, GPT-5, etc.
- **Anthropic** - Claude Sonnet, Claude Opus
- **Google AI** - Gemini 2.5 Pro/Flash
- **Vertex AI** - Google Cloud Vertex
- **AWS Bedrock** - Claude, Llama, etc.
- **Azure OpenAI** - Azure-hosted models
- **OpenRouter** - Access to 100+ models
- **Ollama** - Local models
- **Groq** - Fast inference
- **Cerebras** - Ultra-fast inference
- **OpenAI-Generic** - Compatible APIs

### Multi-Language Support

BAML generates idiomatic code for:
- **Python** - Async/sync, Pydantic models
- **TypeScript/JavaScript** - Promises, Zod schemas
- **Ruby** - Async/sync support
- **Go** - Goroutines, struct types
- **Elixir** - Community-supported

## Common Patterns

### 1. Classification with Context

```baml
enum Sentiment {
  POSITIVE @description("Happy, satisfied, excited")
  NEGATIVE @description("Angry, frustrated, disappointed")
  NEUTRAL @description("Factual, no strong emotion")
}

function ClassifySentiment(text: string) -> Sentiment {
  client "openai/gpt-4o-mini"
  prompt #"
    Classify the sentiment of this text: {{ text }}
  "#
}
```

The `@description` annotations are automatically sent to the LLM for better classification.

### 2. Structured Extraction

```baml
class Invoice {
  invoice_number string
  date string
  vendor string
  line_items LineItem[]
  total float
}

class LineItem {
  description string
  quantity int
  unit_price float
  total float
}

function ExtractInvoice(invoice_text: string) -> Invoice {
  client "anthropic/claude-sonnet-4-5"
  prompt #"
    Extract invoice data from:
    {{ invoice_text }}
  "#
}
```

### 3. Fallback Strategy

```baml
client<llm> Primary {
  provider "openai"
  options { model "gpt-4o" }
}

client<llm> Backup {
  provider "anthropic"
  options { model "claude-sonnet-4-5" }
}

client<llm> Resilient {
  provider "fallback"
  options {
    strategy [Primary, Backup]
  }
}

function MyFunction(input: string) -> Output {
  client Resilient  // Auto-fallback on failure
}
```

### 4. Custom Retry Logic

```baml
retry_policy MyRetry {
  max_retries 3
  strategy {
    type exponential_backoff
    delay_ms 1000
    multiplier 2
  }
}

function MyFunction(input: string) -> Output {
  client "openai/gpt-4o"
  retry_policy MyRetry
}
```

### 5. React Hooks (TypeScript Only)

BAML auto-generates React hooks:

```typescript
import { useExtractResume } from './baml_client/react'

function ResumeExtractor() {
  const { mutate, data, isLoading, isStreaming, error } = useExtractResume({
    stream: true,
    onStreamData: (partial) => {
      console.log("Streaming:", partial?.name)
    },
    onFinalData: (final) => {
      console.log("Final:", final)
    },
    onError: (err) => console.error(err)
  })

  return (
    <button onClick={() => mutate({ resume_text: "..." })}>
      Extract Resume
    </button>
  )
}
```

## Working with This Skill

### For Beginners

1. **Install BAML:** Follow language-specific installation in `../../../references/llms-txt.md`
2. **Create `baml_src/` folder:** Store your .baml files here
3. **Write your first function:** Define types and prompt
4. **Run `baml-cli generate`:** Generates client code
5. **Import and call:** Use the generated client in your code

**First Example:**
```baml
// baml_src/hello.baml
function SayHello(name: string) -> string {
  client "openai/gpt-4o-mini"
  prompt #"Say hello to {{ name }} in a creative way"#
}
```

### For Specific Features

- **Streaming:** Use `b.stream.FunctionName()` - see AsyncClient/SyncClient section in references
- **Multi-provider:** Define multiple clients and use fallback provider
- **Testing:** Write test blocks and run `baml-cli test`
- **Debugging:** Use VSCode Playground to see raw requests/responses
- **Error Handling:** See error handling section in references

### For Advanced Users

- **Custom Providers:** Use `openai-generic` for compatible APIs
- **Media Handling:** Configure `media_url_handler` for images/audio/PDFs
- **Role Mapping:** Use `allowed_roles` and `remap_roles` for custom providers
- **Finish Reason Control:** Use `finish_reason_allow_list`/`deny_list`
- **Prompt Caching:** Use `allowed_role_metadata` for cache control

## Key Advantages Over Other Frameworks

### vs Langchain

**Langchain:**
```python
llm = ChatOpenAI(model="gpt-4o")
structured_llm = llm.with_structured_output(Resume)
result = structured_llm.invoke("John Doe...")
# ❌ No visibility into prompts
# ❌ No testing without running code
# ❌ Provider-specific code
```

**BAML:**
```baml
function ExtractResume(text: string) -> Resume {
  client "openai/gpt-4o"
  prompt #"Extract: {{ text }}"#
}
```
```python
result = await b.ExtractResume(text="John Doe...")
# ✅ Prompts visible in .baml files
# ✅ Test in Playground without code
# ✅ Change provider without code changes
```

### vs Direct API Calls

- **Type Safety:** Guaranteed at build time
- **Error Handling:** Built-in retries and fallbacks
- **JSON Parsing:** Handles malformed JSON automatically
- **Streaming:** Partial object parsing built-in
- **Testing:** Playground for rapid iteration
- **Multi-language:** Same .baml files, multiple languages

## Development Workflow

1. **Write BAML function** in `baml_src/*.baml`
2. **Test in Playground** (VSCode extension)
3. **Generate client:** `baml-cli generate`
4. **Call from code** with full type safety
5. **Iterate on prompt** without changing code

## Reference Files

This skill includes comprehensive documentation in `../../../references/`:

- **llms-txt.md** (235 pages) - Complete BAML documentation including:
  - Installation guides for all languages
  - Function syntax and type system
  - Client providers (OpenAI, Anthropic, Google AI, etc.)
  - Streaming and async patterns
  - Testing and debugging
  - Error handling
  - React hooks reference
  - Provider-specific options

Use `view ../../../references/llms-txt.md` for detailed information on any topic.

## Resources

### Official Links
- **Documentation:** https://docs.boundaryml.com/
- **GitHub:** https://github.com/boundaryml/baml
- **VSCode Extension:** Search "BAML" in VSCode Marketplace
- **Examples:** https://github.com/boundaryml/baml-examples

### CLI Commands
```bash
baml-cli generate          # Generate client code
baml-cli test             # Run all tests
baml-cli test TestName    # Run specific test
baml-cli --version        # Check version
```

## Notes

- Auto-generated from official documentation (llms.txt format)
- All code examples are from official BAML docs
- Supports Python 3.10+, TypeScript/Node.js, Ruby, Go
- VSCode extension provides Playground for testing
- Zero runtime dependencies beyond the generated client

## Updating

To refresh with latest BAML documentation:
```bash
python3 cli/doc_scraper.py --name baml --url https://docs.boundaryml.com/home
python3 cli/enhance_skill_local.py output/baml/
python3 cli/package_skill.py output/baml/
```

