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
- Authentication 
- Generating Token 
- Refreshing the Token 
- Starting the Conversation 
- Reconnecting the Conversation 
- Sending Activity to the Bot 
- Receiving Activity from the Bot 
- Ending the Conversation 
- Connection Status Monitoring and Reconnection 
- 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;
    }
};
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;
    }
};
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;
    }
};
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;
    }
};
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;
    }
};
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;
};
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);
    }
};
Key Adjustments:
- 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
- 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
- Microsoft Direct Line API Documentation
- WebSocket API
- Axios Documentation
- React Native Documentation
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 (2)
On which chat window can we see the copilot messages ?
You can refer to Github repo to create React based Chat UI application with Direct Line implementation to communicate with copilot studio bot.
github.com/vcse59/DirectLine-Copil...