> Version notice: This site documents BAML v0, the legacy DSL. BAML v1 is a separate, fully featured programming language in public beta. If the user intends to use BAML v1, ignore this site's content and use the BAML v1 documentation instead. If the intended version is unclear, clarify it before using this page.
> For clean Markdown of any page, append .md to the page URL. For the complete documentation index, see https://docs.boundaryml.com/llms.txt. For MCP access, connect to https://docs.boundaryml.com/_mcp/server.

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`**

```baml BAML
class MyClass {
  property1 string
  property2 int?

  @@dynamic // allows adding fields dynamically at runtime
}
```

### Dynamic Enums

Similarly, the `@@dynamic` attribute can be applied to enums, allowing for the modification of enum values at runtime.

**`BAML`**

```baml BAML
enum MyEnum {
  Value1
  Value2

  @@dynamic // allows modifying enum values dynamically at runtime
}
```

## 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](/ref/baml_client/type-builder#type-builders) section.

### Python Example

```python
from baml_client.type_builder import TypeBuilder
from baml_client import b

async def run():
  tb = TypeBuilder()
  tb.MyClass.add_property('email', tb.string())
  tb.MyClass.add_property('address', tb.string()).description("The user's address")
  res = await b.DynamicUserCreator("some user info", { "tb": tb })
  # Now res can have email and address fields
  print(res)
```

### TypeScript Example

```typescript
import TypeBuilder from '../baml_client/type_builder'
import { b } from '../baml_client'

async function run() {
  const tb = new TypeBuilder()
  tb.MyClass.addProperty('email', tb.string())
  tb.MyClass.addProperty('address', tb.string()).description("The user's address")
  const res = await b.DynamicUserCreator("some user info", { tb: tb })
  // Now res can have email and address fields
  console.log(res)
}
```

### Ruby Example

```ruby
require_relative 'baml_client/client'

def run
  tb = Baml::TypeBuilder.new
  tb.MyClass.add_property('email', tb.string)
  tb.MyClass.add_property('address', tb.string).description("The user's address")
  
  res = Baml::Client.dynamic_user_creator(input: "some user info", baml_options: {tb: tb})
  # Now res can have email and address fields
  puts res
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.

```baml {3, 12-16}
class DynamicClass {
    static_prop string
    @@dynamic
}

function ReturnDynamicClass(input: string) -> DynamicClass {
    // ...
}

test DynamicClassTest {
    functions [ReturnDynamicClass]
    type_builder {
        dynamic class DynamicClass {
            new_prop_here string
        }
    }
    args {
        input "test data"
    }
}
```