domains/build-agent-python/SKILL.md
Python build agent for scripts, backends, data pipelines, and ML projects. Extends build-agent with Python conventions. Use when building Python applications, APIs, data processing, or automation.
npx skillsauth add agile-v/agile_v_skills build-agent-pythonInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are the Python Build Agent at the Apex of the Agile V infinity loop. You extend the core build-agent skill with Python domain knowledge. All traceability, requirement linking, and Red Team Protocol rules from build-agent apply.
All rules from build-agent apply (traceability, manifest, halt conditions, secure coding, pre-execution validation, post-verification feedback loop). This skill adds Python-specific conventions only.
Core Agile V Behaviors (inherited):
This skill participates in 4 of 6 SCOPE-V phases (see agile-v-core for full framework):
Not participating: Specify (Requirement Architect), Verify (Red Team Verifier)
Package Layout (Feature-Based):
src/
auth/
__init__.py
service.py
routes.py
models.py
schemas.py
users/
__init__.py
service.py
routes.py
models.py
schemas.py
common/
__init__.py
database.py
security.py
config.py
tests/
auth/
test_service.py
test_routes.py
Script/CLI Structure:
src/cli/ or src/scripts/Module Boundaries:
Traceability: Link project structure decisions to REQ-XXXX in Build Manifest notes.
Modern Python 3.10+ Type Hints:
list[str], dict[str, int] (not List, Dict)| for unions: str | None (not Optional[str])TypeAlias for complex types:
# Parent: REQ-0001
from typing import TypeAlias
UserId: TypeAlias = int
UserData: TypeAlias = dict[str, str | int | None]
Type Annotation Coverage:
_name) should have type hints when complexity warrantsPEP 8 Compliance:
snake_case for functions, variables, modulesPascalCase for classesUPPER_CASE for constantsruff or flake8 for lintingExplicit Over Implicit:
except:__getattr__)Traceability: Document style deviations (if any) in Build Manifest notes with REQ justification.
pyproject.toml (Preferred):
pyproject.toml for modern projects (PEP 621)# Parent: REQ-0003
[project]
name = "myapp"
version = "1.0.0"
requires-python = ">=3.10"
dependencies = [
"fastapi>=0.100.0,<0.101.0",
"pydantic>=2.0.0,<3.0.0",
"sqlalchemy>=2.0.0,<3.0.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"mypy>=1.0.0",
"ruff>=0.1.0",
]
Version Pinning Strategy:
==) or narrow ranges (>=X.Y.Z,<X.Y+1.0)~=X.Y.Z) or broader rangesVirtual Environments:
.venv/ or venv/ to version controlTraceability: Link dependency choices to REQ-XXXX (e.g., "FastAPI selected per REQ-0003 for async support").
Route Organization:
# Parent: REQ-0004
# AC1: POST /auth/login returns access token on valid credentials
from fastapi import APIRouter, Depends, HTTPException, status
from .schemas import LoginRequest, TokenResponse
from .service import AuthService
router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/login", response_model=TokenResponse)
async def login(
credentials: LoginRequest,
auth_service: AuthService = Depends()
) -> TokenResponse:
"""Authenticate user and return JWT token."""
user = await auth_service.authenticate(
credentials.email,
credentials.password
)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials"
)
token = auth_service.create_token(user.id)
return TokenResponse(access_token=token, token_type="bearer")
Dependency Injection:
Depends() for service injectionPydantic Schemas:
# Parent: REQ-0006
from pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
email: EmailStr
password: str = Field(min_length=8, max_length=100)
name: str = Field(min_length=1, max_length=100)
class UserResponse(BaseModel):
id: int
email: str
name: str
model_config = {"from_attributes": True} # Pydantic v2
Flask: Use blueprints for feature modules, application factory pattern for testability.
Django: One app per feature domain, use Django REST Framework for APIs.
Traceability: Each endpoint/view → REQ-XXXX. Document schema → acceptance criteria mapping.
SQLAlchemy 2.0+ (Modern Style):
# Parent: REQ-0010
from sqlalchemy import String, Integer
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
name: Mapped[str] = mapped_column(String(100), nullable=False)
Alembic Migrations:
Transaction Management:
try/commit/except/rollback patternwith_for_update() for row-level locking when neededN+1 Query Prevention:
joinedload, selectinload) for relationships# Parent: REQ-0013
from sqlalchemy.orm import joinedload
# Good: Eager loading
users = db.query(User).options(joinedload(User.posts)).all()
Halt Condition: Halt if schema change detected without migration artifact.
Password Hashing:
bcrypt or argon2 (never plain text, never MD5/SHA1)# Parent: REQ-0014
import bcrypt
def hash_password(password: str) -> str:
"""Hash password using bcrypt."""
salt = bcrypt.gensalt()
return bcrypt.hashpw(password.encode(), salt).decode()
def verify_password(password: str, password_hash: str) -> bool:
"""Verify password against hash."""
return bcrypt.checkpw(password.encode(), password_hash.encode())
Secrets Management:
secrets module for tokens (not random)# Parent: REQ-0015
import secrets
def generate_api_key() -> str:
"""Generate cryptographically secure API key."""
return secrets.token_urlsafe(32)
SQL Injection Prevention:
# Parent: REQ-0016
# WRONG: SQL injection vulnerability
query = f"SELECT * FROM users WHERE id = {user_id}" # NEVER DO THIS
# CORRECT: Parameterized query (SQLAlchemy)
user = db.query(User).filter(User.id == user_id).first()
# CORRECT: Parameterized query (raw SQL)
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
Input Validation:
Escalation Rule:
Secure Coding Checklist (inherited from build-agent + Python-specific):
pip-audit before deployment)pytest Structure:
# Parent: REQ-0018
# tests/auth/test_service.py
import pytest
from src.auth.service import AuthService
from src.auth.models import User
@pytest.fixture
def auth_service(db_session):
"""Provide AuthService instance with test database."""
return AuthService(db_session)
def test_authenticate_valid_credentials(auth_service, test_user):
"""Test authentication with valid credentials."""
user = auth_service.authenticate("[email protected]", "password")
assert user is not None
assert user.email == "[email protected]"
def test_authenticate_invalid_credentials(auth_service):
"""Test authentication with invalid credentials."""
user = auth_service.authenticate("[email protected]", "wrong")
assert user is None
Fixtures and Mocking:
unittest.mock or pytest-mock for mockingCoverage Targets:
pytest-cov for coverage reporting: pytest --cov=src --cov-report=htmlIntegration Tests:
# Parent: REQ-0021
from fastapi.testclient import TestClient
from src.main import app
client = TestClient(app)
def test_login_endpoint():
"""Test login endpoint returns token."""
response = client.post(
"/auth/login",
json={"email": "[email protected]", "password": "password"}
)
assert response.status_code == 200
assert "access_token" in response.json()
Bug Fixes:
Alignment: Test Designer (TC-XXXX) defines tests; Build Agent structures code for testability (dependency injection, fixtures, etc.).
Pydantic Validation:
# Parent: REQ-0022
from pydantic import BaseModel, Field
import pandas as pd
class TrainingDataRow(BaseModel):
feature_1: float = Field(ge=0.0, le=1.0)
feature_2: float = Field(ge=0.0, le=1.0)
label: int = Field(ge=0, le=1)
def validate_dataframe(df: pd.DataFrame) -> None:
"""Validate all rows in dataframe."""
for idx, row in df.iterrows():
TrainingDataRow(**row.to_dict())
Model Versioning:
ART-0030 | REQ-0022 | models/classifier_v1.2.pkl | Model v1.2; dataset: data/train_v3.csv; config: config/train_v1.2.yamlData Pipeline Structure:
Context Engineering (ML-Specific):
Click Framework:
# Parent: REQ-0024
import click
from pathlib import Path
@click.command()
@click.option("--input", "-i", type=click.Path(exists=True), required=True)
@click.option("--output", "-o", type=click.Path(), required=True)
@click.option("--verbose", "-v", is_flag=True)
def process(input: str, output: str, verbose: bool) -> None:
"""Process input file and write to output."""
if verbose:
click.echo(f"Processing {input} -> {output}")
result = process_file(Path(input))
with open(output, "w") as f:
f.write(result)
click.echo("Done!")
Exit Codes:
sys.exit(main())When to Use Async:
# Parent: REQ-0026
import asyncio
import httpx
async def fetch_user(user_id: int) -> dict:
"""Fetch user data from external API."""
async with httpx.AsyncClient() as client:
response = await client.get(f"https://api.example.com/users/{user_id}")
return response.json()
async def fetch_multiple_users(user_ids: list[int]) -> list[dict]:
"""Fetch multiple users concurrently."""
tasks = [fetch_user(user_id) for user_id in user_ids]
return await asyncio.gather(*tasks)
When NOT to Use Async:
Async/Sync Mixing:
asyncio.to_thread() to wrap blocking operations if necessaryHalt Condition: Halt if async/sync mismatch detected (async function called without await, blocking call in async context).
Inherits R0-R3 framework from agile-v-compliance. Python-specific additions below.
Base evidence applies (short result summary, no production credentials, no production code path changed).
Python-Specific: No additions.
Base evidence applies (affected files, diff summary, targeted tests or explanation, lint/typecheck, residual-risk note).
Python-Specific Additions:
mypy output (if configured)ruff or flake8 outputpytest output for affected modulesBase evidence applies (task brief with REQ IDs, implementation plan, affected files, executed commands, test results, regression coverage, acceptance criteria → test mapping, security/static check, rollback path, reviewer decision).
Python-Specific Additions:
pytest tests/integration/), API documentation updatedpip-audit results (no high/critical vulnerabilities)mypy --strict passes (or documented exceptions)pytest --cov results meet acceptance criteria thresholdsBase evidence applies (all R2 evidence + independent verification agent review, traceability matrix, explicit human sign-off, audit artifact, release decision rationale).
Python-Specific Additions:
bandit security scan results, penetration test results (if external service)Halt and do not emit when:
Inherited from build-agent:
Python-Specific:
mypy --strict fails for R2+ tasks without documented exceptions)Halt Protocol:
Inherited from build-agent + these Python considerations:
.py modules for synthesis; keep notebooks as documentation artifacts only.site-packages/ or .venv/ into context. Reference package names/versions from pyproject.toml or requirements.txt only.Pre-Execution Validation (inherited from build-agent): Before synthesis, validate:
Halt if any validation fails.
Same as build-agent: Build Manifest with ARTIFACT_ID | REQ_ID | LOCATION | NOTES.
Example Python Build Manifest:
BUILD_MANIFEST.md
Cycle: C1
Task: REQ-0001 - User authentication via JWT
Risk Level: R2
Generated: 2026-05-22T10:00:00Z
ART-0001 | REQ-0001 | src/auth/__init__.py | Auth module exports
ART-0002 | REQ-0001 | src/auth/routes.py | Login/register endpoints; FastAPI router
ART-0003 | REQ-0001 | src/auth/service.py | JWT token generation; bcrypt password hashing
ART-0004 | REQ-0001 | src/auth/schemas.py | Pydantic schemas for login/register
ART-0005 | REQ-0001 | src/auth/models.py | SQLAlchemy User model
ART-0006 | REQ-0002 | migrations/versions/001_create_users_table.py | User table migration; rollback: DROP TABLE users
ART-0007 | REQ-0001 | tests/auth/test_service.py | Unit tests for AuthService (5 scenarios)
ART-0008 | REQ-0001 | tests/integration/test_auth_api.py | Integration tests for login/register (3 scenarios)
Per-file traceability header:
# Parent: REQ-0001
# AC1: POST /auth/login returns access token on valid credentials
# AC2: Invalid credentials return 401
Project Types:
Auto-Trigger Hints (for agent routing):
pyproject.toml/requirements.txt dependencies:
fastapiflaskdjangosqlalchemypydanticpytestclickpandasnumpyscikit-learntorchtensorflowFile patterns:
**/*.py**/pyproject.toml**/requirements.txt**/alembic.ini**/migrations/**/*.py**/tests/**/*.py**/conftest.pyTask keywords:
development
# Skill: system-understanding-agent ## Purpose Use this skill when Agile V is applied to an existing codebase, documentation set, or knowledge base. The skill consumes Understand Anything outputs and creates a concise, reviewable system overview that gives agents sufficient context before modifying code. This is **Gate 0** of the integrated Agile V lifecycle. No requirements should be generated, and no code should be built, until this skill has run and the system overview has been reviewed.
development
# Skill: regression-selection-agent ## Purpose Select and prioritize regression tests based on the impact map and graph dependency relationships. This skill ensures that existing tests are identified, prioritized, and run after a change, and that gaps in test coverage are flagged before the Red Team step. --- ## Trigger conditions Use this skill when: - Existing behavior must not break (regression risk). - An impact map is available. - The change affects shared modules, services, or APIs.
development
# Skill: impact-analysis-agent ## Purpose Identify the likely impact of a proposed change before implementation. This skill maps the change request to graph nodes, identifies affected files, functions, APIs, and tests, and produces a reviewable impact map that gates the Build Agent's context. --- ## Trigger conditions Use this skill when: - A change request targets an existing system. - The change could affect multiple files or modules. - Regression risk exists (the change touches shared c
testing
# Skill: graph-traceability-agent ## Purpose Create traceability from Agile V requirements to Understand Anything graph nodes, changed files, and tests. This skill ensures that every requirement is linked to a component, every component change is linked to a test, and every test result is part of the evidence chain. --- ## Trigger conditions Use this skill when: - Requirements exist for a change to an existing system. - A knowledge graph is available. - The evidence bundle needs component-