How to Build an AI Employee Satisfaction Survey System
Deploy surveys and analyze results with AI to identify sentiment trends.
Jay Banlasan
The AI Systems Guy
Employee satisfaction surveys collect data. But most companies never do anything useful with the responses. I built an ai employee satisfaction survey analysis system that deploys surveys, processes open-ended answers with AI, and surfaces the actual patterns hiding in the feedback.
The AI does what a human analyst would take days to do. It reads every response, groups themes, and flags urgent issues.
What You Need Before Starting
- Python 3.8+
- An AI API key (Claude for text analysis)
- A survey distribution method (email or Slack)
- SQLite for storing responses
Step 1: Design the Survey Template
SURVEY_TEMPLATE = {
"title": "Q1 2025 Employee Satisfaction",
"questions": [
{"id": "q1", "type": "rating", "text": "How satisfied are you with your role? (1-10)"},
{"id": "q2", "type": "rating", "text": "How well does your manager support you? (1-10)"},
{"id": "q3", "type": "rating", "text": "How likely are you to recommend working here? (1-10)"},
{"id": "q4", "type": "open", "text": "What is working well right now?"},
{"id": "q5", "type": "open", "text": "What would you change if you could?"},
{"id": "q6", "type": "open", "text": "Is there anything you need that you do not have?"}
],
"anonymous": True
}
Step 2: Store Responses
import sqlite3
import json
def init_survey_db(db_path="surveys.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS responses (
id INTEGER PRIMARY KEY AUTOINCREMENT,
survey_id TEXT,
department TEXT,
answers_json TEXT,
submitted_at TEXT
)
""")
conn.commit()
return conn
def save_response(conn, survey_id, department, answers):
from datetime import datetime
conn.execute(
"INSERT INTO responses (survey_id, department, answers_json, submitted_at) VALUES (?,?,?,?)",
(survey_id, department, json.dumps(answers), datetime.now().isoformat())
)
conn.commit()
Step 3: Analyze Open-Ended Responses with AI
import anthropic
client = anthropic.Anthropic()
def analyze_open_responses(responses):
all_text = ""
for r in responses:
answers = json.loads(r[3])
for key, value in answers.items():
if isinstance(value, str) and len(value) > 10:
all_text += f"- {value}\n"
prompt = f"""Analyze these anonymous employee survey responses.
Responses:
{all_text[:4000]}
Return a JSON report:
{{
"top_themes": ["list of 5 recurring themes"],
"positive_highlights": ["what employees appreciate most"],
"concerns": ["issues that need attention, ranked by frequency"],
"urgent_flags": ["anything suggesting immediate action needed"],
"sentiment_score": 0-100,
"recommended_actions": ["3-5 specific actions leadership should take"]
}}"""
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}]
)
return json.loads(message.content[0].text)
Step 4: Calculate Quantitative Scores
def calculate_scores(conn, survey_id):
rows = conn.execute(
"SELECT department, answers_json FROM responses WHERE survey_id=?",
(survey_id,)
).fetchall()
dept_scores = {}
for dept, answers_json in rows:
answers = json.loads(answers_json)
if dept not in dept_scores:
dept_scores[dept] = {"ratings": [], "count": 0}
for key, value in answers.items():
if isinstance(value, (int, float)):
dept_scores[dept]["ratings"].append(value)
dept_scores[dept]["count"] += 1
for dept in dept_scores:
ratings = dept_scores[dept]["ratings"]
dept_scores[dept]["average"] = round(sum(ratings) / len(ratings), 1) if ratings else 0
return dept_scores
Step 5: Generate the Executive Summary
def generate_summary(quantitative, qualitative):
report = "# Employee Satisfaction Report\n\n"
report += "## Scores by Department\n\n"
report += "| Department | Avg Score | Responses |\n|---|---|---|\n"
for dept, data in quantitative.items():
report += f"| {dept} | {data['average']}/10 | {data['count']} |\n"
report += f"\n## Sentiment Score: {qualitative['sentiment_score']}/100\n\n"
report += "## Key Themes\n\n"
for theme in qualitative["top_themes"]:
report += f"- {theme}\n"
report += "\n## Recommended Actions\n\n"
for action in qualitative["recommended_actions"]:
report += f"1. {action}\n"
return report
What to Build Next
Add trend tracking that compares this quarter's results to last quarter. Plot sentiment over time so you can see whether changes you made actually improved anything. The survey is just input. The trend line is the insight.
Related Reading
- The Feedback Loop That Powers Everything - why feedback loops are the foundation of good operations
- AI-Powered Reporting That Actually Gets Read - making reports people actually use
- How to Audit Your Operations for AI Opportunities - finding where AI adds the most value
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment