home / skills / wdm0006 / python-skills / api-design
This skill helps design Python library APIs with simplicity, consistency, and discoverability, guiding deprecation, error handling, and versioning.
npx playbooks add skill wdm0006/python-skills --skill api-designReview the files below or copy the command above to add this skill to your agents.
---
name: designing-python-apis
description: Designs intuitive Python library APIs following principles of simplicity, consistency, and discoverability. Handles API evolution, deprecation, breaking changes, and error handling. Use when designing new library APIs, reviewing existing APIs for improvements, or managing API versioning and deprecations.
---
# Python API Design
## Core Principles
1. **Simplicity**: Simple things simple, complex things possible
2. **Consistency**: Similar operations work similarly
3. **Least Surprise**: Behave as users expect
4. **Discoverability**: Find via autocomplete and help
## Progressive Disclosure Pattern
```python
# Level 1: Simple functions
from mylib import encode, decode
result = encode(37.7749, -122.4194)
# Level 2: Configurable classes
from mylib import Encoder
encoder = Encoder(precision=15)
# Level 3: Low-level access
from mylib.internals import BitEncoder
```
## Naming Conventions
```python
# Actions: verbs
encode(), decode(), validate()
# Retrieval: get_*
get_user(), get_config()
# Boolean: is_*, has_*, can_*
is_valid(), has_permission()
# Conversion: to_*, from_*
to_dict(), from_json()
```
## Error Handling
```python
class MyLibError(Exception):
"""Base exception with helpful messages."""
def __init__(self, message: str, *, hint: str = None):
super().__init__(message)
self.hint = hint
# Usage
raise ValidationError(
f"Latitude must be -90 to 90, got {lat}",
hint="Did you swap latitude and longitude?"
)
```
## Deprecation
```python
import warnings
def old_function():
warnings.warn(
"old_function() deprecated, use new_function()",
DeprecationWarning,
stacklevel=2,
)
return new_function()
```
## Anti-Patterns
```python
# Bad: Boolean trap
process(data, True, False, True)
# Good: Keyword arguments
process(data, validate=True, cache=False)
# Bad: Mutable default
def process(items: list = []):
# Good: None default
def process(items: list | None = None):
```
For detailed patterns, see:
- **[PATTERNS.md](PATTERNS.md)** - Builder, factory, and advanced patterns
- **[EVOLUTION.md](EVOLUTION.md)** - API versioning and migration guides
## Review Checklist
```
Naming:
- [ ] Clear, self-documenting names
- [ ] Consistent patterns throughout
- [ ] Boolean params read naturally
Parameters:
- [ ] Minimal required parameters
- [ ] Sensible defaults
- [ ] Keyword-only after positional clarity
Errors:
- [ ] Custom exceptions with context
- [ ] Helpful error messages
- [ ] Documented in docstrings
```
## Learn More
This skill is based on the [Ergonomics](https://mcginniscommawill.com/guides/python-library-development/#ergonomics-the-joy-of-good-design) section of the [Guide to Developing High-Quality Python Libraries](https://mcginniscommawill.com/guides/python-library-development/) by [Will McGinnis](https://mcginniscommawill.com/).
This skill designs intuitive Python library APIs focused on simplicity, consistency, and discoverability. It helps create progressive interfaces that expose simple defaults, configurable classes, and low-level primitives as needed. Use it to shape naming, error handling, deprecation, and API evolution so your library feels natural to use and easy to maintain.
The skill inspects API shapes and recommends patterns: top-level convenience functions for common cases, configurable objects for advanced use, and clear low-level modules for power users. It applies naming conventions (verbs for actions, get_ for retrieval, is_/has_ for booleans, to_/from_ for conversions), checks for anti-patterns, and generates deprecation and error-handling templates. It also produces a review checklist and migration guidance for breaking changes and versioning.
How should I decide what belongs at the top-level API vs internals?
Expose the most common, simplest operations at top level. Progress to configurable classes for advanced customization and keep low-level primitives in clearly-named internal modules for expert use.
What’s the best way to signal breaking changes?
Document the change, provide a migration guide, emit deprecation warnings on the old API with replacement examples, and schedule removals across major releases to give users time to migrate.