DEV Community

Cover image for Using Direct Line API in a React Native Application with Axios to connect to Copilot Studio Agent
Vivek Yadav
Vivek Yadav

Posted on

Using Direct Line API in a React Native Application with Axios to connect to Copilot Studio Agent

This document details the usage of the Microsoft Direct Line API in a React Native application, using JavaScript, Axios, and WebSocket for communication with a Copilot Agent Bot.


Pre-requisites

Before proceeding, ensure the following are in place:

1. Direct Line Secret: Obtain the Direct Line secret from the Coilot chat Bot.

2. React Native Development Environment: Set up a working React Native project.

3. Axios Library Installed: Add Axios to your project dependencies using npm install axios or yarn add axios.

4. WebSocket Support: Ensure the WebSocket API is compatible with your application environment.

5. Basic Knowledge: Familiarity with JavaScript, React Native, and RESTful APIs.


Table of Contents

  1. Authentication

  2. Generating Token

  3. Refreshing the Token

  4. Starting the Conversation

  5. Reconnecting the Conversation

  6. Sending Activity to the Bot

  7. Receiving Activity from the Bot

  8. Ending the Conversation

  9. Connection Status Monitoring and Reconnection

  10. References


1. Authentication

Direct Line API requires a secret to authenticate. Obtain the secret from the Azure Bot Service portal.


2. Generating Token

Tokens are generated using the secret to initiate secure communication.

Code Example:

import axios from 'axios';

const generateToken = async (secret) => {
    const url = 'https://directline.botframework.com/v3/directline/tokens/generate';
    try {
        const response = await axios.post(url, {}, {
            headers: {
                Authorization: `Bearer ${secret}`,
            },
        });
        return response.data.token;
    } catch (error) {
        console.error('Error generating token:', error);
        throw error;
    }
};
Enter fullscreen mode Exit fullscreen mode

3. Refreshing the Token

Tokens have a limited lifespan. Refresh them before they expire.

Code Example:

const refreshToken = async (token) => {
    const url = 'https://directline.botframework.com/v3/directline/tokens/refresh';
    try {
        const response = await axios.post(url, {}, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        return response.data.token;
    } catch (error) {
        console.error('Error refreshing token:', error);
        throw error;
    }
};
Enter fullscreen mode Exit fullscreen mode

4. Starting the Conversation

Initiate a conversation with the bot using the token.

Code Example:

const startConversation = async (token) => {
    const url = 'https://directline.botframework.com/v3/directline/conversations';
    try {
        const response = await axios.post(url, {}, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        return response.data;
    } catch (error) {
        console.error('Error starting conversation:', error);
        throw error;
    }
};
Enter fullscreen mode Exit fullscreen mode

5. Reconnecting the Conversation

If the connection is lost, you can reconnect using the conversationId and WebSocket.

Code Example:

const reconnectConversation = async (conversationId, token) => {
    const url = `https://directline.botframework.com/v3/directline/conversations/${conversationId}?watermark=0`;
    try {
        const response = await axios.get(url, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        return response.data;
    } catch (error) {
        console.error('Error reconnecting conversation:', error);
        throw error;
    }
};
Enter fullscreen mode Exit fullscreen mode

6. Sending Activity to the Bot

Send user messages or activities to the bot.

Code Example:

const sendActivity = async (conversationId, token, activity) => {
    const url = `https://directline.botframework.com/v3/directline/conversations/${conversationId}/activities`;
    try {
        const response = await axios.post(url, activity, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
        return response.data;
    } catch (error) {
        console.error('Error sending activity:', error);
        throw error;
    }
};
Enter fullscreen mode Exit fullscreen mode

7. Receiving Activity from the Bot

Use WebSocket to listen for bot responses in real time.

Code Example:

const connectWebSocket = (streamUrl, onMessage) => {
    const socket = new WebSocket(streamUrl);

    socket.onopen = () => {
        console.log('WebSocket connection established.');
    };

    socket.onmessage = (event) => {
        const data = JSON.parse(event.data);
        console.log('Message received:', data);
        onMessage(data.activities);
    };

    socket.onerror = (error) => {
        console.error('WebSocket error:', error);
    };

    socket.onclose = (event) => {
        console.warn('WebSocket connection closed:', event);
    };

    return socket;
};
Enter fullscreen mode Exit fullscreen mode

8. Ending the Conversation

Explicitly end a conversation by ceasing communication.

Note: Direct Line API doesn’t require an explicit API call to "end" a conversation.


9. Connection Status Monitoring and Reconnection

Monitor the WebSocket status for errors and disconnects. If a WebSocket connection fails, fallback to polling to retrieve activities from the bot.

To simplify the implementation, ensure conversationId and token are stored in a higher scope or accessible context.

Code Example:

const monitorConnection = (socket, fallbackToPolling) => {
    socket.onclose = () => {
        console.warn('WebSocket connection closed. Falling back to polling.');
        fallbackToPolling();
    };
};

// Define fallbackToPolling without requiring explicit parameters
const fallbackToPolling = () => {
    console.log('Starting polling to receive activities.');
    const url = `https://directline.botframework.com/v3/directline/conversations/${conversationId}/activities`;

    try {
        const intervalId = setInterval(async () => {
            const response = await axios.get(url, {
                headers: {
                    Authorization: `Bearer ${token}`,
                },
            });
            if (response.data.activities && response.data.activities.length) {
                console.log('Activities received via polling:', response.data.activities);
            }
        }, 3000); // Poll every 3 seconds

        // Optionally clear the interval when conditions are met
        // clearInterval(intervalId);

    } catch (error) {
        console.error('Error during polling:', error);
    }
};
Enter fullscreen mode Exit fullscreen mode

Key Adjustments:

  1. Global Variables: Ensure conversationId and token are stored globally or in a context accessible by fallbackToPolling.
let conversationId = ''; // Set this during conversation start
let token = '';          // Set this during token generation
Enter fullscreen mode Exit fullscreen mode
  1. Simplified Invocation: Since fallbackToPolling doesn't take explicit arguments, ensure that it references these globally scoped variables.

This approach ensures that fallbackToPolling functions correctly when called without parameters.


10. References

Conclusion

This document provides a complete guide to integrate Direct Line API into a React Native application using Axios and WebSocket. Follow the outlined steps to authenticate, manage conversations, and handle communication reliably with a Copilot Agent Bot.

Top comments (0)