Get Answers▪️Capture Knowledge ▪️Save Time

AI Assistant and Knowledge Management for your Slack

For companies with 100 or more employees. Calculate your own ROI.
Learn more about the NextKS features.
For companies with 100 or more employees. Calculate your own time savings.
const voiceBtn = document.getElementById('voiceBtn'); const voiceLabel = document.getElementById('voiceLabel'); const waveform = document.getElementById('waveform'); const spinner = document.getElementById('spinner'); const statusBox = document.getElementById('statusBox'); const statusText = document.getElementById('statusText'); const listeningSpinner = document.getElementById('listeningDots'); const phoneIcon = document.getElementById('phoneIcon'); const pickUpPhoneIcon = 'https://img.icons8.com/windows/32/ringer-volume.png'; const hangUpPhoneIcon = 'https://img.icons8.com/windows/32/call-disconnected.png'; const STATE = { IDLE: 'idle', INIT: 'initializing', MICINIT: 'initializing mic', LISTEN: 'listening', PROC: 'processing', SPEAK: 'speaking' }; let currentState = STATE.IDLE; let ws, audioCtx, micNode, procNode, inputStream; let playbackQueue = []; let isEndOfStream = false; let isPlaying = false; let currentSource = null; function logState(to) { console.log(`→ State: ${to}`); currentState = to; switch (to) { case STATE.IDLE: statusBox.style.display = 'inline-flex'; phoneIcon.src = pickUpPhoneIcon; voiceLabel.innerHTML = 'Ask anything'; spinner.classList.remove('active'); waveform.classList.remove('active'); statusText.textContent = '(AI Voice Assistant)'; listeningSpinner.style.display = 'none'; break; case STATE.INIT: statusBox.style.display = 'inline-flex'; phoneIcon.src = hangUpPhoneIcon; voiceLabel.innerText = 'Hang up'; spinner.classList.add('active'); waveform.classList.remove('active'); statusText.textContent = 'Connecting…'; listeningSpinner.style.display = 'none'; break; case STATE.MICINIT: statusBox.style.display = 'inline-flex'; phoneIcon.src = hangUpPhoneIcon; voiceLabel.innerText = 'Hang up'; spinner.classList.add('active'); waveform.classList.remove('active'); statusText.textContent = 'Initializing mic…'; listeningSpinner.style.display = 'none'; break; case STATE.LISTEN: statusBox.style.display = 'inline-flex'; phoneIcon.src = hangUpPhoneIcon; voiceLabel.innerText = 'Hang up'; spinner.classList.remove('active'); waveform.classList.remove('active'); statusText.textContent = "I'm listening"; listeningSpinner.style.display = 'inline-flex'; break; case STATE.PROC: statusBox.style.display = 'inline-flex'; phoneIcon.src = hangUpPhoneIcon; voiceLabel.innerText = 'Hang up'; spinner.classList.add('active'); waveform.classList.remove('active'); statusText.textContent = 'Thinking, just a sec…'; listeningSpinner.style.display = 'none'; break; case STATE.SPEAK: statusBox.style.display = 'inline-flex'; phoneIcon.src = hangUpPhoneIcon; voiceLabel.innerText = 'Hang up'; spinner.classList.remove('active'); waveform.classList.add('active'); statusText.textContent = ''; listeningSpinner.style.display = 'none'; break; } } voiceBtn.onclick = () => { if (currentState === STATE.IDLE) { startSession(); } else { stopSession(); } }; function stopSession() { console.log('Stopping session…'); ws.send(JSON.stringify({ event: 'stop_session' })); ws.close(); if (currentSource) { currentSource.stop(); currentSource = null; } playbackQueue = []; isEndOfStream = true; isPlaying = false; teardownAudio(); logState(STATE.IDLE); } async function startSession() { logState(STATE.INIT); /* 1) Check server health */ try { const resp = await fetch('https://voice-assistant-927518067979.europe-west1.run.app'); if (!resp.ok) throw new Error(`Status ${resp.status}`); console.log('Server healthy, opening WS…'); } catch (err) { console.error('Server health check failed:', err); return; /* bail out */ } ws = new WebSocket('wss://voice-assistant-927518067979.europe-west1.run.app/ws'); ws.onopen = () => { console.log('WS open, sending handshake'); ws.send(JSON.stringify({ event: 'handshake', thread_id: localStorage.getItem('thread_id') || null })); }; ws.onmessage = async (evt) => { /* 1) Control messages (JSON text) */ if (typeof evt.data === 'string') { let msg; try { msg = JSON.parse(evt.data); } catch (e) { console.warn('Bad JSON from server:', evt.data); return; } switch (msg.event) { case 'handshake_ack': console.log('Handshake ACK, thread_id=', msg.thread_id); localStorage.setItem('thread_id', msg.thread_id); await startMic(); logState(STATE.PROC); break; case 'utterance_done': console.log('Received utterance_done → marking end of stream'); isEndOfStream = true; break; default: console.warn('ws.onmessage unknown event:', msg.event); } return; } if (evt.data instanceof Blob || evt.data instanceof ArrayBuffer) { playbackQueue.push(evt.data); if (currentState !== STATE.SPEAK) { logState(STATE.SPEAK); playLoop(); } return; } /* 3) Anything else */ console.warn('ws.onmessage received unexpected data type:', evt.data); }; ws.onclose = (e) => { console.log('WebSocket closed:', e.code, e.reason); teardownAudio(); logState(STATE.IDLE); }; ws.onerror = (e) => { console.error('WebSocket error:', e); }; } async function startMic() { logState(STATE.MICINIT); audioCtx = new AudioContext({ sampleRate: 24000 }); const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const mic = audioCtx.createMediaStreamSource(stream); const proc = audioCtx.createScriptProcessor(4096, 1, 1); proc.onaudioprocess = (e) => { if (currentState !== STATE.LISTEN) return; const inF32 = e.inputBuffer.getChannelData(0); const int16 = new Int16Array(inF32.length); for (let i = 0; i < inF32.length; i++) { const s = Math.max(-1, Math.min(1, inF32[i])); int16[i] = s < 0 ? s * 0x8000 : s * 0x7FFF; } ws.send(int16.buffer); }; mic.connect(proc); proc.connect(audioCtx.destination); micNode = mic; procNode = proc; inputStream = stream; /*logState(STATE.INIT);*/ /*detectSilence(audioCtx, mic, proc, stream);*/ } function teardownAudio() { if (procNode) { procNode.disconnect(); procNode = null; } if (micNode) { micNode.disconnect(); micNode = null; } if (inputStream) { inputStream.getTracks().forEach(t => t.stop()); inputStream = null; } if (audioCtx && audioCtx.state !== 'closed') { audioCtx.close(); } audioCtx = null; } function detectSilence(ctx, mic, proc, stream) { const analyser = ctx.createAnalyser(); mic.connect(analyser); analyser.fftSize = 512; const data = new Uint8Array(analyser.frequencyBinCount); const thresh = 9; const delay = 1500; let speechStarted = false; let silentSince = null; (function check() { analyser.getByteFrequencyData(data); const avg = data.reduce((a,b)=>a+b,0)/data.length; if (!speechStarted) { if (avg >= thresh) { speechStarted = true; console.log('Speech started—now watching for silence'); silentSince = Date.now(); } } else { if (avg < thresh) { /* if silence continues long enough, stop */ if (Date.now() - silentSince > delay) { console.log('Silence detected → end_audio (mic still open)'); logState(STATE.PROC); ws.send(JSON.stringify({ event: 'end_audio' })); return; } } else { /* reset timer while speech continues */ silentSince = Date.now(); } } requestAnimationFrame(check); })(); } async function playLoop() { if (isPlaying) return; isPlaying = true; if (!window.__playCtx) { window.__playCtx = new AudioContext(); await window.__playCtx.resume(); } const ctx = window.__playCtx; logState(STATE.SPEAK); const FRAME_RATE = 24000; while (!isEndOfStream || playbackQueue.length > 0) { if (playbackQueue.length === 0) { await new Promise(r => setTimeout(r, 50)); continue; } const raw = playbackQueue.shift(); let buf; if (raw instanceof Blob) { buf = await raw.arrayBuffer(); } else { buf = raw; } if (buf.byteLength === 0) continue; const int16 = new Int16Array(buf); const f32 = new Float32Array(int16.length); for (let i = 0; i < int16.length; i++) { f32[i] = int16[i] / 32768; } const audioBuf = ctx.createBuffer(1, f32.length, FRAME_RATE); audioBuf.copyToChannel(f32, 0); const src = ctx.createBufferSource(); src.buffer = audioBuf; src.connect(ctx.destination); currentSource = src; /* 4) Wait its true duration*/ await new Promise(resolve => { src.onended = () => { if (currentSource === src) currentSource = null; resolve(); }; src.start(); }); } console.log('✅ Playback complete'); isEndOfStream = false; isPlaying = false; logState(STATE.LISTEN); detectSilence(audioCtx, micNode, procNode, inputStream); } logState(STATE.IDLE);

“..it has proven to be a game-changer for us.”
Dmitry Olenov, Director of Technical Support, Lokalise

25-person team saved
450 hours in just 7 months

"..the perfect balance between cutting-edge AI technology and human collaboration."

"Aligning seamlessly with our long-term vision, NextKS is setting a new standard..."

Instant setup & instant benefits

Get started with a one-click setup and a 15-minute onboarding. Enjoy instant improvements without any extra headaches.

Your 1st line of sales support

Equip your sales team with instant answers to pricing, playbooks, objections, and product details - so they can close deals faster.

No more language barriers

Now, you can access knowledge and get answers instantly in any language - no matter what language it’s in.

No AI training or migration

No extra processes, no discruptive changes. Keep using Slack, Confluence, web docs, and your current tools. NextKS plugs in seamlessly.

100+ hours saved/month

Free up your best talents from answering repetitive Q&A. Save up to 20% of your employes' time McKinsey & Company research

Leadership dashboards

Gain instant visibility into team knowledge flow, gaps, and risks - turning survey data and Q&A activity into actionable insights.

Uncover the Cost of Inefficient Communication

Business Calculator



Results:

✅ Your inefficient internal knowledge sharing costs you approximately 0 every year.

✅ In total, NextKS can recover 0 hours every year in your organization for more productive activities.

✅ In your sales team alone, it's equivalent to adding 0 FTEs (Full Time Employee) without hiring costs.

✅ This means that your revenue can be theoretically higher by 0 every year.


👉 The total theoretical value of NextKS in your case is 0 every year.

Features

Slack-native Q&A workflow

Continuous learning

Leadership dashboards

NextKS Framework helps your team get answers instantly, without endless back-and-forth. It uses AI to respond directly in Slack or routes questions to the right expert, cutting down wasted time and reducing bottlenecks. No more digging through threads or waiting for replies - just fast, accurate answers when and where you need them.

1. AI-Powered Intelligent Chat

Engage with a smart assistant that taps into your company-wide knowledge, directly from Slack. Powered by AI, the NextKS Assistant provides instant, insightful responses based on your team's collective expertise. Say goodbye to long waits and embrace quick, reliable answers without leaving your workspace.

2. Integrated Question Ticketing System

Easily turn unresolved queries into tickets that automatically involve only the relevant experts—no spam or unnecessary disturbances for the rest of the team. This Slack-based system ensures smooth collaboration, so you get the right answer, fast, with minimal distractions.

3. Smart Knowledge Retention

Once a question is answered and accepted, it’s stored in a dynamic, company-wide knowledge base for future use, ensuring that every question is answered only once. With each interaction, your team builds a long-lasting resource that continuously grows and improves, giving you access to previously solved problems at your fingertips.

4. Expert Discovery & Connection

Automatically connect with the right experts across your company when the AI can’t provide an answer. The system ensures that only those with the knowledge are involved, making knowledge-sharing efficient and focused. Stop searching for answers—NextKS brings the experts directly to you, within Slack.

5. Platform Analytics

This analytics dashboard provides you with all essential metrics related to the platform's usage. You can track the adoption rate, trending topics, and the approximate number of hours the tool saved in your organization.

Testimonials

Dmitry Olenov, Director of Technical Support at Lokalise.

We recently began integrating the NextKS tool to enhance our internal technical support, and it has proven to be a game-changer for us. Aligning seamlessly with our long-term vision, NextKS is setting a new standard for how Internal Support should function on a company level.
It's the solution we have been dreaming of ...
Read the full text

Dmitry Olenov, Director of Technical Support at Lokalise.

We recently began integrating the NextKS tool to enhance our internal technical support, and it has proven to be a game-changer for us. Aligning seamlessly with our long-term vision, NextKS is setting a new standard for how Internal Support should function on a company level.
During the early stages of implementation, feedback from our support managers and staff has been overwhelmingly positive. It's the solution we have been dreaming of, striking the perfect balance between cutting-edge AI technology and human collaboration. This synergy provides us with an efficient, scalable and streamlined support experience.
Remarkably, we've observed an increase in incoming inquiries, as people are less hesitant to ask questions when those are private. Simultaneously, the number of requests needing dedicated Support specialist intervention has decreased significantly, demonstrating NextKS's effectiveness in empowering users and resolving issues autonomously. We are excited about the continued positive impact this tool will have on our operations and growth.

Lokalise Case Study

About Us

At NextKS, we’re on a mission to drive team growth and efficiency by simplifying knowledge sharing.Our vision is simple:
To make work life easier - by turning knowledge sharing into a seamless, frustration-free experience.
We believe that work life should be easier, more enjoyable, and free from constant frustration. We understand that when information is buried in endless messages, documents, or locked away in people’s heads, it holds your team back. We’ve designed NextKS to eliminate those obstacles by making knowledge sharing effortless, intuitive, and accessible to everyone - no matter where they are or what language they speak. With a powerful AI Assistant and a streamlined Q&A workflow, we ensure that your team can focus on what truly matters: doing their best work and enjoying the process.Welcome to a new era of collaboration and knowledge sharing.
Welcome to NextKS.

Team

Milan Karásek
Lead Software Engineer

Tomas Franc
Founder, CEO

Designed by Tomas Franc, winner of the Process Innovation Challenge for North America 2

Liam James
Founder’s Associate (Biz Dev focus)

Join Our Early Access Program

We’re looking for fast-growing companies to help us shape the future of knowledge sharing.
Here’s what you’ll get:

50% Off Your First Invoice
Get a one-time 50% discount when you activate your account - no long-term commitment required.

Locked-In Discounts
Secure access to limited early adopter pricing before public launch. No surprise upcharges later.

Early Adopter Perks
Help shape the product roadmap with direct access to our founding team. Your feedback will influence features, workflows, and UX.

Recognition
Gain recognition as an innovator - we’ll spotlight your team’s success (with your permission) in future case studies.

 

Spots are limited - reach out and let’s see if your team’s a good fit.

Pricing Plans

AnnuallyMonthly

Compact

$699/ m (50 users)
+ extra 50 users: $99/ m
$599/ m (50 users)
+ extra 50 users: $89/ m
  • Intelligent chat and knowledge-sharing via Slack
  • Question ticketing system for team collaboration
  • Vector-based storage for Knowledge retention
  • Basic analytics - ticket volume, knowledge usage, time saved
  • Basic support - email support & online knowledge base
  • 2 hours of assisted training and onboarding
function check() { var checkBox = document.getElementById("checbox"); var text1 = Array.prototype.slice.call(document.getElementsByClassName("text1")); var text2 = Array.prototype.slice.call(document.getElementsByClassName("text2")); for (var i = 0; i < text1.length; i++) { if (checkBox.checked) { text1[i].style.display = "block"; text2[i].style.display = "none"; } else { text1[i].style.display = "none"; text2[i].style.display = "block"; } } } check();

*Prices exclude VAT. VAT is charged where applicable based on EU regulations.