Skip to main content
Direct Line API 3.0

Direct Line API 3.0

You can enable communication between your bot and Unity by using the Direct Line API. I will explain how to do it in Unity but also provide some information about the mechanism.

Authentication

Direct Line API 3.0 requests can be authenticated either by using a secret that you obtain from the Direct Line channel configuration page in the Azure Portal or by using a token that you obtain at runtime.

  • A Direct Line secret is a master key that can be used to access any conversation that belongs to the associated bot. A secret can also be used to obtain a token. Secrets do not expire.
  • A Direct Line token is a key that can be used to access a single conversation. A token expires but can be refreshed.

Starting conversation

Additional Reading

Direct Line conversations are explicitly opened by clients and may run as long as the bot and client participate and have valid credentials. While the conversation is open, both the bot and client may send messages.

More than one client may connect to a given conversation and each client may participate on behalf of multiple users.

To open conversation, issue a POST Request to the endpoint

POST https://directline.botframework.com/v3/directline/conversations
Authorization: Bearer `SECRET` OR `TOKEN`

If the request is successful, the response will contain an ID for the conversation, a token, a value that indicates the number of seconds until the token expires, and a stream URL that the client may use to receive activities.

{
    "conversationId": "-ABC-",
    "token": "-123-",
    "expires_in": 3600,
    "streamUrl": "wss://directline.botframework.com/v3/directline/conversations/-ABC-/stream?watermark=-&t=-123-",
    "referenceGrammarId": "ddf0cd2c-b093-595c-b951-8431afebed17"
}

To perform this action in Unity, we have to:

internal IEnumerator StartConversation()
{
  // Compose Directline Endpoint
  string conversationEndpoint = string.Format("{0}/conversations", botEndpoint);

  // Create a empty webform to perform post
  WWWForm webForm = new WWWForm();

  // Call HTTP Service with Unity - See https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html
  using (UnityWebRequest uwr = UnityWebRequest.Post(conversationEndpoint, webForm))
  {
    // Define Auth header
    uwr.SetRequestHeader("Authorization", "Bearer " + botSecret);
    // Define temp storage for answer
    uwr.downloadHandler = new DownloadHandlerBuffer();

    // Send & Wait for answer
    yield return uwr.SendWebRequest();

    // Manage answer if no faillure
    if (uwr.result != UnityWebRequest.Result.Success)
    {
      Debug.LogError($"BOT | StartConversation | Request error: {uwr.error} \n Status: {uwr.responseCode.ToString()}");
    }
    else
    {
      // Catch the answer
      string jsonResponse = uwr.downloadHandler.text;

      // Create Conversation to store authentication
      conversation = new Conversation();
      conversation = JsonUtility.FromJson<Conversation>(jsonResponse);

      // Create Activities to store conversation messages
      activities = new Activities();

      // Set the Bot Status
      conversationStarted = true; 

      // Request a first "introduction" from the Bot
      if(greetings)
      {
        // The following call is necessary to create and inject an activity of type "conversationUpdate" to get greetings from your bot
        StartCoroutine(SendMessageToBot("", botId, botName, "conversationUpdate"));
      }
    }
  }
}

Sending messages

Additional Reading By using Direct Line API, Unity can send messages to your bot by issuing HTTP POST requests.

You may send a single message per request.

To send a message to the bot, the client must create an Activity and then issue a request to https://directline.botframework.com/v3/directline/conversations/{conversationId}/activities, specifying the Activity object in the body of the request.

POST https://directline.botframework.com/v3/directline/conversations/abc123/activities
Authorization: Bearer RCurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0
Content-Type: application/json
[other headers]
{
    "locale": "en-EN",
    "type": "message",
    "from": {
        "id": "user1"
    },
    "text": "hello"
}

When the activity is delivered to the bot, the service responds with an HTTP status code that reflects the bot’s status code. If the POST is successful, the response contains a JSON payload that specifies the ID of the Activity that was sent to the bot.

private IEnumerator SendMessageToBot(string message, string activityType)
{
    // Compose Directline Endpoint
    string activityEndpoint = string.Format("{0}/conversations/{1}/activities", botEndpoint, conversation.conversationId);

    // Create a empty webform to perform post
    WWWForm webForm = new WWWForm();

    // Create a new activity
    Activity activity = new Activity();
    // Provide Conversation Id
    activity.conversation = new ConversationReference();
    activity.conversation.id = conversation.conversationId;
    // Provide Sender Information
    activity.from = new UserAccount();
    activity.from.id = playerId;
    activity.from.name = playerName;
    // Provide Message
    activity.text = message;
    // Provide content Type
    activity.type = activityType;
    // Provide Channel used
    activity.channelId = "DirectLineChannelId";

    // Serialize the activity
    string json = JsonUtility.ToJson(activity);

    // Call HTTP Service with Unity - See https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html
    using (UnityWebRequest uwr = UnityWebRequest.Post(activityEndpoint, webForm))
    {
        // Define Auth header
        uwr.SetRequestHeader("Authorization", "Bearer " + botSecret);
        // Define temp storage for answer
        uwr.downloadHandler = new DownloadHandlerBuffer();
        // Define
        uwr.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(json));
        // Define Content format
        uwr.uploadHandler.contentType = "application/json";

        // Send & Wait for answer
        yield return uwr.SendWebRequest();

        // Manage answer if no faillure
        if (uwr.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError($"BOT | StartConversation | Request error: {uwr.error} \n Status: {uwr.responseCode.ToString()}");
        }
        else
        {
            // Catch the answer
            string jsonResponse = uwr.downloadHandler.text;

            // Create ActivtyReference to store latest message
            activityReference = new ActivityReference();
            activityReference = JsonUtility.FromJson<ActivityReference>(jsonResponse);
            // Add a timestamp
            activityReference.time = Time.time;

            // Get the Bot Service Answer
            StartCoroutine(GetResponseFromBot(activity));
        }
    }
}

Receiving messages

Using Direct Line API 3.0, a client can receive messages from your bot either via WebSocket stream or by issuing HTTP GET requests. Using either of these techniques, a client may receive multiple messages from the bot at a time as part of an ActivitySet. For more information, see Receive activities from the bot.

Conversation

Message

Share (for immortality)

Laurent LEFEVRE avatar

Laurent LEFEVRE

Producer

I'm a Microsoft employee, working on Technology Strategy for large Enterprise account. I focus on industry business trends and explain how you can leverage Azure Game Stack & Xbox services. I assume that I don't know anything. This is a great habit to do a full knowledge refresh and avoiding bias.