Systems Library / Operations & Admin / How to Create Automated Status Update Systems
Operations & Admin process workflow

How to Create Automated Status Update Systems

Generate and distribute project status updates automatically.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Writing status updates takes time that could go toward the actual work. I built an automate status update reporting system that pulls data from project management tools, generates a formatted update, and distributes it to stakeholders. The report writes itself from real data.

No more Monday morning "what is the status?" emails.

What You Need Before Starting

Step 1: Pull Project Data from Your PM Tool

import requests

def fetch_project_data(project_key, api_token, base_url):
    headers = {"Authorization": f"Bearer {api_token}"}

    tasks = requests.get(
        f"{base_url}/tasks?project={project_key}&modified_since=7d",
        headers=headers
    ).json()

    completed = [t for t in tasks if t["status"] == "complete"]
    in_progress = [t for t in tasks if t["status"] == "in_progress"]
    blocked = [t for t in tasks if t["status"] == "blocked"]

    return {
        "completed": completed,
        "in_progress": in_progress,
        "blocked": blocked,
        "total_tasks": len(tasks)
    }

Step 2: Generate the Status Narrative

import anthropic
import json

client = anthropic.Anthropic()

def generate_status_update(project_name, data):
    prompt = f"""Write a brief project status update for stakeholders.

Project: {project_name}
Completed this week: {len(data['completed'])} tasks
{json.dumps([t['title'] for t in data['completed'][:10]], indent=2)}

In Progress: {len(data['in_progress'])} tasks
{json.dumps([t['title'] for t in data['in_progress'][:10]], indent=2)}

Blocked: {len(data['blocked'])} tasks
{json.dumps([{'title': t['title'], 'reason': t.get('block_reason', 'unspecified')} for t in data['blocked']], indent=2)}

Write 3-4 short paragraphs: what got done, what is happening now, what is at risk.
Be specific. Use task names. No corporate fluff."""

    message = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}]
    )
    return message.content[0].text

Step 3: Format the Report

from datetime import datetime

def format_status_report(project_name, narrative, data):
    report = f"# {project_name} - Weekly Status\n"
    report += f"*{datetime.now().strftime('%B %d, %Y')}*\n\n"

    report += f"## Summary\n\n{narrative}\n\n"

    report += f"## Metrics\n\n"
    report += f"| Metric | Count |\n|---|---|\n"
    report += f"| Completed this week | {len(data['completed'])} |\n"
    report += f"| In Progress | {len(data['in_progress'])} |\n"
    report += f"| Blocked | {len(data['blocked'])} |\n\n"

    if data["blocked"]:
        report += "## Blockers Requiring Attention\n\n"
        for task in data["blocked"]:
            report += f"- **{task['title']}**: {task.get('block_reason', 'No reason specified')}\n"

    return report

Step 4: Distribute to Stakeholders

import requests as req

def post_to_slack(report, channel, slack_token):
    req.post(
        "https://slack.com/api/chat.postMessage",
        headers={"Authorization": f"Bearer {slack_token}"},
        json={"channel": channel, "text": report}
    )

def send_email_report(report, recipients, subject):
    import smtplib
    from email.mime.text import MIMEText

    msg = MIMEText(report)
    msg["Subject"] = subject
    msg["To"] = ", ".join(recipients)

    with smtplib.SMTP("smtp.gmail.com", 587) as server:
        server.starttls()
        server.login("[email protected]", "app-password")
        server.send_message(msg)

Step 5: Schedule Weekly Reports

def run_weekly_status(projects_config):
    for project in projects_config:
        data = fetch_project_data(project["key"], project["api_token"], project["base_url"])
        narrative = generate_status_update(project["name"], data)
        report = format_status_report(project["name"], narrative, data)

        for channel in project.get("slack_channels", []):
            post_to_slack(report, channel, project["slack_token"])

        if project.get("email_recipients"):
            send_email_report(report, project["email_recipients"],
                            f"{project['name']} Weekly Status - {datetime.now().strftime('%B %d')}")

# Schedule: Monday 9am
# 0 9 * * 1 python3 /path/to/status_update.py

What to Build Next

Add trend tracking that compares this week to last week. Show velocity changes, blocker patterns, and completion rate trends. A single status update is informative. A trend over time tells you if the project is accelerating or stalling.

Related Reading

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

Related Systems