The AI ​​wrote the Python code, but it’s still your job to maintain it

by SkillAiNest

The AI ​​wrote the Python code, but it’s still your job to maintain itThe AI ​​wrote the Python code, but it’s still your job to maintain it
Photo by author

# Introduction

AI coding tools are getting impressively good at writing Python code that works. They can develop entire applications and implement complex algorithms in minutes. However, AI generated code is often a pain to maintain.

If you are using tools like Claude Codefor , for , for , . GitHub Coplotor Cursor Agent Mode, you’ve probably experienced it. AI helps you ship working code faster, but the cost shows up later. You’ve probably refactored a bloated function to understand how it works weeks after it was developed.

The problem isn’t that AI writes bad code – although it sometimes does – it’s that AI optimizes to “work now” and fulfill the requirements in your prompt, whereas you need code that’s readable and maintainable in the long term. This article shows you how to address this gap with Python-specific strategies.

# Avoiding the blank canvas trap

The biggest mistake developers make is asking the AI ​​to start from scratch. AI agents work best with constraints and guidelines.

Before you write your first clue, Set up the basics of the project yourself. This means that you choose the structure of your project – installing your core libraries and implementing some working examples – to set the tone. It may seem counterintuitive, but it helps the AI ​​write code that best suits what you need in your application.

Start by building a couple of features manually. If you’re building an API, implement yourself a complete endpoint with all the patterns you want: dependency injection, proper error handling, database access, and validation. This becomes the reference implementation.

Say you write this first endpoint manually:

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session

router = APIRouter()

# Assume get_db and User model are defined elsewhere
async def get_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

When AI sees this pattern, it understands how we handle dependencies, how we query the database, and how we handle missing records.

The same applies to your project structure. Create your directories, set your imports, and configure your testing framework. AI should not make these architectural decisions.

# Building a python type system does the heavy lifting

Python’s dynamic typing is flexible, but flexibility becomes a liability when AI is writing your code. Make type pointers necessary guards instead of good to good in your application code.

AI errors occur before hard typing reaches output. When you need a type indicator on each function signature and run mypy In hard mode, the AI ​​cannot take shortcuts. It cannot return ambiguous types, nor can it accept parameters that can be strings or lists.

More importantly, strict types force better design. For example, trying to write a function that accepts an AI agent data: dict Many assumptions can be made about what is in this dictionary. However, an AI agent writes a function that accepts data: UserCreateRequest where UserCreateRequest a pydantic The model has exactly one interpretation.

# This constrains AI to write correct code
from pydantic import BaseModel, EmailStr

class UserCreateRequest(BaseModel):
    name: str
    email: EmailStr
    age: int

class UserResponse(BaseModel):
    id: int
    name: str
    email: EmailStr

def process_user(data: UserCreateRequest) -> UserResponse:
    pass

# Rather than this
def process_user(data: dict) -> dict:
    pass

Use libraries that implement contracts: sqlalchemy 2.0 with type-checked models and Fastpy The best choices are with responsive models. These are not just good practices. They are the obstacles that keep the AI ​​on track.

Set MYPY to strict mode and non-negotiate passing type checks. When the AI ​​produces code that fails type checking, it will iterate until it passes. This automatic feedback loop produces better code than any amount of quick engineering.

# Creating documentation to guide AI

Most projects have documentation that developers ignore. For AI agents, you need documentation that they actually use. Readme.md file with instructions. This means a single file with clear, specific rules.

a Claude.Mid or Agents. M.D File at the root of your project. Don’t make it too long. Focus on what’s unique about your project rather than common Python best practices.

Your AI guidelines should specify:

  • Project structure and where different types of code belong
  • What libraries to use for common tasks
  • Specific patterns to follow (e.g. point to files)
  • Obvious haram patterns
  • Testing requirements

Here is an example Agents. M.D file:

# Project Guidelines

## Structure
/src/api - FastAPI routers
/src/services - business logic
/src/models - SQLAlchemy models
/src/schemas - Pydantic models

## Patterns
- All services inherit from BaseService (see src/services/base.py)
- All database access goes through repository pattern (see src/repositories/)
- Use dependency injection for all external dependencies

## Standards
- Type hints on all functions
- Docstrings using Google style
- Functions under 50 lines
- Run `mypy --strict` and `ruff check` before committing

## Never
- No bare except clauses
- No type: ignore comments
- No mutable default arguments
- No global state

The key is unique. Don’t just say “follow best practices”. Point to the exact file that represents the pattern. Not just “handle errors properly.” Show sample error handling if you want.

# Writing points to examples

Common notations generate common code. Specific pointers that refer to your existing code base produce more maintainable code.

Instead of asking the AI ​​to “add validation”, walk through the implementation with reference to your samples. Here is an example of such pointers that point to examples:

Implement JWT authentication in src/services/auth_service.py Follow the same structure as the user service in src/services/user_service.py. Use Bcrypt for password hashing (already in requirements.txt).
Add a validation dependency to src/api/dependencies following the get_db pattern.
Create pydantic schemes in src/schemes/auth.py as user
Add a pytest test to test/test_out_service.py using fixtures from conftest.py.

Notice how each directive points to an existing file or pattern. You’re not asking AI to build an architecture. You’re asking it to implement what you need on a new feature.

When the AI ​​generates code, evaluate it against your patterns. Does it use the same dependency injection approach? Does it follow the same error handling? Does it manage imports the same way? If not, point out the inconsistency and ask for alignment with the current model.

# Planning before execution

AI agents can move quickly, which can sometimes make them less effective if speed comes at the expense of structure. Before writing any code, use plan mode or ask for an execution plan.

A planning phase forces the AI ​​to think through dependencies and structures. This gives you the opportunity to catch architectural problems – such as circular dependencies or redundant services – before implementation.

Ask for a plan that describes:

  • Which files will be created or modified?
  • What dependencies exist between components
  • What existing patterns will be followed?
  • What tests are needed?

Review the plan as you would review a design document. Check that the AI ​​understands your project structure. Verify that it is using the correct libraries and verify that it is not repeating something that already exists.

If the plan looks good, let the AI ​​execute it. If not, fix the project before writing any code. It’s easier to fix a bad project than to fix bad code.

# Asking the AI ​​to write tests that actually test

AI is very good and fast in writing tests. However, AI is not effective at writing useful tests unless you are specific about what “useful” means.

The default AI test behavior is to check the happy path and nothing else. You get tests that verify the code works when everything goes well, which is exactly when you don’t need tests.

Clearly state your testing needs. For each feature, require:

  • Pleasant way test
  • Validation error tests to check what happens with incorrect input
  • Edge case tests for null values, none, boundary conditions, and more
  • Error handling tests for database failures, external service failures, and the like

For example point AI to your existing test files. If you already have good test patterns, the AI ​​will write useful tests too. If you don’t have good tests yet, write some yourself first.

# Systematically validating the output

After generating the AI ​​code, don’t just check if it runs. Run it through the checklist.

Your checklist should include questions such as the following:

  • Does it pass Mypy hard mode?
  • Does it follow existing code patterns?
  • All the functions are under 50 lines
  • Tests cover edge cases and errors
  • Do all functions have type pointers?
  • Does it use specific libraries correctly?

Automate what you can. Setup Pre-commit Hooks that run mypi, Roughand pietists. If AI-infiltrated code fails these checks, it is not committed.

For what you can’t automate, you’ll see common antipatterns after reviewing enough AI code.

# Implementing a practical workflow

Let us now summarize everything we have discussed so far.

You start a new project. You spend time setting up the framework, choosing and installing libraries, and writing a couple of example features. You create Claude.Mid Write specific pedantic models with your guidelines.

Now you ask the AI ​​to implement a new feature. You write a detailed allusion, citing your examples. AI creates a plan. You review it and approve it. AI writes code. You run type checking and tests. Everything passes. You review the code against your samples. It is similar. You commit.

The total time for a prompt can be as little as 15 minutes for a feature that would take you an hour to write manually. But more importantly, the code you get is easy to maintain – it follows the patterns you’ve established.

The next feature runs faster because the AI ​​has more examples to learn from. Code becomes more consistent over time as each new feature reinforces existing patterns.

# wrap up

With AI coding tools proving extremely useful, your job as a developer or data professional is changing. Now you spend less time writing code and more time:

  • Designing the system and choosing the architecture
  • Implementation reference samples
  • Writing constraints and guidelines
  • Reviewing AI output and maintaining the quality bar

The skill that matters most is not writing code fast. Rather, it’s designing systems that force AI to write the code that sustains it. It knows which methods scale and which create technical debt. I hope you find this article helpful even if you don’t use Python as your programming language of choice. Let us know what else you think we can do to maintain Ai-generated Python code. What can you do? Keep searching!

Bala Priya c is a developer and technical writer from India. She loves working at the intersection of mathematics, programming, data science, and content creation. His areas of interest and expertise include devops, data science, and natural language processing. She enjoys reading, writing, coding and coffee! Currently, she is working on learning and sharing her knowledge with the developer community by authoring tutorials, how-to guides, opinion pieces and more. Bala also engages resource reviews and coding lessons.

You may also like

Leave a Comment

At Skillainest, we believe the future belongs to those who embrace AI, upgrade their skills, and stay ahead of the curve.

Get latest news

Subscribe my Newsletter for new blog posts, tips & new photos. Let's stay updated!

@2025 Skillainest.Designed and Developed by Pro