Automating Tasks with ChatGPT: A Practical Guide

# Automating Tasks with ChatGPT: A Practical Guide

ChatGPT isn’t just for chatting. If you’re a developer, it’s a programmable tool that can handle repetitive tasks—code reviews, documentation, test generation, bug triage—without the marketing fluff. This guide shows you how to actually automate these workflows using the OpenAI API, with working code you can drop into your projects today.

## Why Automate with ChatGPT?

You’ve written the same documentation three times. You’ve spent hours reviewing boilerplate code. These are tasks that require just enough cognitive effort to be annoying, but not enough to be interesting. ChatGPT can handle the heavy lifting.

The key difference between using ChatGPT in a browser and automating it is the API. With the API, you can:
– Trigger workflows automatically (CI/CD, git hooks, cron jobs)
– Process files in bulk
– Build custom pipelines for your specific needs

This isn’t about replacing developers. It’s about reclaiming time for work that actually matters.

## Setting Up the OpenAI API

Before automating anything, you need API access. Here’s the minimum setup:

“`bash
# Install the OpenAI Python library
pip install openai

# Verify it works
python -c “import openai; print(openai.__version__)”
“`

Get your API key from [platform.openai.com](https://platform.openai.com). You’ll need to add billing—there’s no free tier for API access in 2026, but the pricing is reasonable for automation. GPT-4o mini costs roughly $0.60 per million input tokens.

Store your key in your environment, never hardcoded:

“`python
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ.get(“OPENAI_API_KEY”))
“`

That’s it. You’re ready to send requests.

## Building a Simple Automation Script

Let’s start with something concrete: a script that takes a file path and generates documentation for it.

“`python
import os
import sys
from openai import OpenAI

client = OpenAI(api_key=os.environ.get(“OPENAI_API_KEY”))

def generate_doc(file_path):
with open(file_path, ‘r’) as f:
content = f.read()

response = client.chat.completions.create(
model=”gpt-4o-mini”,
messages=[
{
“role”: “system”,
“content”: “You are a code documentation generator. Generate clear, concise docstrings in the Google style.”
},
{
“role”: “user”,
“content”: f”Generate documentation for this code:\n\n{content}”
}
],
temperature=0.3
)

return response.choices[0].message.content

if __name__ == “__main__”:
file_path = sys.argv[1]
doc = generate_doc(file_path)
print(doc)
“`

Run it:

“`bash
python doc_gen.py my_module.py
“`

This works, but it’s fragile. What if the file is huge? What if the API fails? Let’s improve it.

## Handling API Limits and Errors

The API has rate limits (roughly 500 requests/minute for most accounts), and things fail. Here’s a more robust pattern:

“`python
import time
from openai import APIError, RateLimitError

def chat_with_retry(client, messages, max_retries=3):
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model=”gpt-4o-mini”,
messages=messages,
temperature=0.3
)
return response.choices[0].message.content

except RateLimitError:
wait_time = 2 ** attempt
print(f”Rate limited. Waiting {wait_time}s…”)
time.sleep(wait_time)

except APIError as e:
print(f”API error: {e}”)
if attempt == max_retries – 1:
raise

raise Exception(“Max retries exceeded”)
“`

This handles rate limits with exponential backoff—a must for any production automation.

Also note: the API has a context window limit (128K tokens for GPT-4o). If you’re processing large files, you need to chunk them:

“`python
def chunk_file(file_content, max_tokens=8000):
“””Split file into chunks that fit in the context window.”””
lines = file_content.split(‘\n’)
chunks = []
current_chunk = []
current_size = 0

for line in lines:
line_size = len(line.split())
if current_size + line_size > max_tokens:
chunks.append(‘\n’.join(current_chunk))
current_chunk = [line]
current_size = line_size
else:
current_chunk.append(line)
current_size += line_size

if current_chunk:
chunks.append(‘\n’.join(current_chunk))

return chunks
“`

## Automating Code Reviews

One of the most practical uses: automated code review on every PR. Here’s a script that runs as part of your CI pipeline:

“`python
import subprocess
import os

def get_changed_files():
“””Get list of modified Python files in this PR.”””
result = subprocess.run(
[“git”, “diff”, “–name-only”, “main…HEAD”, “–“, “*.py”],
capture_output=True,
text=True
)
return [f for f in result.stdout.strip().split(‘\n’) if f]

def review_file(file_path):
with open(file_path, ‘r’) as f:
content = f.read()

response = client.chat.completions.create(
model=”gpt-4o-mini”,
messages=[
{
“role”: “system”,
“content”: “You are a senior code reviewer. Find bugs, security issues, and code quality problems. Be concise and specific.”
},
{
“role”: “user”,
“content”: f”Review this code:\n\n{content}”
}
],
temperature=0.2
)

return response.choices[0].message.content

# CI integration
if __name__ == “__main__”:
changed_files = get_changed_files()
print(f”Reviewing {len(changed_files)} files…\n”)

for file_path in changed_files:
print(f”=== {file_path} ===”)
review = review_file(file_path)
print(review)
print()
“`

Drop this into your CI pipeline (GitHub Actions example):

“`yaml
name: Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– name: Run automated review
run: python review_pr.py
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
“`

**Limitation:** The model can miss subtle bugs or context-specific issues. Use this as a first-pass filter, not a replacement for human review.

## Generating Tests from Code

Another solid use case: generating unit tests for new code:

“`python
def generate_tests(file_path):
with open(file_path, ‘r’) as f:
content = f.read()

response = client.chat.completions.create(
model=”gpt-4o-mini”,
messages=[
{
“role”: “system”,
“content”: “Generate pytest unit tests for the given code. Include edge cases. Use fixtures where appropriate.”
},
{
“role”: “user”,
“content”: content
}
],
temperature=0.3
)

return response.choices[0].message.content
“`

The quality depends on how well-structured your code is. Well-named functions and clear interfaces produce better tests. If your code is a mess, the tests will be a mess—which is actually useful for identifying refactoring needs.

## Real-World Workflow: Bug Triage

Here’s a more complex example: automatically triaging bug reports.

“`python
def triage_bug(title, description, stack_trace=None):
prompt = f”””
Analyze this bug report and provide:
1. Severity: critical / high / medium / low
2. Likely area: frontend / backend / database / infrastructure
3. Suggested first step: what should the developer check first?
4. Priority score: 1-10

Title: {title}
Description: {description}
“””

if stack_trace:
prompt += f”\nStack trace:\n{stack_trace}”

response = client.chat.completions.create(
model=”gpt-4o-mini”,
messages=[
{“role”: “system”, “content”: “You are a bug triage expert. Be brief and actionable.”},
{“role”: “user”, “content”: prompt}
],
temperature=0.2
)

return response.choices[0].message.content
“`

Hook this into your issue tracker via webhooks, and every new bug gets an initial classification before a human looks at it.

## Cost Considerations

Let’s be real about costs. Here’s a rough breakdown for typical automation:

| Task | Input Size | Output Size | Cost (GPT-4o mini) |
|——|————|————-|——————-|
| Code review (1 file) | ~500 tokens | ~200 tokens | ~$0.0005 |
| Documentation (1 file) | ~500 tokens | ~300 tokens | ~$0.0006 |
| Bug triage | ~300 tokens | ~100 tokens | ~$0.0003 |

For a small team running 100 automated reviews per day, you’re looking at roughly $5/month. The ROI is obvious.

**Warning:** Monitor your usage. It’s easy to accidentally run up bills by processing files in loops without limits. Set up usage alerts in the OpenAI dashboard.

## Key Takeaways

– The OpenAI API enables programmatic automation—browser ChatGPT cannot
– Start with simple scripts (documentation, basic review) before complex pipelines
– Always implement retry logic with exponential backoff for production use
– Chunk large files to stay within