Harness the Power of Stream, Cronofy, and OpenAI for Team Collaboration

7 min read
Jeroen L.
Jeroen L.
Published December 5, 2024

Geographically dispersed teams often have a hard time scheduling meetings that work for all participants. Human Resources departments also face this challenge when working with existing employees and job candidates alike. Employees have the benefit of a defined and somewhat uniform computing environment, job applicants are a whole different challenge. Each candidate uses whatever computer they have available, or runs a variety of operating systems, calendaring packages, and video conferencing utilities. Traditional methods can be time-consuming and may lead to scheduling conflicts or delays in addressing employee concerns.

Let's explore a way to combine Stream Chat, Stream Video, and Cronofy's calendaring features to create an automated and efficient video meeting scheduling process.

By leveraging Stream’s Chat and Video APIs and Cronofy, we can create a streamlined process that allows employees to schedule video meetings through a chat interface easily. We will use AI-assisted routing to help with the scheduling process. This is going to be a proof of concept. If you wanted to do a similar thing in a production environment, you would have to refine the whole process further. However, this implementation proves the usefulness of an AI-supported system.

Running Our Code

To run our code, you need to put a few things on your machine.

  • A current version of Node.js. The current LTS version should do
  • Yarn
  • An account with Stream
  • An account with Cronofy
  • An account for OpenAI API

Clone the following repository to your machine: https://github.com/GetStream/cronofy-meeting-scheduler-nextjs

shell
1
$ git clone https://github.com/GetStream/cronofy-meeting-scheduler-nextjs

Change the directory into the cloned repository and make sure to install all required dependencies.

shell
1
2
$ cd cronofy-meeting-scheduler-nextjs $ yarn install

Before you can run the code, providing your credentials for Stream and Cronofy is important.

You should copy and edit the file .env.template in the root of the repository.

NEXT_PUBLIC_STREAM_API_KEY=  
STREAM_SECRET=  
OPENAI_SERVICE_KEY=

CRONOFY_SDK_IDENTIFIER=  
CRONOFY_API_HOST=  
CRONOFY_SITE_HOST=  
CRONOFY_CLIENT_ID=  
CRONOFY_CLIENT_SECRET=  

Once you entered your credentials, you can run the project locally.

shell
1
$ yarn dev

Benefits of an Integrated Approach

The integrated approach of combining Stream Chat, Video, and Cronofyoffers numerous benefits that significantly enhance the HR scheduling process. First and foremost, this solution dramatically improves efficiency by reducing the time and effort required to schedule HR meetings. By automating much of the scheduling process, HR professionals can focus on more value-added tasks, while employees and candidates can quickly secure the meetings they need without lengthy email exchanges or phone calls.

Accuracy is another key advantage of this system. By leveraging Cronofy's advanced scheduling capabilities, the solution minimizes scheduling conflicts and human error. This ensures that meetings are scheduled at times that work for all parties involved, reducing the frustration and lost productivity associated with double bookings or miscommunications.

The system also prioritizes accessibility, providing a user-friendly interface through Stream Chat for employees and candidates to initiate HR-related requests. This ease of use encourages more frequent and open communication with an HR department. Furthermore, the solution offers flexibility by supporting both in-person and virtual meetings over Stream’s video calling integration, accommodating the diverse needs of modern workplaces, including remote and hybrid work arrangements.

Lastly, the intelligent routing feature ensures that a person’s concerns are directed to the most appropriate HR team members. This targeted approach not only speeds up issue resolution but also ensures that employees receive the most relevant and expert assistance for their specific needs, ultimately leading to more satisfactory outcomes and a more efficient process overall.

Building an AI-Powered Scheduling Assistant with Stream Chat: A Technical Deep Dive

Modern businesses need efficient ways to schedule meetings and coordinate calendars. We've built a sophisticated scheduling assistant that leverages Stream Chat's messaging capabilities, OpenAI's language understanding, and Cronofy's calendar management. Let's explore how these technologies work together to create a seamless scheduling experience.

Core Architecture

The application is built using Next.js and TypeScript, with Stream Chat providing the messaging infrastructure. Here's how the main components interact:

1. Chat Interface

The core chat component manages the real-time messaging experience:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
export default function MyChat({ apiKey, user, token, channelId, }: { apiKey: string; user: User; token: string; channelId: string; }) { const [channel, setChannel] = useState<StreamChannel>(); const [currentState, setCurrentState] = useState<PageState>( PageState.CollectUserInput ); const chatClient = useCreateChatClient({ apiKey: apiKey, tokenOrProvider: token, userData: user, }); useEffect(() => { if (!chatClient) return; const channel = chatClient.channel('messaging', channelId); // Listen for channel updates const extraDataUnsubscribeFunction = channel.on( 'channel.updated', (event) => { const currentState = event.channel?.extra_data?.currentState; updateCurrentState(currentState); } ); // Handle new messages const unsubscribeFunction = channel.on('message.new', (event) => { if (event?.user?.id === user.id && event?.message?.text) { fetch('/api/sendBotResponse', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ channelId: channelId, message: event.message.text, }), }); } }); setChannel(channel); return () => { unsubscribeFunction.unsubscribe(); extraDataUnsubscribeFunction.unsubscribe(); }; }, [chatClient, channelId, user.id]);

This component handles:

  • Chat client initialization

  • Real-time message handling

  • Channel state management

  • Event subscription cleanup

2. AI Integration

The AI component processes user requests using OpenAI's GPT model:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
export async function askOpenAI(message: string): Promise<string> { const openai = new OpenAI({ apiKey: process.env.OPENAI_SERVICE_KEY, }); const systemPrompt = `You are a scheduling assistant. Your task is to help the user plan a meeting with one of the people that are listed. You need to check what the intended purpose of the meeting is and then match with the person that is best suited for the request.`; const listOfPeople = [ 'Simon: HR Specialist for hiring software developers in the early stage', 'Kamil: Specialist for onboarding new employees', 'Simona: HR Specialist for hiring software developers in later stages', 'Paula: Software developer specialized in technical interviews', 'Thierry: CEO determining cultural fit', ]; const completion = await openai.beta.chat.completions.parse({ model: 'gpt-4o-mini', messages: [ { role: 'system', content: systemPrompt }, { role: 'system', content: listOfPeople.join('\n') }, { role: 'user', content: message }, ], response_format: zodResponseFormat(ExpectedOutput, 'event'), });

The AI system:

  • Understands meeting requirements
  • Matches users with appropriate team members
  • Provides contextual responses
  • Validates output using Zod schema
Building your own app? Get early access to our Livestream or Video Calling API and launch in days!

3. Calendar Integration

The calendar system handles multiple aspects of scheduling:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
export default async function listCalenders( accessToken: string, refreshToken: string, channelId: string, userId: string, startDate: string, endDate: string, participants: string[] ) { const cronofyClient = new Cronofy({ client_id: process.env.NEXT_PUBLIC_CRONOFY_CLIENT_ID, client_secret: process.env.CRONOFY_CLIENT_SECRET, access_token: accessToken, refresh_token: refreshToken, }); try { const calendars = await cronofyClient.listCalendars({ access_token: accessToken, }); const calendarArray = calendars.calendars.map((calendar: any) => ({ id: calendar.calendar_id, name: calendar.calendar_name, })); // Send calendar selection message const serverClient = StreamChat.getInstance(apiKey, streamSecret); const channel = serverClient.channel('messaging', channelId); await channel.sendMessage({ text: 'Please select a calendar to add the meeting to.', attachments: [ { type: 'selectCalendar', calendarArray: calendarArray, eventDetails: { start: startDate, end: endDate, participants }, }, ], user_id: 'bot', });

4. Event Creation

When a time slot is selected, the system creates a calendar event with video call integration:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
export default async function createEvent( accessToken: string, refreshToken: string, calendarId: string, startDate: string, endDate: string, channelId: string ) { const cronofyClient = new Cronofy({/*...*/}); // Generate unique event ID const eventId = Math.random().toString(36).substring(2, 15); // Create Stream video call const streamClient = new StreamClient(apiKey, streamSecret); const call = streamClient.video.call("default", eventId); await call.getOrCreate({ data: { created_by_id: "bot", starts_at: new Date(startDate), settings_override: { backstage: { enabled: true, join_ahead_time_seconds: 300, }, }, }, }); // Create calendar event const eventOptions = { calendar_id: calendarId, event_id: eventId, summary: "Meeting with Stream", description: "Today is your lucky day! You get to meet with Stream, hooray!", start: startDate, end: endDate, conferencing: { profile_id: "explicit", provider_description: "Stream Video", join_url: `https://pronto.getstream.io/join/${eventId}`, }, }; await cronofyClient.createEvent(eventOptions);

This process:

  1. Generates a unique event ID
  2. Creates a Stream video call
  3. Adds the event to participants' calendars
  4. Sends confirmation messages

Key Features

1. Intelligent Matching

The system uses AI to understand meeting purposes and match users with appropriate team members based on their roles and expertise.

2. Real-time Updates

Stream Chat's WebSocket connections ensure that all participants receive immediate updates about scheduling progress.

3. Calendar Synchronization

Cronofy integration handles:

  • Calendar authentication
  • Availability checking
  • Event creation
  • Multiple calendar support

4. Video Integration

Stream's video platform is integrated directly into calendar events, providing:

  • Unique meeting links
  • Backstage capabilities
  • Join-ahead functionality

Security and Authentication

The application implements secure authentication flows:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export default function Page() { const searchParams = useSearchParams(); useEffect(() => { const code = searchParams.get('code'); if (code) { initializeCronofy(code).then((returnValue) => { localStorage.setItem('accessToken', returnValue.accessToken); localStorage.setItem('refreshToken', returnValue.refreshToken); localStorage.setItem('sub', returnValue.sub); }); } }, [searchParams]); const scope = 'read_free_busy'; const clientId = process.env.NEXT_PUBLIC_CRONOFY_CLIENT_ID; let url = 'https://app-de.cronofy.com/oauth/authorize?'; url += '&response_type=code'; url += `&client_id=${clientId}`; url += `&redirect_uri=http://localhost:3000/cronofy`; url += `&scope=${scope}`;

Technical Considerations

State Management

The application uses React's useState and useEffect hooks for local state management, while Stream Chat handles real-time state synchronization across clients.

Error Handling

Comprehensive error handling is implemented throughout the application:

  • API error responses
  • Calendar synchronization failures
  • Message delivery issues

Performance

  • Efficient WebSocket connections via Stream Chat
  • Optimized calendar operations
  • Proper cleanup of event listeners

Conclusion

This AI-powered scheduling assistant demonstrates the power of combining multiple technologies to create a seamless, intelligent scheduling experience. By leveraging Stream Chat and Video for mutli-media communication, OpenAI for natural language understanding, and Cronofy for calendar management the application provides a comprehensive solution for modern meeting scheduling needs. The integration of these technologies results in a user-friendly system that can understand scheduling requests, find mutually available times, and set up video calls with minimal user effort.

The modular architecture and use of modern technologies make it highly extensible and maintainable. Stream Chat's reliable infrastructure ensures smooth real-time communication, while integrations with OpenAI and Cronofy add powerful functionality to the core messaging experience.

Ready to revolutionize your team collaboration scheduling process and boost productivity? Stream Chat makes it easy to build powerful, AI-enhanced communication tools like this scheduling assistant. With its robust API and flexible SDKs, you can create custom chat experiences that seamlessly integrate with AI services and third-party tools.

Don't just read about it – experience it for yourself! Sign up for a free Stream account today and start building your own intelligent real-time communication apps. Whether you're looking to streamline scheduling, enhance customer support, or create engaging social features, Stream provides the foundation you need to bring your ideas to life.

Integrating Video With Your App?
We've built a Video and Audio solution just for you. Check out our APIs and SDKs.
Learn more ->