Create Your First Service Flows

This tutorial will guide you through creating service flows on the MelodyArc Platform. Service flows consist of a series of points that outline how tasks are serviced. In this example, the service flows will handle receiving, processing, servicing, and responding to a task. The concepts covered, although simplified for demonstration purposes, are fundamental to building robust, production-ready service flows.

Prerequisites

To successfully complete this tutorial, you will need:

  • An active MelodyArc account
  • Permissions to create points within MelodyArc
  • Permissions to service tasks of type "expert" within MelodyArc
  • Ideally, a basic understanding of JavaScript and HTTP requests

New to MelodyArc?

To get started with MelodyArc, reach out to book a demo.

Setup

This tutorial will use the experts page within the MelodyArc Portal and a few Platform APIs.

On the experts page, ensure "All Points" is selected as the point set.

Create Configuration

When the MelodyArc Platform receives a task, it checks if a configuration can be applied. The configuration is applied if its inputs are triggered by undirected fill.

We will create a configuration that activates when a task has a value of customer_service in the data token path of task.intent. Configurations orchestrate how tasks are serviced by segmenting points based on flows. These flows define which points can be evaluated by undirected fill based on their belonging to one or more groupings called "partitions".

Steps

Click the + next to "Configuration" to create a new configuration. Enter the following required information:

📘

Optional information

Points and configurations have required and optional properties. If a property is not mentioned in this tutorial, assume you can leave it blank.

Metadata

  • Name: first_service_tutorial

Inputs

We will define one input.

  • Path: task.intent
  • Operator: equals
  • Value: customer_service

Tags

  • MelodyArc Tags: service_tutorial

Flows

We will make six flows.

Flow 1

  • Name: Get context
  • Partitions: context

Flow 2

  • Name: Prepare context
  • Partitions: prepare_context

Flow 3

  • Name: Prepare service
  • Partitions: prepare_service

Flow 4

  • Name: Service
  • Partitions: service

Flow 5

  • Name: Response
  • Partitions: response

Flow 6

  • Name: Debug
  • Partitions: debug

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "first_service_tutorial",
  "partition": "",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "when": [
    {
      "task.intent": {
        "evaluate": "=customer_service"
      }
    }
  ],
  "flows": [
    {
      "action": "undirected_fill",
      "details": {
        "name": "Get context",
        "partitions": [
          "context"
        ],
        "components": "enabled",
        "repeatable": false,
        "allow_additional_outputs": true,
        "on_multiple_points": "sequential",
        "on_no_points": "error",
        "max_points": 20
      }
    },
    {
      "action": "undirected_fill",
      "details": {
        "name": "Prepare context",
        "partitions": [
          "prepare_context"
        ],
        "components": "enabled",
        "repeatable": false,
        "allow_additional_outputs": true,
        "on_multiple_points": "sequential",
        "on_no_points": "error",
        "max_points": 20
      }
    },
    {
      "action": "undirected_fill",
      "details": {
        "name": "Prepare service",
        "partitions": [
          "prepare_service"
        ],
        "components": "enabled",
        "repeatable": false,
        "allow_additional_outputs": true,
        "on_multiple_points": "sequential",
        "on_no_points": "error",
        "max_points": 20
      }
    },
    {
      "action": "undirected_fill",
      "details": {
        "name": "Service",
        "partitions": [
          "service"
        ],
        "components": "enabled",
        "repeatable": false,
        "allow_additional_outputs": true,
        "on_multiple_points": "sequential",
        "on_no_points": "error",
        "max_points": 20
      }
    },
    {
      "action": "undirected_fill",
      "details": {
        "name": "Response",
        "partitions": [
          "response"
        ],
        "components": "enabled",
        "repeatable": false,
        "allow_additional_outputs": true,
        "on_multiple_points": "sequential",
        "on_no_points": "error",
        "max_points": 20
      }
    },
    {
      "action": "undirected_fill",
      "details": {
        "name": "Debug",
        "partitions": [
          "debug"
        ],
        "components": "enabled",
        "repeatable": false,
        "allow_additional_outputs": true,
        "on_multiple_points": "sequential",
        "on_no_points": "error",
        "max_points": 20
      }
    }
  ],
  "search_resource_type": "configuration"
}

Prevent Task Closing

First, we will prepare for debugging by creating an invoke point that prevents our test task from closing. This invoke will call a code point that is available by default.

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_prevent_close
  • Friendly Name: Prevent Task from Closing
  • Partition: debug

Inputs

We will define one input.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define three attributes.

Attribute 1

  • Key: friendly_name
  • Value: Prevent Task from Closing

Attribute 2

  • Key: description
  • Value: Prevent task from closing

Attribute 3

  • Key: instructions
  • Value: Prevent task from closing

Code

  • Code: prevent_task_close

Confirm Creation

Select Yes and click Submit.

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_prevent_close",
  "partition": "debug",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    }
  },
  "attributes": {
    "friendly_name": "Prevent Task from Closing",
    "description": "Prevent task from closing",
    "instructions": "Prevent task from closing"
  },
  "code": "prevent_task_close",
  "search_resource_type": "invoke"
}

🚧

Preventing a task from closing

Preventing a task from closing prevents it from completing. In production, this can add unintended behaviors. Preventing close should only be used for configuration or testing.

Send Task

We will now send a task to the ingress webhook. In the request, we will include information to trigger the configuration and simulate a service request. The simulated service request will contain information about a customer and a message describing their request.

Steps

Go to the ingress webhook API here. Enter the following required information:

  • authorization: A valid JWT for your organization.
  • domain: The webhook domain of your organization.
  • organization_id: The unique identifier of your organization.
  • id: tutorial1001
  • dedupe_key: tutorial1001
  • type: expert
  • task_type: expert
  • data: Enter the below JSON
{
    "task": {
        "intent": "customer_service"
    },
    "customer": {
        "email": "[email protected]",
        "message": "Hi,\n\nI think I accidentally ordered 5 of the Colombo bed. Meant to only order 1. Can you confirm if I did that?\n\nLiam"
    }
}

📘

Sending multiple tasks

The easiest way to send multiple tasks for testing is to change the values of the id and dedupe_key.

⚙️

Create via curl

Creation can also be achieved by sending the curl request below and updating the webhook domain, organization_id and jwt.

curl
curl --location 'https://<replace_webhook_domain>.melodyarc.app/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <replace_jwt>' \
--data-raw '{
  "organization_id": "<replace_organization_id>",
  "dedupe_key": "tutorial1001",
  "id": "tutorial1001",
  "type": "expert",
  "task_type": "expert",
  "data": {
    "task": {
      "intent": "customer_service"
    },
    "customer": {
      "email": "[email protected]",
      "message": "Hi,\n\nI think I accidentally ordered 5 of the Colombo bed. Meant to only order 1. Can you confirm if I did that?\n\nLiam"
    }
  }
}'

Open the Task

Go to the "Monitoring" page. If your configuration was done successfully, you will see the task you created. Click on the task id to open.

We will use the MelodyArc Portal to view the token of this task. You can view the tokens by opening the "Expert Tools" panel located in the top right.

🤔

No points or components

While a configuration was successfully activated for this task, we have not yet configured points to activate.

Retrieve Customer Information

We will now begin servicing the task. For this demo, we are using mock data from DummyJSON.

First, we will retrieve the customers information based on their email. To do this we will write a code point, to retrieve the order via an API call, and a corresponding invoke point to trigger this code point via undirected fill based on data received in the task.

Create Code Point

On the experts page, click the + next to "Code" to create a new code point. Enter the following required information:

Metadata

  • Name: tutorial_get_customer
  • Friendly Name: Tutorial - Get Customer
  • Partition: context

Tags

  • MelodyArc Tags: service_tutorial

Code

  • Code: Enter the below:
const email = _token.customer.email ?? "";
async function execute_process() {
    try {
        const res = await fetch(`https://dummyjson.com/users/filter?key=email&value=${email}`);
        const response = await res.json();
        return {
            "customer.user": response.users[0],
            "agent_helpers.metadata.friendly_name": _token.friendly_name,
            "agent_helpers.metadata.description": _token.description,
            "agent_helpers.metadata.instructions": _token.instructions
        };
    } catch (error) {
        return {
            "customer.user": "API failure",
            "agent_helpers.metadata.friendly_name": null,
            "agent_helpers.metadata.description": null,
            "agent_helpers.metadata.instructions": null
        };
    }
};

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_get_customer",
  "partition": "context",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "code": "const email = _token.customer.email ?? \"\";\nasync function execute_process() {\n    try {\n        const res = await fetch(`https://dummyjson.com/users/search?q=${email}`);\n        const response = await res.json();\n        return {\n            \"customer.user\": response.users[0],\n            \"agent_helpers.metadata.friendly_name\": _token.friendly_name,\n            \"agent_helpers.metadata.description\": _token.description,\n            \"agent_helpers.metadata.instructions\": _token.instructions\n        };\n    } catch (error) {\n        return {\n            \"customer.user\": \"API failure\",\n            \"agent_helpers.metadata.friendly_name\": null,\n            \"agent_helpers.metadata.description\": null,\n            \"agent_helpers.metadata.instructions\": null\n        };\n    }\n}",
  "imports": [],
  "parameters": [],
  "language": "JavaScript",
  "version": "latest",
  "search_resource_type": "code"
}

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_get_customer
  • Friendly Name: Tutorial - Get Customer
  • Partition: context

Inputs

We will define two inputs.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Input 2

  • Path: customer.email
  • Operator: exists
  • Description: Customer email is present

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define three attributes.

Attribute 1

  • Key: friendly_name
  • Value: Tutorial - Get Customer

Attribute 2

  • Key: description
  • Value: Retrieve mock customer data

Attribute 3

  • Key: instructions
  • Value: Retrieve customer data from external service

Code

  • Code: tutorial_get_customer

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_get_customer",
  "partition": "context",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    },
    "customer.email": {
      "evaluate": true,
      "description": "Customer email is present"
    }
  },
  "attributes": {
    "friendly_name": "Tutorial - Get Customer",
    "description": "Retrieve mock customer data",
    "instructions": "Retrieve customer data from external service"
  },
  "code": "tutorial_get_customer",
  "search_resource_type": "invoke"
}

Testing

Test your flow after each step. To test, select the task on the monitoring page and choose restart from the actions. Alternatively, you can click restart in the top menu of the agent task view.

Return to task once restarted and see if expected values have been written to the data token.

📘

Undirected fill logs

The expert tool panel contains logs for undirected fill within the "bot token" under the key "undirected".

Retrieve Orders

Next, we will augment our context by bringing in the customer's orders based on their user id.

Create Code Point

On the experts page, click the + next to "Code" to create a new code point. Enter the following required information:

Metadata

  • Name: tutorial_get_orders
  • Friendly Name: Tutorial - Get Orders
  • Partition: context

Tags

  • MelodyArc Tags: service_tutorial

Code

  • Code: Enter the below:
// get user id from token
const user_id = _token.customer.user.id ?? "";
async function execute_process() {
    try {
        const res = await fetch(`https://dummyjson.com/carts/user/${user_id}`);
        const response = await res.json();
        return {
            "orders": response.carts[0],
            "agent_helpers.metadata.friendly_name": _token.friendly_name,
            "agent_helpers.metadata.description": _token.description,
            "agent_helpers.metadata.instructions": _token.instructions
        };
    } catch (error) {
        return {
            "orders": "API failure",
            "agent_helpers.metadata.friendly_name": null,
            "agent_helpers.metadata.description": null,
            "agent_helpers.metadata.instructions": null
        };
    }
    };

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_get_orders",
  "partition": "context",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "code": "const user_id = _token.customer.user.id ?? \"\";\nasync function execute_process() {\n    try {\n        const res = await fetch(`https://dummyjson.com/carts/user/${user_id}`);\n        const response = await res.json();\n        return {\n            \"orders\": response.carts[0],\n            \"agent_helpers.metadata.friendly_name\": _token.friendly_name,\n            \"agent_helpers.metadata.description\": _token.description,\n            \"agent_helpers.metadata.instructions\": _token.instructions\n        };\n    } catch (error) {\n        return {\n            \"orders\": \"API failure\",\n            \"agent_helpers.metadata.friendly_name\": null,\n            \"agent_helpers.metadata.description\": null,\n            \"agent_helpers.metadata.instructions\": null\n        };\n    }\n    };",
  "imports": [],
  "parameters": [],
  "language": "JavaScript",
  "version": "latest",
  "search_resource_type": "code"
}

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_get_orders
  • Friendly Name: Tutorial - Get Orders
  • Partition: context

Inputs

We will define two inputs.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Input 2

  • Path: customer.user.id
  • Operator: exists
  • Description: Customer user id exists

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define three attributes.

Attribute 1

  • Key: friendly_name
  • Value: Tutorial - Get Orders

Attribute 2

  • Key: description
  • Value: Retrieve mock customer orders

Attribute 3

  • Key: instructions
  • Value: Retrieve customer data from external service

Code

  • Code: tutorial_get_orders

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_get_orders",
  "partition": "context",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    },
    "customer.user.id": {
      "evaluate": true,
      "description": "Customer user id exists"
    }
  },
  "attributes": {
    "friendly_name": "Tutorial - Get Orders",
    "description": "Retrieve mock customer data",
    "instructions": "Retrieve customer data from external service"
  },
  "code": "tutorial_get_orders",
  "search_resource_type": "invoke"
}

Prepare Context

Now that we have the customers data we are going to prepare it for agents. To do this we will configure a set of code and invoke points that create an order history view in markdown.

Create Code Point

On the experts page, click the + next to "Code" to create a new code point. Enter the following required information:

Metadata

  • Name: tutorial_create_order_history
  • Friendly Name: Tutorial - Create Order History
  • Partition: prepare_context

Tags

  • MelodyArc Tags: service_tutorial

Code

  • Code: Enter the below:
// Function to convert order details to markdown format
const createOrderHistory = (json) => {
    let markdown = `# Order Details\n\n`;

    markdown += `**Order ID:** ${json.id ?? 'N/A'}\n\n`;
    markdown += `**User ID:** ${json.userId ?? 'N/A'}\n\n`;
    markdown += `**Total Products:** ${json.totalProducts ?? 'N/A'}\n\n`;
    markdown += `**Total Quantity:** ${json.totalQuantity ?? 'N/A'}\n\n`;
    markdown += `**Total Price:** $${(json.total ?? 0).toFixed(2)}\n\n`;
    markdown += `**Total Discounted Price:** $${(json.discountedTotal ?? 0).toFixed(2)}\n\n`;

    markdown += `## Products\n\n`;

    (json.products ?? []).forEach((product) => {
        markdown += `### ${product.title ?? 'No title'}\n\n`;
        markdown += `![${product.title ?? 'No title'}](${product.thumbnail ?? ''})\n\n`;
        markdown += `- **Product ID:** ${product.id ?? 'N/A'}\n`;
        markdown += `- **Price:** $${(product.price ?? 0).toFixed(2)}\n`;
        markdown += `- **Quantity:** ${product.quantity ?? 'N/A'}\n`;
        markdown += `- **Total:** $${(product.total ?? 0).toFixed(2)}\n`;
        markdown += `- **Discount Percentage:** ${product.discountPercentage ?? 0}%\n`;
        markdown += `- **Discounted Total:** $${(product.discountedTotal ?? 0).toFixed(2)}\n\n`;
    });

    return markdown;
};

// Orders object from the token
const orders = _token.orders ?? {};

async function execute_process() {
    // Create order history markdown
    const order_history = createOrderHistory(orders);

    return {
        "reference.order_history": order_history,
        "agent_helpers.metadata.friendly_name": _token.friendly_name,
        "agent_helpers.metadata.description": _token.description,
        "agent_helpers.metadata.instructions": _token.instructions
    };
};

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
  {
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_create_order_history",
  "partition": "prepare_context",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "code": "// Function to convert order details to markdown format\nconst createOrderHistory = (json) => {\n    let markdown = `# Order Details\\n\\n`;\n\n    markdown += `**Order ID:** ${json.id ?? 'N/A'}\\n\\n`;\n    markdown += `**User ID:** ${json.userId ?? 'N/A'}\\n\\n`;\n    markdown += `**Total Products:** ${json.totalProducts ?? 'N/A'}\\n\\n`;\n    markdown += `**Total Quantity:** ${json.totalQuantity ?? 'N/A'}\\n\\n`;\n    markdown += `**Total Price:** $${(json.total ?? 0).toFixed(2)}\\n\\n`;\n    markdown += `**Total Discounted Price:** $${(json.discountedTotal ?? 0).toFixed(2)}\\n\\n`;\n\n    markdown += `## Products\\n\\n`;\n\n    (json.products ?? []).forEach((product) => {\n        markdown += `### ${product.title ?? 'No title'}\\n\\n`;\n        markdown += `![${product.title ?? 'No title'}](${product.thumbnail ?? ''})\\n\\n`;\n        markdown += `- **Product ID:** ${product.id ?? 'N/A'}\\n`;\n        markdown += `- **Price:** $${(product.price ?? 0).toFixed(2)}\\n`;\n        markdown += `- **Quantity:** ${product.quantity ?? 'N/A'}\\n`;\n        markdown += `- **Total:** $${(product.total ?? 0).toFixed(2)}\\n`;\n        markdown += `- **Discount Percentage:** ${product.discountPercentage ?? 0}%\\n`;\n        markdown += `- **Discounted Total:** $${(product.discountedTotal ?? 0).toFixed(2)}\\n\\n`;\n    });\n\n    return markdown;\n};\n\n// Orders object from the token\nconst orders = _token.orders ?? {};\n\nasync function execute_process() {\n    // Create order history markdown\n    const order_history = createOrderHistory(orders);\n\n    return {\n        \"reference.order_history\": order_history,\n        \"agent_helpers.metadata.friendly_name\": _token.friendly_name,\n        \"agent_helpers.metadata.description\": _token.description,\n        \"agent_helpers.metadata.instructions\": _token.instructions\n    };\n}\n",
  "imports": [],
  "parameters": [],
  "language": "JavaScript",
  "version": "latest",
  "search_resource_type": "code"
}

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_create_order_history
  • Friendly Name: Tutorial - Create Order History
  • Partition: prepare_context

Inputs

We will define two inputs.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Input 2

  • Path: orders.id
  • Operator: exists
  • Description: Orders exist

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define three attributes.

Attribute 1

  • Key: friendly_name
  • Value: Tutorial - Create Order History

Attribute 2

  • Key: description
  • Value: Create markdown order history view

Attribute 3

  • Key: instructions
  • Value: Create markdown order history view

Code

  • Code: tutorial_create_order_history

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_create_order_history",
  "partition": "prepare_context",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    },
    "orders.id": {
      "evaluate": true,
      "description": "Orders exist"
    }
  },
  "attributes": {
    "friendly_name": "Tutorial - Create Order History",
    "description": "Create markdown order history view",
    "instructions": "Create markdown order history view"
  },
  "code": "tutorial_create_order_history",
  "search_resource_type": "invoke"
}

Create Response Template

We will create a template, often called a blurb, for how the response to the customer should look. We will house this blurb in a value point.

Create Value Point

On the experts page, click the + next to "Value" to create a new value point. Enter the following required information:

Metadata

  • Name: tutorial_response_template
  • Friendly Name: Tutorial - Response Template
  • Partition: service_tutorial

Inputs

This value will have no inputs. Delete blank inputs to proceed.

Tags

  • MelodyArc Tags: service_tutorial

Value

Select Markdown

  • Value: Enter the below:
Hi [Customer Name],

[Message goes here]

Let us know if we can help with anything else,

Customer Service

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_response_template",
  "partition": "service_tutorial",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "value": "Hi [Customer Name],\n\n[Message goes here]\n\nLet us know if we can help with anything else,\n\nCustomer Service",
  "search_resource_type": "value"
}

Create Entities

We are ready to service the task. We will create an entity to run the service points. Entities enable points to run multiple times across different context. Each task type has a defined key which houses entities. For us, the key is entity. We will create a set of code and invoke points to set values in the entity key.

🤔

Why use an entity?

We are using an entity in this tutorial to demonstrate how to create entities and activate points within one. An entity is not actually needed for the tutorial use case. In production, entities are widely used to allow branches of service to occur across elements in the entity array.

Create Code Point

On the experts page, click the + next to "Code" to create a new code point. Enter the following required information:

Metadata

  • Name: tutorial_create_service_entities
  • Friendly Name: Tutorial - Create Service Entities
  • Partition: service

Tags

  • MelodyArc Tags: service_tutorial

Code

  • Code: Enter the below:
async function execute_process() {
    const data = {
        type: "service",
        id: _token.customer.user.id ?? "none",
    };

    return {
        "entity": [
            ...(_token.entity ?? []),
            data
        ],
        "agent_helpers.metadata.friendly_name": _token.friendly_name,
        "agent_helpers.metadata.description": _token.description,
        "agent_helpers.metadata.instructions": _token.instructions
    };
};

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON

{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_create_service_entities",
  "partition": "service",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "code": "async function execute_process() {\n    const data = {\n        type: \"service\",\n        id: _token.customer.user.id ?? \"none\",\n    };\n\n    return {\n        \"entity\": [\n            ...(_token.entity ?? []),\n            data\n        ],\n        \"agent_helpers.metadata.friendly_name\": _token.friendly_name,\n        \"agent_helpers.metadata.description\": _token.description,\n        \"agent_helpers.metadata.instructions\": _token.instructions\n    };\n};",
  "imports": [],
  "parameters": [],
  "language": "JavaScript",
  "version": "latest",
  "search_resource_type": "code"
}

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_create_service_entities
  • Friendly Name: Tutorial - Create Service Entities
  • Partition: service

Inputs

We will define two inputs.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Input 2

  • Path: orders.id
  • Operator: exists
  • Description: Orders exist

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define three attributes.

Attribute 1

  • Key: friendly_name
  • Value: Tutorial - Create Service Entities

Attribute 2

  • Key: description
  • Value: Create markdown order service entities

Attribute 3

  • Key: instructions
  • Value: Create markdown order service entities

Code

  • Code: tutorial_create_service_entities

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_create_service_entities",
  "partition": "service",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    },
    "orders.id": {
      "evaluate": true,
      "description": "Orders exist"
    }
  },
  "attributes": {
    "friendly_name": "Tutorial - Create Service Entities",
    "description": "Create markdown order service entities",
    "instructions": "Create markdown order service entities"
  },
  "code": "tutorial_create_service_entities",
  "search_resource_type": "invoke"
}

Create Procedure

We will use a procedure template to service this task. A procedure template makes it easy for AI agents to service a task and prompt a human agent for review. For the tutorial, we will set this procedure to always require human agent review.

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_service_customer_procedure
  • Friendly Name: Tutorial - Service Customer
  • Partition: service

Inputs

We will define two inputs.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Input 2

  • Path: _this.type
  • Operator: equals
  • Value: service
  • Description: Entity type is service

📘

Path with _this

_this is used to activate points in entities. Any invoke that has one or more paths with _this will activate in an entity. More information can be found here.

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define four attributes.

Attribute 1

  • Key: friendly_name
  • Value: Tutorial - Service Customer

Attribute 2

  • Key: description
  • Value: Service procedures for tutorial

Attribute 3

  • Key: instructions, change to Markdown
  • Value: Enter the below:
You are an expert Customer Service Agent.  
# Purpose
Create a response to the customer's request.
# Instructions  
> [!NOTE]
> 🤖😀 Steps to be followed by AI and human Agents

## Step 1 - Review Customer Information
- Name: [[customer.user.firstName]] [[customer.user.lastName]]

## Step 2 - Read Customer Message

<details><summary>Message</summary>  

[[customer.message]]
</details>

## Step 3 - Review Order History

<details><summary>Order History</summary>  

[[reference.order_history?{}]]
</details>

## Step 4 - Write a Response to the Customer

Write a concise response to the customer's message.

Use the following template as a guide, replace anything enclosed in brackets and use GitHub Markdown to format line breaks. 

### Response Template
[[@tutorial_response_template]]

## Step 5 - Apply Overrides  
If present, apply instruction overrides found in Appendix.

# Appendix
## Instruction Overrides  
Alter instructions with any feedback provided here:  

📘

Fill text

The procedure instructions use fill text to dynamically populate text from the data token and value points. Note we utilize the value point we created earlier.

Attribute 4

  • Key: system_message, change to Markdown
  • Value: Enter the below:
You are an expert Customer Service Agent.  

### Generate JSON Response  
Create a JSON object with a top level key of `_this` with the following element:
  - `response`: The response to the customer. Use GitHub markdown to format the response, use \n for line breaks.

Create a 50 character or less summary justifying why this response was written. Add this to the JSON output with the key "summary" at the root level.

Add a key called "markdown" at the root level with a value of the same response to the customer. Use GitHub markdown to format the response, use \n for line breaks.

#### Example format:
```json
{
  "summary": "Response generated based on customer's message about delayed delivery.",
  "markdown": "Hi Jane Doe,\n\nThank you for reaching out regarding your recent order. We apologize for the inconvenience caused by the delayed delivery. Our team is currently investigating the issue and we will provide you with an update as soon as possible.\n\nLet us know if we can help with anything else,\nCustomer Service",
  "_this": 
    {
      "response": "Hi Jane Doe,\n\nThank you for reaching out regarding your recent order. We apologize for the inconvenience caused by the delayed delivery. Our team is currently investigating the issue and we will provide you with an update as soon as possible.\n\nLet us know if we can help with anything else,\nCustomer Service"
    }
}
```

Code

  • Code: procedure

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_service_customer_procedure",
  "partition": "service",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    },
    "_this.type": {
      "evaluate": "=service",
      "description": "Entity type is service"
    }
  },
  "attributes": {
    "friendly_name": "Tutorial - Service Customer",
    "description": "Service procedures for tutorial",
    "instructions": "You are an expert Customer Service Agent.  \n# Purpose\nCreate a response to the customer's request.\n# Instructions  \n> [!NOTE]\n> 🤖😀 Steps to be followed by AI and human Agents\n\n## Step 1 - Review Customer Information\n- Name: [[customer.user.firstName]] [[customer.user.lastName]]\n\n## Step 2 - Read Customer Message\n\n<details><summary>Message</summary>  \n\n[[customer.message]]\n</details>\n\n## Step 3 - Review Order History\n\n<details><summary>Order History</summary>  \n\n[[reference.order_history?{}]]\n</details>\n\n## Step 4 - Write a Response to the Customer\n\nWrite a concise response to the customer's message.\n\nUse the following template as a guide, replace anything enclosed in brackets and use GitHub Markdown to format line breaks. \n\n### Response Template\n[[@tutorial_response_template]]\n\n## Step 5 - Apply Overrides  \nIf present, apply instruction overrides found in Appendix.\n\n# Appendix\n## Instruction Overrides  \nAlter instructions with any feedback provided here:  \n",
    "system_message": "You are an expert Customer Service Agent.  \n\n### Generate JSON Response  \nCreate a JSON object with a top level key of `_this` with the following element:\n  - `response`: The response to the customer. Use GitHub markdown to format the response, use \\n for line breaks.\n\nCreate a 50 character or less summary justifying why this response was written. Add this to the JSON output with the key \"summary\" at the root level.\n\nAdd a key called \"markdown\" at the root level with a value of the same response to the customer. Use GitHub markdown to format the response, use \\n for line breaks.\n\n#### Example format:\n```json\n{\n  \"summary\": \"Response generated based on customer's message about delayed delivery.\",\n  \"markdown\": \"Hi Jane Doe,\\n\\nThank you for reaching out regarding your recent order. We apologize for the inconvenience caused by the delayed delivery. Our team is currently investigating the issue and we will provide you with an update as soon as possible.\\n\\nLet us know if we can help with anything else,\\nCustomer Service\",\n  \"_this\": \n    {\n      \"response\": \"Hi Jane Doe,\\n\\nThank you for reaching out regarding your recent order. We apologize for the inconvenience caused by the delayed delivery. Our team is currently investigating the issue and we will provide you with an update as soon as possible.\\n\\nLet us know if we can help with anything else,\\nCustomer Service\"\n    }\n}\n```"
  },
  "code": "procedure",
  "search_resource_type": "invoke"
}

Review Procedure Component

The procedure component will now display to prompt human agent review.

Component parts include:

  • Agent instructions (blue square)
  • A markdown preview of the proposed response (green square)
  • Justification for the proposed response (purple square)
  • Option to provide feedback to the AI agent for revision (yellow square)

Select the purple option and click submit to continue.

Create a Key

To simulate sending a response, we will use Webhook Tester. Webhook Tester creates a dynamic endpoint for receiving messages via HTTP calls.

The site will provide a unique webhook URL like: https://webhook-test.com/9f785021d3e66100bf7448230b48f64d

We will store the long number at the end as a key point. Key points are used to store confidential values. While this number is not confidential, we will treat it like it is to learn how to create key points.

Key points cannot be created via the experts page and must be created via API.

Steps

Go to the key point API here. Enter the following required information:

  • authorization: A valid API token for your organization.
  • domain: The API domain of your organization.
  • organization_id: The unique identifier of your organization.
  • name: __tutorial_webhook_key
  • description: Temporary key for service tutorial
  • value: The URL number, e.g. 9f785021d3e66100bf7448230b48f64d

⚙️

Create via curl

Creation can also be achieved by sending the curl request below and updating the api_domain, organization_id, value and api_key.

curl
curl --request PUT \
     --url https://<replace_api_domain>.melodyarc.app/api/v1/points/key \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-api-key: <relace_api_key>' \
     --data '
{
  "organization_id": "<replace_organization_id>",
  "name": "__tutorial_webhook_key",
  "value": "<replace_value>"
}
'

Send Response

To complete this tutorial we will send the response to the webhook. To do this we will create a code point that uses the key we created as a parameter and a corresponding invoke point.

Create Code Point

On the experts page, click the + next to "Code" to create a new code point. Enter the following required information:

Metadata

  • Name: tutorial_send_response
  • Friendly Name: Tutorial - Send Response
  • Partition: response

Tags

  • MelodyArc Tags: service_tutorial

Attributes

  • Parameters: Add __tutorial_webhook_key and hit enter. Note that you will need to type in the key name as only value points populate in search.

Code

  • Code: Enter the below:
//get key
const key = __tutorial_webhook_key ?? "no_key";

//get response
const payload = _this.response ?? "no response found";

// send response to webhook function
async function sendToWebhook(payload) {
    const webhookUrl = `https://webhook-test.com/${key}`;

    const response = await fetch(webhookUrl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
    });

    if (!response.ok) {
        throw new Error('Webhook POST request failed');
    }
};

async function execute_process() {

    const response = await sendToWebhook(payload); // send webhook
    return {
        [`${get_entity_string()}.response_result`]: response ?? "no response",
        "agent_helpers.metadata.friendly_name": _token.friendly_name,
        "agent_helpers.metadata.description": _token.description,
        "agent_helpers.metadata.instructions": _token.instructions
    };
};

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
{
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_send_response",
  "partition": "response",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "code": "//get key\nconst key = __tutorial_webhook_key ?? \"no_key\";\n\n//get response\nconst payload = _this.response ?? \"no response found\";\n\n// send response to webhook function\nasync function sendToWebhook(payload) {\n    const webhookUrl = `https://webhook-test.com/${key}`;\n\n    const response = await fetch(webhookUrl, {\n        method: 'POST',\n        headers: {\n            'Content-Type': 'application/json'\n        },\n        body: JSON.stringify(payload)\n    });\n\n    if (!response.ok) {\n        throw new Error('Webhook POST request failed');\n    }\n};\n\nasync function execute_process() {\n\n    const response = await sendToWebhook(payload); // send webhook\n    return {\n        [`${get_entity_string()}.response_result`]: response ?? \"no response\",\n        \"agent_helpers.metadata.friendly_name\": _token.friendly_name,\n        \"agent_helpers.metadata.description\": _token.description,\n        \"agent_helpers.metadata.instructions\": _token.instructions\n    };\n};",
  "imports": [],
  "parameters": [
    "__tutorial_webhook_key"
  ],
  "language": "JavaScript",
  "version": "latest",
  "search_resource_type": "code"
}

Create Invoke Point

On the experts page, click the + next to "Invoke" to create a new invoke point. Enter the following required information:

Metadata

  • Name: tutorial_send_response
  • Friendly Name: Tutorial - Send Response
  • Partition: response

Inputs

We will define two inputs.

Input 1

  • Path: task.intent
  • Operator: equals
  • Value: customer_service
  • Description: Task is for customer service demo

Input 2

  • Path: _this.response
  • Operator: exists
  • Description: Tutorial response exists

Tags

  • MelodyArc Tags: service_tutorial

Attributes

We will define three attributes.

Attribute 1

  • Key: friendly_name
  • Value: Tutorial - Send Response

Attribute 2

  • Key: description
  • Value: Send response for tutorial

Attribute 3

  • Key: instructions
  • Value: Send response to webhook

Code

  • Code: tutorial_send_response

Confirm Creation

Select Yes and click Submit

⚙️

Create with JSON

Alternatively, creation can also be achieved by selecting the "Show JSON" box on the top toolbar. Then, paste the following content and update the organization_id.

JSON
 {
  "organization_id": "<replace_organization_id>",
  "name": "tutorial_send_response",
  "partition": "response",
  "description": "",
  "tags": [
    "service_tutorial"
  ],
  "inputs": {
    "task.intent": {
      "evaluate": "=customer_service",
      "description": "Task is for customer service demo"
    },
    "_this.response": {
      "evaluate": true,
      "description": "Tutorial response exists"
    }
  },
  "attributes": {
    "friendly_name": "Tutorial - Send Response",
    "description": "Send response for tutorial",
    "instructions": "Send response to webhook"
  },
  "code": "tutorial_send_response",
  "search_resource_type": "invoke"
}

Task Serviced

You should see the response appear on Webhook Tester.

Complete

You have completed the tutorial and successfully created a full service flow! 🥳

The concepts learned are the same used in production builds that service thousands of tasks. Please explore the MelodyArc Platform and Resources documents to learn more.