Back to apps
AI Company Assistant
A company assistant powered by AI that answers employee questions using your internal data. Ask about team contacts, sales performance, HR policies, or any company information. Built with Windmill scripts as tools that the AI can call to fetch real-time data.
- Frontend in React 19
- Windmill flow with built-in AI agent step for backend
- Fully customizable AI agent step (knowledge base, AI provider, tools, ...)
- Windmill scripts as tools for the AI agent to fetch real-time data
ReactAI AgentFlowsScripts
Add to my workspaceFiles
frontend
App.tsx
index.tsx
index.css
wmill.ts
package.json
backend
sendAiMessage
getMarketingActivations
getSalesMetrics
1import React, { useState, useEffect, useRef } from 'react'2import { backend } from './wmill'3import './index.css'45type Message = { role: "user" | "assistant"; content: string; timestamp?: Date; toolsUsed?: string[] };67const SYSTEM_PROMPT = `You are Boris, the internal AI assistant for Acme Corporation...89## Company Overview10- **Company Name**: Acme Corporation11- **CEO**: Sarah Johnson12- **Number of Employees**: 450+1314## Key Contacts15- **HR Director**: Maria Garcia (maria.garcia@acme.com)16- **IT Support**: helpdesk@acme.com or ext. 55551718## Payroll & Compensation19- **Pay Schedule**: Bi-weekly, every other Friday20- **Annual Raises**: Performance reviews in March, raises effective April 1st2122## Time Off & Leave23- **PTO Policy**: 20 days per year for all full-time employees24- **Sick Leave**: 10 days per year (separate from PTO)25- **Parental Leave**: 16 weeks paid for primary caregivers`;2627const SUGGESTIONS = [28 "When is payday?",29 "Who is in charge of HR?",30 "How many sales did we make this week?",31 "Which marketing campaign had the highest ROI?",32];3334type Tool = {35 id: string;36 name: string;37 description: string;38 enabled: boolean;39 backendMethod: string;40};4142const TOOLS: Tool[] = [43 {44 id: 'get_sale_metrics',45 name: 'Sales Metrics',46 description: 'Triggers a script that gets sales metrics from the last 30 days',47 enabled: true,48 backendMethod: 'c',49 },50 {51 id: 'get_marketing_activations',52 name: 'Marketing Activations',53 description: 'Triggers a script that gets marketing activations from the last 30 days',54 enabled: true,55 backendMethod: 'b',56 },57];5859const App = () => {60 const [messages, setMessages] = useState<Message[]>([]);61 const [input, setInput] = useState('');62 const [loading, setLoading] = useState(false);63 const [activeTab, setActiveTab] = useState<'chat' | 'context' | 'tools'>('chat');64 const messagesEndRef = useRef<HTMLDivElement>(null);6566 async function sendMessage(e: React.FormEvent) {67 e.preventDefault();68 if (!input.trim() || loading) return;6970 const userMessage = input.trim();71 setInput('');72 setLoading(true);7374 setMessages(prev => [...prev, { role: 'user', content: userMessage, timestamp: new Date() }]);7576 try {77 const response = await backend.sendAiMessage({78 message: userMessage,79 });80 setMessages(prev => [...prev, { role: 'assistant', content: response, timestamp: new Date() }]);81 } catch (e) {82 console.error('Failed to send message:', e);83 }84 setLoading(false);85 }8687 return (88 <div className="chat-app">89 <div className="chat-container">90 <header className="chat-header">91 <div className="header-left">92 <div className="bot-avatar"><BotIcon /></div>93 <div className="header-info">94 <h1>Boris</h1>95 <span className="subtitle">AI Assistant</span>96 </div>97 </div>98 </header>99100 <div className="tabs">101 <button className={`tab ${activeTab === 'chat' ? 'active' : ''}`} onClick={() => setActiveTab('chat')}>102 Chat103 </button>104 <button className={`tab ${activeTab === 'context' ? 'active' : ''}`} onClick={() => setActiveTab('context')}>105 Knowledge Base106 </button>107 <button className={`tab ${activeTab === 'tools' ? 'active' : ''}`} onClick={() => setActiveTab('tools')}>108 Tools109 </button>110 </div>111112 {activeTab === 'chat' && (113 <main className="messages-container">114 {messages.length === 0 ? (115 <div className="empty-state">116 <h2>Hi, I'm Boris!</h2>117 <p>Ask me anything about your company</p>118 <div className="suggestions">119 {SUGGESTIONS.map((suggestion, idx) => (120 <button key={idx} className="suggestion-btn" onClick={() => setInput(suggestion)}>121 {suggestion}122 </button>123 ))}124 </div>125 </div>126 ) : (127 <div className="messages-list">128 {messages.map((msg, idx) => (129 <div key={idx} className={`message-wrapper ${msg.role}`}>130 <div className="message-bubble">131 <div className="message-content">{msg.content}</div>132 </div>133 </div>134 ))}135 </div>136 )}137 </main>138 )}139 </div>140 </div>141 )142}143144export default App