# Create custom language operators

Language operators are the programmable Generative AI (GenAI)-powered building blocks of Conversation Intelligence. You can create custom language operators tailored to your specific use cases that Twilio-authored language operators might not address.

## What is a custom language operator?

Custom language operators let you define and create your own language understanding tasks and perform conversational analysis that is:

* Unique to your business, tailored to your domain, terminology, and workflows
* Configurable, giving you full control over instructions and expected output
* Flexible, supporting both real-time and post-conversation use cases

You define what you want to extract using freeform instructions (prompt) and can optionally add context ([Conversation Memory](/docs/conversations/memory), [Enterprise Knowledge](/docs/conversations/knowledge)) for more personalized and grounded results. The outcome is returned as a language operator result you can consume and activate in downstream systems.

### Custom language operator examples

The following are examples of custom language operators that augment human agents or trigger automation:

* **Personalized greeting recommendations** based on customer history and business context
* **Real-time compliance checks** to detect required disclosures or prohibited language
* **Live objection handling** using common objections unique to your products and services
* **Custom lead qualification** based on your proprietary scoring criteria
* **Tailored summaries** that are specific to your business and personalized to the customer

## Custom language operator components

A custom language operator consists of the following components:

* [Prompt](#prompt)
* [Output format](#output-format)
* [Parameters](#parameters)
* [(Optional) Context capabilities](#context-capabilities)

### Prompt

A prompt provides instructions for analyzing incoming conversations. You describe in natural language the task you want the language operator to perform with your conversations.

For guidance on how to write effective prompts, see [Prompting best practices](#prompting-best-practices).

For examples, see [Example use cases](/docs/conversations/intelligence/custom-language-operator-examples).

### Output format

You can specify the desired output format (`outputFormat`) for your custom language operator:

* `TEXT`: Plain text (default)
* `JSON`: Structured JSON object
* `CLASSIFICATION`: Classifier string

When you provide a JSON schema, the language operator formats its output according to that schema. This helps ensure consistent and predictable results that are easier to parse and integrate with other systems.

Learn more about [Structuring JSON schema](#structuring-json-schema).

### Parameters

Using parameters, custom language operators can accept dynamic inputs at runtime. Parameters make language operators configurable, reusable across intelligence configurations, and able to adapt their behavior based on the context of each conversation.

You must reference parameters directly in the language operator prompt using special syntax that substitutes the parameter values at runtime.

You define and use parameters in two places:

* **Custom language operator**: Where you define the parameter schema
* **Intelligence configuration rule**: Where you specify parameter values set at runtime

Together, these control how the language operator behaves during execution. When a rule triggers, the following occurs:

1. Conversation Intelligence loads the language operator and its parameter schema.
2. The intelligence configuration rule supplies parameter values.
3. Default values are applied where values are not provided.
4. The knowledge source content is resolved (if applicable).
5. The prompt is rendered with parameter substitutions.
6. The language operator executes using the combined prompt, parameters, and context.

Learn more about [Defining parameters](#defining-parameters).

### Context capabilities

You can optionally enable context capabilities for your custom language operator. When enabled, the language operator can access contextual data during execution to:

* Personalize its output
* Use business or domain information
* Produce more accurate and relevant results

You enable context capabilities using two on/off toggles: one for Conversation Memory and one for Enterprise Knowledge.

When a language operator has Conversation Memory or Enterprise Knowledge enabled and becomes context-aware, it can query that data during execution. The language operator determines at runtime whether to use the provided context based on its relevance to the prompt and conversation transcript.

Learn more about [business and customer data for language operators](/docs/conversations/intelligence/business-customer-data).

For context to work:

* The language operator must declare support for Conversation Memory or Enterprise Knowledge.
* The intelligence configuration rule must provide the context resources, such as customer profiles or knowledge bases.

Learn more about how language operators use [knowledge search and memory tools](#knowledge-search-and-memory-tools).

### Training examples

You can provide training examples to help improve language operator results by contextualizing, clarifying, signaling intent, and adding specificity to your request.

Training examples consist of a sample input and the corresponding expected output:

* **Input**: Provide sample communications for the language operator to use as an example conversation
* **Output**: Provide what you would expect the language operator result to be for the given input

The language operator uses these examples to better understand the task you are asking it to perform.

## Prompting best practices

To ensure the best possible results from your custom language operators, follow these prompting best practices:

* **Specify the task clearly and use explicit instructions**:

  Clearly state what you want the model to do, and specify the style or format of the response. This reduces ambiguity and ensures that the model provides the desired output.

  **Example**: Instead of asking "Tell me about this customer", ask:

  ```text
  Provide a concise summary of the customer's needs with regard to moving and storage.
  ```
* **Include context**:

  Providing relevant context can help the model generate more relevant and coherent responses, especially for complex queries.

  **Example**:

  ```text
  Given our company's emphasis on recurring revenue over one-time purchases, how strong a lead is this prospect?
  ```
* **Ask specific questions and limit open-ended inputs**:

  Formulate precise questions to elicit clear and focused responses. Narrow the scope to avoid broad or vague answers.

  **Example**:

  ```text
  What are three key factors this customer is looking for in an insurance provider?
  ```
* **Break down complex tasks**:

  For complex or multi-step tasks, consider breaking them into simpler, sequential prompts.

  **Example**:

  ```text
  - Step 1: List the key moments in this conversation. - Step 2: Compare these with the following script.
  ```
* **Use examples to guide format**:

  Offering a sample response can set expectations for the type and style of answer you anticipate.

  **Example**:

  ```text
  Describe the key features the customer wants in a car. For instance, 'The customer is looking for a sports car with low mileage and a good infotainment system'.
  ```

  If you have multiple examples, consider using [Training examples](#training-examples) to provide these in a structured way.
* **Provide constraints when necessary**:

  Introducing constraints like word limits or particular formats can help control the output.

  **Example**:

  ```text
  Summarize the conversation in 100 words or fewer.
  ```

## Knowledge search and memory tools

Knowledge search and memory tools give language operators access to Enterprise Knowledge and Conversation Memory, enabling more accurate and personalized responses.

* **Knowledge search tool**: Performs semantic search over [knowledge bases](/docs/conversations/knowledge) to retrieve documentation, policies, and product information.
* **Memory tools**: Provides access to historical context and user attributes for personalized responses. Memory tools include:
  * **Observational memory search tool**: Searches observations automatically extracted from past conversations with the customer.
  * **Trait memory fetch tool**: Fetches attributes explicitly set about a customer, such as name, preferences, and VIP status.

### Configuration

For a language operator to use these tools, set the following in the language operator configuration and intelligence configuration rule:

| Type                  | Operator                          | Intelligence configuration rule                    |
| --------------------- | --------------------------------- | -------------------------------------------------- |
| Knowledge search tool | `context.knowledge.enabled: true` | `context.knowledge.bases: ["<KNOWLEDGE_BASE_ID>"]` |
| Memory tools          | `context.memory.enabled: true`    | N/A                                                |

**Note**: Conversation Memory doesn't require additional configuration in the intelligence configuration rule because the system automatically handles user identification.

### Tool prompting best practices

When knowledge search or memory tools are enabled in your operator and intelligence configuration, the language operator can invoke them during execution. While leaving this unguided works for some language operators, explicitly referencing the tool in the prompt can improve results.

To help the language operator correctly identify and use these tools, follow these best practices when writing your prompt:

* **Use the exact name**: Always refer to the tool as the "knowledge search tool", "observational memory search tool", or "trait memory fetch tool" in the prompt. This ensures consistency with the tool's description and helps the language operator recognize it.
* **Structure your instruction**: Use clear sections, such as "Goal" and "Steps".

  * If the language operator should *always* use the tool, reference it in both the Goal and Steps sections.
  * If the language operator should *conditionally* use the tool, clearly define the conditions in the Steps section.
* **Don't reference the knowledge base IDs in the prompt**: The language operator doesn't understand them and might hallucinate. The language operator interacts with the knowledge search tool only using query strings.

```text title="Example: Knowledge search tool prompting"
# Goal

Analyze the following transcript to determine if incorrect policy information was provided by the Agent

# Steps

1. Read through the following transcript and identify if the agent provides any information related to company policy to the customer. Examples of this include the company's returns policy or service level agreement for faulty products.
2. If no company policies were discussed, return 'no policies discussed'.
3. If a company policy was discussed, you should use the knowledge search tool to search the official policy documentation. Use the results of the knowledge search tool to check if the agent provided any information that contradicted or was not present in the company's official policies. You should return a list of all incorrect policy information. You should include the information provided by the agent as well as the actual policy as identified by the knowledge search tool.
```

```text title="Example: Memory tools prompting"
# Goal

Analyze the following transcript to determine if the customer is making a repeated complaint. That is, if the current call includes any complaint that the customer has made in previous calls.

# Steps

1. Identify all complaints that the customer has made in the transcript below.
2. Use the observational memory search tool to search for any complaints in observational memory.
3. Compare the complaints from the current transcript with the complaints from observational memory.
   a. If there are matching complaints, return all matching complaints in the "repeated_complaints" list of the JSON response.
   b. If there are no complaints in the current transcript, or no complaints in observational memory, or no matching complaints, set the "repeated_complaints" property to an empty list.
```

## Structuring JSON schema

Use JSON schema to define the expected output structure when using structured JSON as the output format for your custom language operator.

A JSON schema for custom language operator results must be an object type. At minimum, a valid schema must include the following keywords:

* `type`: Must be set to `object`
* `properties`: An object defining the property names and their data types that the language operator should return

### Schema example

The following example shows a valid JSON schema for a tailored summarization use case:

```json
{
    "type": "object",
    "properties": {
        "budget": { "type": "string" },
        "authority": { "type": "string" },
        "need": { "type": "string" },
        "timeline": { "type": "string" }
    }
}
```

### Schema guidelines

When creating a JSON schema for your custom language operator, keep the following guidelines in mind:

* When you choose `outputFormat: JSON`, you must provide a matching output schema (`outputSchema`), and the language operator's structured output will conform to this schema. See [Troubleshooting: Response schema validation](/docs/conversations/intelligence/troubleshooting#troubleshooting-response-schema-validation) for failures related to response schema.
* The root-level type of a JSON schema must be set to object.
* The following property data types are supported: `string`, `number`, `boolean`, `integer`, `object`, `array`, `enum`, `anyOf`
* Each output response has a maximum limit of 8,800 characters. To keep your output responses within this limit, follow these guidelines when designing the output schema:
  * Flatten your JSON structure: Avoid overly nested JSON objects. Each nesting level adds extra characters when producing the JSON structure.
  * Use efficient data types: Use Boolean (true/false) or integer (1/0) values for classifications.
  * Abbreviate JSON property keys: Use concise, common abbreviations. For example, use `cust_id` instead of `customer_identification_number`.
  * Minimize redundancy: Only include fields that are absolutely necessary for your downstream processes.
* Max **100 object properties** and **5 levels of nesting** are supported.
* Max **500 enum values** across all enum properties are supported.
* Notable JSON Schema keywords not supported include:
  * **For strings**: `minLength`, `maxLength`, `pattern`, `format`
  * **For numbers**: `minimum`, `maximum`, `multipleOf`
  * **For objects**: `patternProperties`, `unevaluatedProperties`, `propertyNames`, `minProperties`, `maxProperties`
  * **For arrays**: `unevaluatedItems`, `contains`, `minContains`, `maxContains`, `minItems`, `maxItems`, `uniqueItems`
* Structured language operator results will be returned in the same order as the keys in the schema.
* If the language operator refuses a language operator execution request for safety reasons, the language operator result will include a `refusal` field.
* Twilio will automatically set `additionalProperties` to `false` and specify all provided fields as required (constraints of Structured Outputs). You don't need to pass these fields as part of your JSON schema. Twilio will automatically overwrite any user-provided values for these fields.

For additional JSON result schema examples, see [Example use cases](/docs/conversations/intelligence/custom-language-operator-examples).

To review all available JSON schema syntax, see the [JSON schema reference](https://json-schema.org/understanding-json-schema/reference). You can also use JSON schema generators, such as [transform.tools](https://transform.tools/json-schema-generator).

## Defining parameters

When creating a custom language operator, you define a parameter schema that describes:

* What parameters are available (parameter names)
* Parameter types
* Whether parameters are required
* Parameter default values (if applicable)
* How to reference parameters inside your prompt

Each parameter includes:

* `type`: The data type. Supported types are `string`, `integer`, `number`, `boolean`, and `knowledge_base_and_source_ids`.
* `default`: (Optional) A fallback value if the intelligence configuration doesn't provide one
* `required`: Whether the parameter must be provided at execution time
* `description`: A human-readable explanation of the parameter's purpose

### knowledge\_base\_and\_source\_ids parameter type

The `knowledge_base_and_source_ids` parameter type allows a custom language operator to directly reference a specific knowledge source from a knowledge base. Use this for tasks like:

* Product-specific troubleshooting
* Policy-aware reasoning
* FAQ-informed agent guidance

The intelligence configuration rule passes the parameter value as a colon-separated string formatted:

```text
<knowledge_base_id>:<knowledge_source_id>
```

* This parameter type only supports plain text knowledge sources.
* This parameter type doesn't support `default` values.

When the language operator executes, it uses the provided knowledge base ID and knowledge source ID to look up the corresponding knowledge source.

At runtime, Twilio retrieves the plain text content of that knowledge source and injects it into the operator prompt.

The following example shows how to define a `knowledge_base_and_source_ids` parameter in your custom language operator's parameter schema:

```json
{
  "type": "object",
  "parameters": {
    "policy_doc": {
      "type": "knowledge_base_and_source_ids",
      "required": true,
      "description": "Policy document to reference for compliance checks."
    }
  }
}
```

### Parameter schema example

```json
{
  "parameters": {
    "scale": {
      "type": "integer",
      "default": 5,
      "required": true,
      "description": "Maximum score for evaluating script adherence."
    }
  } 
}
```

### Referencing parameters inside your prompt

You can reference parameters in your prompt using the following syntax:

```text
{{parameters.<param_name>}}
```

At runtime, Twilio replaces these tokens with the values supplied by your intelligence configuration rule. For example, if you have a parameter named `length`, you can reference it in your prompt like this:

```text
Provide a {{parameters.length}}-length summary of this conversation.
```

## Prerequisites

Before creating a custom language operator, check if any [Twilio-authored language operator](/docs/conversations/intelligence/use-twilio-authored-language-operators) meets your needs.

## Create a custom language operator

You can create a custom language operator using Twilio Console or the API.

> \[!NOTE]
>
> Twilio recommends using Twilio Console for most users. If you're an Independent Software Vendor (ISV) or use Infrastructure as Code (IaC) automation, use the API to programmatically create and manage custom language operators.

## Console

To create a custom language operator using Twilio Console:

1. In [Twilio Console](https://1console.twilio.com), go to **Products & services** > **Conversation Intelligence** > **Language operators** and click **Create operator**.
2. Follow the steps to create a custom language operator. The steps are:
   * Create instructions.
   * Add context capabilities.
3. Review and save the custom language operator.

## API

To create a custom language operator using the API, make a `POST` request to the [Operators resource](/docs/api/intelligence/v3/Operators).

The following example creates a Personalized Greeting operator that:

* Generates a personalized greeting message for the customer with justification.
* Uses GenAI to incorporate customer attributes (name, status, recent activity).
* Supports Conversation Memory and Enterprise Knowledge to tailor the greeting.
* Accepts a configurable tone parameter to control greeting style.
* Returns a structured JSON object containing the greeting and metadata.

Create a custom language operator

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID at twilio.com/console
// Provision API Keys at twilio.com/console/runtime/api-keys
// and set the environment variables. See http://twil.io/secure
// For local testing, you can use your Account SID and Auth token
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const apiKey = process.env.TWILIO_API_KEY;
const apiSecret = process.env.TWILIO_API_SECRET;
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });

async function createOperator() {
  const operator = await client.intelligence.v3.operators.create({
    displayName: "Personalized Greeting",
    description:
      "Creates a personalized, context-aware greeting for a customer.",
    version: 1,
    author: "SELF",
    prompt:
      "Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile attributes (name, preferences, status) and relevant business knowledge to tailor the message. Return JSON with the greeting text and a brief justification.",
    outputFormat: "JSON",
    outputSchema: {
      type: "object",
      properties: {
        greeting: {
          type: "string",
        },
        justification: {
          type: "string",
        },
      },
    },
    context: {
      knowledge: {
        enabled: true,
      },
    },
    parameters: {
      tone: {
        type: "STRING",
        default: "friendly",
        required: false,
        description:
          "The tone of the greeting (e.g., friendly, professional, casual).",
      },
    },
  });

  console.log(operator.id);
}

createOperator();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client
from twilio.rest.intelligence.v3 import OperatorList

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = os.environ["TWILIO_API_KEY"]
api_secret = os.environ["TWILIO_API_SECRET"]
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
client = Client(api_key, api_secret, account_sid)

operator = client.intelligence.v3.operators.create(
    language_operator=OperatorList.LanguageOperator(
        {
            "displayName": "Personalized Greeting",
            "description": "Creates a personalized, context-aware greeting for a customer.",
            "version": 1,
            "author": "SELF",
            "prompt": "Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile attributes (name, preferences, status) and relevant business knowledge to tailor the message. Return JSON with the greeting text and a brief justification.",
            "outputFormat": "JSON",
            "outputSchema": {
                "type": "object",
                "properties": {
                    "greeting": {"type": "string"},
                    "justification": {"type": "string"},
                },
            },
            "context": OperatorList.OperatorContext(
                {
                    "knowledge": OperatorList.OperatorContextKnowledge(
                        {"enabled": True}
                    )
                }
            ),
            "parameters": {
                "tone": OperatorList.OperatorParameter(
                    {
                        "type": "STRING",
                        "default": "friendly",
                        "required": False,
                        "description": "The tone of the greeting (e.g., friendly, professional, casual).",
                    }
                )
            },
        }
    )
)

print(operator.id)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Intelligence.V3;
using System.Threading.Tasks;
using System.Collections.Generic;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID at twilio.com/console
        // Provision API Keys at twilio.com/console/runtime/api-keys
        // and set the environment variables. See http://twil.io/secure
        // For local testing, you can use your Account SID and Auth token
        string apiKey = Environment.GetEnvironmentVariable("TWILIO_API_KEY");
        string apiSecret = Environment.GetEnvironmentVariable("TWILIO_API_SECRET");
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");

        TwilioClient.Init(apiKey, apiSecret, accountSid);

        var _operator = await OperatorResource.CreateAsync(
            languageOperator: new OperatorResource.LanguageOperator.Builder()
                .WithDisplayName("Personalized Greeting")
                .WithDescription("Creates a personalized, context-aware greeting for a customer.")
                .WithVersion(1)
                .WithAuthor("SELF")
                .WithPrompt(
                    "Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile attributes (name, preferences, status) and relevant business knowledge to tailor the message. Return JSON with the greeting text and a brief justification.")
                .WithOutputFormat("JSON")
                .WithOutputSchema(new Dictionary<string, Object>() {
                    { "type", "object" },
                    { "properties",
                      new Dictionary<string, Object>() {
                          { "greeting", new Dictionary<string, Object>() { { "type", "string" } } },
                          { "justification",
                            new Dictionary<string, Object>() { { "type", "string" } } }
                      } }
                })
                .WithContext(
                    new OperatorResource.OperatorContext.Builder()
                        .WithKnowledge(new OperatorResource.OperatorContextKnowledge.Builder()
                                           .WithEnabled(true)
                                           .Build())
                        .Build())
                .WithParameters(new Dictionary<string, OperatorResource.OperatorParameter>() {
                    { "tone",
                      new OperatorResource.OperatorParameter.Builder()
                          .WithType("STRING")
                          .WithDefault("friendly")
                          .WithRequired(false)
                          .WithDescription(
                              "The tone of the greeting (e.g., friendly, professional, casual).")
                          .Build() }
                })
                .Build());

        Console.WriteLine(_operator.Id);
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.twilio.Twilio;
import com.twilio.rest.intelligence.v3.Operator;

public class Example {
    // Find your Account SID at twilio.com/console
    // Provision API Keys at twilio.com/console/runtime/api-keys
    // and set the environment variables. See http://twil.io/secure
    // For local testing, you can use your Account SID and Auth token
    public static final String API_KEY = System.getenv("TWILIO_API_KEY");
    public static final String API_SECRET = System.getenv("TWILIO_API_SECRET");
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");

    public static void main(String[] args) {
        Twilio.init(API_KEY, API_SECRET, ACCOUNT_SID);

        Operator.OperatorContextKnowledge operatorContextKnowledge =
            Operator.OperatorContextKnowledge.builder().enabled(true).build();

        Operator.OperatorContext operatorContext =
            Operator.OperatorContext.builder().knowledge(operatorContextKnowledge).build();

        Operator.LanguageOperator languageOperator =
            Operator.LanguageOperator
                .builder("Personalized Greeting",
                    "Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile "
                    + "attributes (name, preferences, status) and relevant business knowledge to tailor the message. "
                    + "Return JSON with the greeting text and a brief justification.",
                    Operator.OperatorOutputFormat.JSON)
                .description("Creates a personalized, context-aware greeting for a customer.")
                .version(1)
                .author(Operator.OperatorAuthorEnum.SELF)
                .outputSchema(new HashMap<String, Object>() {
                    {
                        put("type", "object");
                        put("properties", new HashMap<String, Object>() {
                            {
                                put("greeting", new HashMap<String, Object>() {
                                    {
                                        put("type", "string");
                                    }
                                });
                                put("justification", new HashMap<String, Object>() {
                                    {
                                        put("type", "string");
                                    }
                                });
                            }
                        });
                    }
                })
                .context(operatorContext)
                .parameters(new HashMap<String, Map<String, Object>>() {
                    {
                        put("tone", new HashMap<String, Object>() {
                            {
                                put("type", "STRING");
                                put("default", "friendly");
                                put("required", false);
                                put("description", "The tone of the greeting (e.g., friendly, professional, casual).");
                            }
                        });
                    }
                })
                .build();

        Operator.CreateOperatorResponse response = Operator.creator(languageOperator).create();

        System.out.println(response.getId());
    }
}
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = ENV['TWILIO_API_KEY']
api_secret = ENV['TWILIO_API_SECRET']
account_sid = ENV['TWILIO_ACCOUNT_SID']
@client = Twilio::REST::Client.new(api_key, api_secret, account_sid)

operator = @client
           .intelligence
           .v3
           .operators
           .create(
             language_operator: {
               'displayName' => 'Personalized Greeting',
               'description' => 'Creates a personalized, context-aware greeting for a customer.',
               'version' => 1,
               'author' => 'SELF',
               'prompt' => 'Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile attributes (name, preferences, status) and relevant business knowledge to tailor the message. Return JSON with the greeting text and a brief justification.',
               'outputFormat' => 'JSON',
               'outputSchema' => {
                 'type' => 'object',
                 'properties' => {
                   'greeting' => {
                     'type' => 'string'
                   },
                   'justification' => {
                     'type' => 'string'
                   }
                 }
               },
               'context' => {
                 'knowledge' => {
                   'enabled' => true
                 }
               },
               'parameters' => {
                 'tone' => {
                   'type' => 'STRING',
                   'default' => 'friendly',
                   'required' => false,
                   'description' => 'The tone of the greeting (e.g., friendly, professional, casual).'
                 }
               }
             }
           )

puts operator.id
```

```bash
LANGUAGE_OPERATOR_OBJ=$(cat << EOF
{
  "displayName": "Personalized Greeting",
  "description": "Creates a personalized, context-aware greeting for a customer.",
  "version": 1,
  "author": "SELF",
  "prompt": "Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile attributes (name, preferences, status) and relevant business knowledge to tailor the message. Return JSON with the greeting text and a brief justification.",
  "outputFormat": "JSON",
  "outputSchema": {
    "type": "object",
    "properties": {
      "greeting": {
        "type": "string"
      },
      "justification": {
        "type": "string"
      }
    }
  },
  "context": {
    "knowledge": {
      "enabled": true
    }
  },
  "parameters": {
    "tone": {
      "type": "STRING",
      "default": "friendly",
      "required": false,
      "description": "The tone of the greeting (e.g., friendly, professional, casual)."
    }
  }
}
EOF
)
curl -X POST "https://intelligence.twilio.com/v3/ControlPlane/Operators" \
--json "$LANGUAGE_OPERATOR_OBJ" \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

```json
{
  "id": "intelligence_operator_01kcgy1ew0e9x8re6jq542zt8b",
  "displayName": "Script Adherence",
  "description": "Creates a personalized, context-aware greeting for a customer.",
  "version": 1,
  "author": "SELF",
  "prompt": "Generate a {{parameters.tone}} greeting for the customer. Use any available customer profile attributes (name, preferences, status) and relevant business knowledge to tailor the message. Return JSON with the greeting text and a brief justification.",
  "outputFormat": "JSON",
  "outputSchema": {
    "type": "object",
    "properties": {
      "score": {
        "type": "integer"
      },
      "explanation": {
        "type": "string"
      }
    },
    "required": [
      "score",
      "explanation"
    ],
    "additionalProperties": false
  },
  "trainingExamples": [
    {
      "input": "This is an example sentence which qualifies the lead as HOT.",
      "output": "{\"score\": 5, \"explanation\": \"The agent followed the script closely and addressed all key points effectively.\"}"
    }
  ],
  "context": {
    "knowledge": {
      "enabled": true
    }
  },
  "parameters": {
    "tone": {
      "type": "STRING",
      "default": "friendly",
      "required": false,
      "description": "The tone of the greeting (e.g., friendly, professional, casual)."
    }
  }
}
```

## Next steps

* Review [custom language operator examples](/docs/conversations/intelligence/custom-language-operator-examples).
