> ## Documentation Index
> Fetch the complete documentation index at: https://docs.021labs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# BAML

> Trace BAML structured extraction calls

## What is BAML?

[BAML](https://github.com/BoundaryML/baml) (Boundary AI Markup Language) is a domain-specific language for building type-safe LLM applications. It provides structured extraction with automatic validation and retry logic.

## Installation

```bash theme={null}
pip install rdk baml-py --extra-index-url https://pypi.fury.io/021labs/
```

## Setup

### 1. Create BAML Files

Create your BAML schema in `baml_src/main.baml`:

```baml theme={null}
class CustomerInquiry {
  category "billing" | "technical" | "general"
  priority int @description("1-5, where 5 is highest")
  summary string
}

function ClassifyInquiry(message: string) -> CustomerInquiry {
  client Claude
  prompt #"
    Classify this customer inquiry:
    {{ message }}

    Return the classification as JSON.
  "#
}
```

### 2. Configure Generator

Create `baml_src/generators.baml`:

```baml theme={null}
generator target {
  output_type python/pydantic
  output_dir ../
  version "0.219.0"
}

client<llm> Claude {
  provider anthropic
  options {
    model "claude-sonnet-4-6"
  }
}
```

### 3. Generate Client

```bash theme={null}
baml-cli generate
```

## Basic Usage

<Warning>
  BAML clients are code-generated per project and cannot be auto-instrumented. You **must** call `instrument_baml(b)` after `init()`, or BAML calls will not be traced.
</Warning>

```python theme={null}
from baml_client import b
from baml_client.types import CustomerInquiry
from rdk import observe, instrument_baml, shutdown

# Wrap the BAML client — required for tracing
b = instrument_baml(b)

@observe(name="classify-inquiry")
def classify(message: str) -> CustomerInquiry:
    return b.ClassifyInquiry(message)

result = classify("I can't log into my account!")
print(f"Category: {result.category}")
print(f"Priority: {result.priority}")
print(f"Summary: {result.summary}")

shutdown()
```

## Async Support

BAML async functions are fully supported:

```python theme={null}
import asyncio
from baml_client import b
from rdk import observe, instrument_baml, shutdown

b = instrument_baml(b)

@observe(name="async-classify")
async def async_classify(message: str):
    return await b.ClassifyInquiry(message)

result = asyncio.run(async_classify("Payment failed"))
shutdown()
```

## Complex Types

BAML excels at structured extraction with nested types:

```baml theme={null}
class Address {
  street string
  city string
  country string
  postal_code string | null
}

class Contact {
  name string
  email string
  phone string | null
  address Address
}

function ExtractContact(text: string) -> Contact {
  client Claude
  prompt #"
    Extract contact information from:
    {{ text }}
  "#
}
```

```python theme={null}
from baml_client import b
from rdk import observe, instrument_baml, shutdown

b = instrument_baml(b)

@observe(name="extract-contact")
def extract_contact(text: str):
    return b.ExtractContact(text)

result = extract_contact("""
    John Smith
    john@example.com
    123 Main St, New York, NY 10001
""")
print(f"Name: {result.name}")
print(f"City: {result.address.city}")
shutdown()
```

## What Gets Captured

For each BAML call, RDK captures:

| Field               | Description                   |
| ------------------- | ----------------------------- |
| `type`              | `LLM`                         |
| `model`             | Model from BAML client config |
| `input.args`        | Function arguments            |
| `output.result`     | Structured result             |
| `token_usage`       | Token counts                  |
| `metadata.provider` | `"baml"`                      |

## Error Handling

BAML provides validation errors for malformed responses:

```python theme={null}
from baml_client import b
from baml_client.errors import BamlValidationError
from rdk import observe, instrument_baml, shutdown

b = instrument_baml(b)

@observe(name="safe-classify")
def safe_classify(message: str):
    try:
        return b.ClassifyInquiry(message)
    except BamlValidationError as e:
        print(f"Validation failed: {e}")
        return None

result = safe_classify("Hello")
shutdown()
```

## See Also

* [instrument\_baml()](/api-reference/instrument-baml) — API reference
