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

# Using behaviors

> How to retrieve the preset catalog, apply preset slugs, and include BehaviorDef objects in your BatchConfig.

The `behaviors` array in `BatchConfig` accepts two types of entries — preset reference strings and full `BehaviorDef` objects — and you can mix both freely.

## Listing available presets

Call `GET /api/velma-2-batch/list-presets` or `GET /api/velma-2-streaming/list-presets` to retrieve the behavior preset catalog. Both endpoints require the `X-API-Key` header and return the same response format.

<CodeGroup>
  ```bash curl theme={null}
  curl https://platform.modulate.ai/api/velma-2-batch/list-presets \
    -H "X-API-Key: $MODULATE_API_KEY"
  ```

  ```python Python theme={null}
  import os, requests

  response = requests.get(
      "https://platform.modulate.ai/api/velma-2-batch/list-presets",
      headers={"X-API-Key": os.environ["MODULATE_API_KEY"]},
  )
  response.raise_for_status()
  for preset in response.json()["presets"]:
      print(f"preset:{preset['identifier']}  —  {preset['name']}")
      print(f"  {preset['short_description']}")
  ```
</CodeGroup>

<Accordion title="Example response (truncated)">
  ```json theme={null}
  {
    "presets": [
      {
        "identifier": "service-churn",
        "name": "Service Churn",
        "short_description": "Customer decides to cancel an ongoing service.",
        "detailed_description": "To qualify, the speech must fit the following criteria: The speech must feature assertions that the speaker would like to cancel a service or subscription. The speech must not be phrased as a threat in the first or second person voice."
      },
      {
        "identifier": "harassment",
        "name": "Harassment",
        "short_description": "Targeted, repeated hostile behavior toward a participant.",
        "detailed_description": "..."
      }
    ]
  }
  ```
</Accordion>

The `identifier` is what you use in a preset reference string. The `detailed_description` is the exact detection language Velma applies when you reference a preset — use it as a starting point when adapting a preset into a custom behavior.

## Using preset references

Include a preset by adding a `"preset:<identifier>"` string to the `behaviors` array. Velma expands it into the full behavior definition before processing.

<CodeGroup>
  ```bash websocat theme={null}
  websocat "wss://platform.modulate.ai/api/velma-2-streaming?api_key=$MODULATE_API_KEY" \
    --text - <<'EOF'
  {"behaviors":["preset:harassment","preset:service-churn","preset:account-impersonation"]}
  EOF
  ```

  ```python Python theme={null}
  import os, json, asyncio, websockets

  config = {
      "behaviors": [
          "preset:harassment",
          "preset:service-churn",
          "preset:account-impersonation",
      ]
  }

  async def stream():
      url = f"wss://platform.modulate.ai/api/velma-2-streaming?api_key={os.environ['MODULATE_API_KEY']}"
      async with websockets.connect(url) as ws:
          await ws.send(json.dumps(config))
          with open("audio.mp3", "rb") as f:
              while chunk := f.read(4096):
                  await ws.send(chunk)
          await ws.send("")
          async for message in ws:
              event = json.loads(message)
              if event["type"] == "done":
                  break

  asyncio.run(stream())
  ```
</CodeGroup>

## Including BehaviorDef objects directly

Put full `BehaviorDef` objects in the `behaviors` array for precise control. All four required fields must be present.

**To define a custom behavior:** supply all four fields with a UUID you generate. See [Custom behaviors](/velma/behaviors/custom-behaviors).

<CodeGroup>
  ```bash websocat theme={null}
  websocat "wss://platform.modulate.ai/api/velma-2-streaming?api_key=$MODULATE_API_KEY" \
    --text - <<'EOF'
  {
    "behaviors": [
      {
        "behavior_uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "Service Churn",
        "short_description": "Customer decides to cancel an ongoing service.",
        "detailed_description": "To qualify, the speech must fit the following criteria: The speech must feature assertions that the speaker would like to cancel a service or subscription. The speech must not be phrased as a threat in the first or second person voice."
      }
    ]
  }
  EOF
  ```

  ```python Python theme={null}
  import os, json, asyncio, websockets

  config = {
      "behaviors": [
          {
              "behavior_uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
              "name": "Service Churn",
              "short_description": "Customer decides to cancel an ongoing service.",
              "detailed_description": (
                  "To qualify, the speech must fit the following criteria: "
                  "The speech must feature assertions that the speaker would like to cancel "
                  "a service or subscription. The speech must not be phrased as a threat "
                  "in the first or second person voice."
              ),
          }
      ]
  }

  async def stream():
      url = f"wss://platform.modulate.ai/api/velma-2-streaming?api_key={os.environ['MODULATE_API_KEY']}"
      async with websockets.connect(url) as ws:
          await ws.send(json.dumps(config))
          with open("audio.mp3", "rb") as f:
              while chunk := f.read(4096):
                  await ws.send(chunk)
          await ws.send("")
          async for message in ws:
              event = json.loads(message)
              if event["type"] == "behavior_detection":
                  d = event["detection"]
                  print(f"{d['behavior_name']}: detected={d['detected']} confidence={d['confidence']}")
              elif event["type"] == "done":
                  break

  asyncio.run(stream())
  ```
</CodeGroup>

## Mixing presets and custom behaviors

Preset references and `BehaviorDef` objects can coexist in the same `behaviors` array. If a custom `BehaviorDef` shares a UUID with a preset entry, the custom definition takes precedence.

```json theme={null}
{
  "behaviors": [
    "preset:harassment",
    {
      "behavior_uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "name": "Service Churn",
      "short_description": "Customer decides to cancel an ongoing service.",
      "detailed_description": "To qualify, the speech must feature assertions that the speaker would like to cancel a service or subscription. The speech must not be phrased as a threat in the first or second person voice."
    }
  ]
}
```

## Behavior fields reference

| Field                                | Type                | Required |
| ------------------------------------ | ------------------- | -------- |
| `behavior_uuid`                      | UUID string         | Yes      |
| `name`                               | string (min 1 char) | Yes      |
| `short_description`                  | string              | Yes      |
| `detailed_description`               | string              | Yes      |
| `applies_to_conversation_type_uuids` | UUID array or null  | No       |
| `applies_to_participant_role_uuids`  | UUID array or null  | No       |

## Related

* [Custom behaviors](/velma/behaviors/custom-behaviors) — define your own from scratch or adapt pre-built ones
* [Best practices](/velma/behaviors/best-practices) — write descriptions that produce accurate results
* [Capabilities](/velma/capabilities) — the full BatchConfig reference
