Building Valo: AWS Service Client Wrappers — From boto3 Chaos to Typed Elegance
boto3 is AWS's official Python SDK. It's comprehensive, battle-tested, and... completely untyped.
Today we wrapped four AWS services (Lambda, SQS, EventBridge, S3) with typed client classes that are testable, type-safe, and production-ready.
The Problem: boto3's Low-Level API
boto3 works great for simple scripts, but production applications need:
- Type hints (boto3 returns
Anyeverywhere) - Consistent error handling (ClientError is a catch-all)
- Testability (mocking boto3 clients requires careful setup)
- Clean APIs (boto3's parameter dictionaries are complex)
Our Solution: Typed Client Wrappers
We created four wrapper classes following a consistent pattern:
Key design decisions:
- Dependency Injection: Client parameter allows test mocking
- Automatic JSON Serialization: We handle serialization internally
- Consistent Error Handling: All boto3 errors wrapped in
AWSServiceError - Type Safety: Using
cast()ensures mypy strict mode compliance - Sensible Defaults: region, delay_seconds, etc.
Four Services, One Pattern
1. LambdaClient — Function Invocation
- Invoke MCP servers from orchestrator
- Cross-Lambda communication
- Async event processing
2. SQSClient — Message Queue Operations
- Async task processing
- Decoupling services
- Request buffering
3. EventBridgeClient — Event Publishing
- Event-driven architecture
- Service coordination
- Audit logging
4. S3Client — Object Storage
- Prediction storage
- Match data archival
- Configuration distribution
Testing: Dependency Injection Pattern
All clients support dependency injection for testing. Create a mock, inject it, test with it. Simple and effective.
Type Safety: mypy Strict Mode Compliance
All clients pass mypy strict mode. boto3 returns Any, but we use cast() to satisfy mypy.
This ensures type safety without sacrificing boto3 compatibility.
What We Learned from Sentinel
Patterns we adopted:
- Dependency Injection for Testability: Optional client parameter pattern
- Idempotent Error Handling: Ignore expired receipts (future iteration)
- Abstract Base Classes: Deferred for MVP (YAGNI), but noted for multi-cloud support
Quality Metrics
- 132 tests passing (49 new AWS client tests, 83 existing)
- 88% overall coverage
- Lambda: 85% | SQS: 80% | EventBridge: 83% | S3: 81%
- Zero mypy errors (strict mode)
- Zero ruff errors
Typed. Testable. Production-ready.