Create an AI Writing Coach: Real-Time Feedback That Actually Improves Your Writing
Build a writing assistant that gives actionable feedback on clarity, structure, tone, and style. Not just grammar — real coaching.
Grammar checkers catch typos. Writing coaches improve thinking. There’s a chasm between “your comma is wrong” and “your argument structure buries the most compelling point in paragraph four.” Most writing tools operate in the grammar checker lane. This tutorial builds a genuine writing coach.
Our AI writing coach analyzes clarity, structure, argument strength, tone, and readability. It gives specific, actionable feedback that makes writing genuinely better — not just grammatically correct. And it does it in real time, as you write.
What We’re Building

A writing analysis tool that:
- Evaluates text across five dimensions: clarity, structure, tone, argument strength, and readability
- Provides specific, actionable improvement suggestions
- Shows readability metrics (Flesch-Kincaid, sentence length distribution)
- Offers before/after rewrites for weak sections
- Adapts feedback style to writing context (blog, email, academic, business)
Tech Stack
- Python 3.11+
- Streamlit for the web interface
- Claude API for writing analysis
- textstat for readability metrics
- Plotly for visualization
Step 1: Readability Analysis Engine

import textstat
import re
from collections import Counter
def analyze_readability(text: str) -> dict:
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if s.strip()]
words = text.split()
sentence_lengths = [len(s.split()) for s in sentences]
return {
"flesch_reading_ease": textstat.flesch_reading_ease(text),
"flesch_kincaid_grade": textstat.flesch_kincaid_grade(text),
"gunning_fog": textstat.gunning_fog(text),
"word_count": len(words),
"sentence_count": len(sentences),
"avg_sentence_length": sum(sentence_lengths) / max(len(sentence_lengths), 1),
"max_sentence_length": max(sentence_lengths) if sentence_lengths else 0,
"paragraph_count": text.count("\n\n") + 1,
"passive_voice_estimate": estimate_passive(text),
"adverb_count": count_adverbs(text),
"sentence_length_distribution": sentence_lengths
}
def estimate_passive(text: str) -> int:
passive_patterns = [
r'\b(was|were|been|being|is|are|am)\s+\w+ed\b',
r'\b(was|were|been|being|is|are|am)\s+\w+en\b',
]
count = 0
for pattern in passive_patterns:
count += len(re.findall(pattern, text, re.IGNORECASE))
return count
def count_adverbs(text: str) -> int:
adverb_pattern = r'\b\w+ly\b'
common_non_adverbs = {'only', 'early', 'daily', 'family', 'likely', 'apply', 'reply', 'supply', 'July', 'holy'}
matches = re.findall(adverb_pattern, text, re.IGNORECASE)
return len([m for m in matches if m.lower() not in common_non_adverbs])
Step 2: AI Writing Analysis

from anthropic import Anthropic
import json
client = Anthropic()
def analyze_writing(text: str, context: str = "blog post") -> dict:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2048,
system=f"""You are an expert writing coach analyzing a {context}.
Evaluate the text and return JSON:
{{
"overall_score": 1-10,
"clarity": {{"score": 1-10, "feedback": "specific feedback", "examples": ["quote problematic sentence -> suggestion"]}},
"structure": {{"score": 1-10, "feedback": "specific feedback", "suggestions": ["reorder suggestion"]}},
"tone": {{"score": 1-10, "detected_tone": "formal/casual/etc", "consistency": "consistent/mixed", "feedback": "feedback"}},
"argument_strength": {{"score": 1-10, "feedback": "feedback", "weak_points": ["specific weak arguments"]}},
"engagement": {{"score": 1-10, "feedback": "feedback", "hooks": "assessment of opening hook"}},
"top_3_improvements": ["most impactful changes ranked by priority"],
"strongest_element": "what the writer does best"
}}
Be specific. Quote actual sentences. Suggest concrete rewrites. Be encouraging but honest.""",
messages=[{"role": "user", "content": text}]
)
result_text = response.content[0].text
if "```json" in result_text:
result_text = result_text.split("```json")[1].split("```")[0]
return json.loads(result_text.strip())
Step 3: Streamlit Interface

import streamlit as st
import plotly.graph_objects as go
st.set_page_config(page_title="AI Writing Coach", layout="wide")
st.title("AI Writing Coach")
# Context selector
context = st.selectbox(
"What are you writing?",
["Blog post", "Business email", "Academic paper",
"Marketing copy", "Technical documentation", "Personal essay"]
)
# Text input
text = st.text_area("Paste your text here:", height=400,
placeholder="Enter at least 100 words for meaningful analysis...")
if text and len(text.split()) >= 50:
col1, col2 = st.columns([1, 1])
with col1:
st.subheader("Readability Metrics")
metrics = analyze_readability(text)
# Score gauges
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=metrics["flesch_reading_ease"],
title={"text": "Readability Score"},
gauge={"axis": {"range": [0, 100]},
"bar": {"color": "darkblue"},
"steps": [
{"range": [0, 30], "color": "red"},
{"range": [30, 60], "color": "yellow"},
{"range": [60, 100], "color": "green"}
]}
))
st.plotly_chart(fig, use_container_width=True)
st.metric("Words", metrics["word_count"])
st.metric("Avg Sentence Length", f"{metrics['avg_sentence_length']:.1f} words")
st.metric("Passive Voice", metrics["passive_voice_estimate"])
with col2:
st.subheader("AI Analysis")
with st.spinner("Analyzing your writing..."):
analysis = analyze_writing(text, context.lower())
# Score cards
for dimension in ["clarity", "structure", "tone", "argument_strength", "engagement"]:
data = analysis[dimension]
score = data["score"]
color = "green" if score >= 7 else "orange" if score >= 5 else "red"
st.markdown(f"**{dimension.replace('_', ' ').title()}**: :{color}[{score}/10]")
st.caption(data["feedback"])
st.subheader("Top Improvements")
for i, improvement in enumerate(analysis["top_3_improvements"], 1):
st.markdown(f"{i}. {improvement}")
st.success(f"Strongest element: {analysis['strongest_element']}")
Step 4: Section-by-Section Rewriting

Add a feature that lets users select weak sections and get AI-generated rewrites:
def rewrite_section(original: str, feedback: str, context: str) -> str:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=f"Rewrite this {context} section based on the feedback. Maintain the author's voice while improving clarity and impact.",
messages=[{"role": "user", "content": f"Original:\n{original}\n\nFeedback:\n{feedback}\n\nProvide the rewritten version:"}]
)
return response.content[0].text
Step 5: Writing Style Profiles

Create style profiles for different writing contexts:
- Blog: Casual, engaging, scannable. Target Flesch score 60-80.
- Business Email: Clear, direct, actionable. Target Flesch score 50-70.
- Academic: Precise, evidence-based, formal. Target Flesch score 30-50.
- Marketing: Persuasive, emotional, benefit-focused. Target Flesch score 60-80.
- Technical Docs: Clear, structured, example-rich. Target Flesch score 40-60.
Each profile adjusts the AI’s evaluation criteria and feedback style.
Step 6: Progress Tracking

Track improvement over time by storing analysis results and showing trend charts. Writers can see their clarity, structure, and engagement scores improve across drafts.
Step 7: Export and Integration

Add export options:
- Download analysis report as PDF
- Copy improved text to clipboard
- Generate a “writing checklist” based on the analysis
- Export readability metrics as JSON for integration with content management systems
The Bottom Line
A writing coach that gives specific, contextual feedback is fundamentally different from a grammar checker. It improves the quality of thinking, not just the mechanics of writing. And unlike a human editor who charges $50-100/hour, an AI writing coach is available 24/7 for pennies per analysis.
Build time: 3-4 hours. Cost: $5-15/month for typical individual use. Impact: dramatically better writing across your team, with measurable improvement in engagement metrics for published content.
Sources
> Want more like this?
Get the best AI insights delivered weekly.
> Related Articles
AI Agent Approval Workflows: Put Humans at the Right Control Points
Human approval can make an agent safer—or merely slower. Design checkpoints around irreversible actions, changing risk, and evidence people can actually review.
LLM Trace Redaction in Production: Debug Without Logging Private Data
LLM traces are debugging gold and privacy dynamite. Capture structure, decisions, and timing while removing secrets and personal data before storage.
Secret Management for AI Agents: Stop Leaking Credentials Into Prompts
An agent needs tools, not a backpack full of API keys. Keep secrets outside model context, issue short-lived capability tokens, and audit every use.
Tags
> Stay in the loop
Weekly AI tools & insights.