Third-Party SDK Integrations
Relevant source files
The following files were used as context for generating this wiki page:
Third-party SDK integrations represent critical boundaries between internal project logic and external services such as Anthropic, Google, Stripe, and Meta. These integrations are characterized by two primary interfaces: outgoing requests (internal code to SDK) and incoming data (SDK/API to internal code). Proper management of these boundaries is essential to prevent system crashes during startup, avoid unhandled exceptions, and ensure data integrity when dealing with external payloads.
Effective integration requires defensive programming at both boundaries, including robust exception hierarchy handling, input validation using type guards, and careful management of "lazy" objects that may defer network requests and hide authentication failures.
Sources: BY-STACK/external-sdk.md:12-21, MIGRATION-NOTES.md:118-129
SDK Boundary Architecture
The integration architecture treats every external SDK as a two-way boundary. The internal system must protect itself from external failures while ensuring that data passed to external services is correctly formatted.
Data Flow and Boundary Protection
The following diagram illustrates the protective layers required at the SDK boundary:
The diagram shows the sequence of a request and the necessity of validation and error handling at the junction between the SDK and internal logic.
Sources: BY-STACK/external-sdk.md:14-21, bugbot-rules/sdk-lazy-object-not-validated.md:1-12
Error Handling and Exception Completeness
A common failure pattern in SDK integrations is catching too narrow a base class in try/except blocks. Subclasses of an SDK's APIError (such as NotFound or Auth) may bypass generic retry logic if the exception hierarchy is not handled from most specific to most general.
Exception Hierarchy Strategy
- Catch Base Classes: Always catch the documented base exception of the SDK (e.g.,
anthropic.APIError,stripe.error.StripeError). - Order Blocks: Arrange
exceptblocks with subclasses appearing before superclasses. - Handle Async Cancellations: In Python 3.8+,
asyncio.CancelledErrorinherits fromBaseException, notException. Checkingisinstance(r, Exception)inasyncio.gatherresults will miss cancellation states.
Sources: BY-STACK/external-sdk.md:27-44, RECURRING-PATTERNS.md:124-140, claude-md-snippets/external-sdk.md:1-2
Lazy Object Validation
Some SDKs, notably PyGithub, return "lazy" objects that do not trigger network requests upon instantiation. Methods like get_user() may return a proxy object; the actual API call (and potential authentication failure) only occurs when an attribute is accessed.
Comparison of PyGithub Lazy vs. Non-Lazy Calls
| Method Call | Network Request Sent at Init | Risk Level |
|---|---|---|
get_user() | No | HIGH (Lazy) |
get_user(lazy=False) | Yes | LOW (Validated) |
get_user("username") | Yes | LOW (Validated) |
get_user(lazy=True) | No | HIGH (Lazy) |
Sources: bugbot-rules/sdk-lazy-object-not-validated.md:33-42, BY-STACK/external-sdk.md:145-155
Validation Sequence for Lazy Objects
To ensure authentication is valid, a request must be forced immediately after client initialization.
External Input Validation
Data returning from an SDK or AI output (JSON) must be treated as untrusted. The project enforces isinstance guards before performing operations like .get(), .append(), or .strip().
Validation Rules
- Type Guards: Verify
dict,list, orstrbefore usage. - Numeric Safety: Use
isfinite()and range checks for external numbers. - JSON from Prose: When extracting JSON from AI responses, avoid greedy regex like
\{.*\}which breaks on prose. Usejson.JSONDecoder().raw_decode()starting from the first{. - Idempotent Enums: For Pydantic models receiving external data, use
str | Nonewith validation instead of strictStrEnumto prevent losing entire payloads due to a single unknown enum value.
Sources: BY-STACK/external-sdk.md:105-125, claude-md-snippets/external-sdk.md:4-6, RECURRING-PATTERNS.md:162-171
Startup and Configuration
SDK initialization during application startup (e.g., setting VAPID keys for push notifications or initializing Stripe/OAuth clients) must be wrapped in try/except blocks. Invalid environment variables or malformed keys should disable the specific feature rather than causing the entire server boot to fail.
Safe Initialization Pattern
def init_sdk():
try:
# Validate format (e.g., mailto: prefix for VAPID)
# Initialize client
return True
except Exception:
logger.exception("Feature disabled - SDK init failed")
return False
Sources: BY-STACK/external-sdk.md:73-95, claude-md-snippets/external-sdk.md:3
Summary of Integration Patterns
| Pattern | Description | Recommendation |
|---|---|---|
| Base Class Catch | Catching SDK base exceptions. | Catch APIError before generic Exception. |
| Async Gather | Checking results of concurrent tasks. | Use isinstance(r, BaseException). |
| JSON Extraction | Parsing JSON from AI/SDK strings. | Use raw_decode over regex. |
| Truthy Env Vars | Handling environment variable overrides. | Use is not None to allow empty strings. |
| Result Boolean | Checking SDK success objects. | Implement __bool__ or check result.ok. |
Sources: BY-STACK/external-sdk.md:47-130, claude-md-snippets/external-sdk.md:7-9
Third-party SDK integrations are a primary source of asynchronous race conditions and unexpected crashes. By enforcing strict validation at the boundaries—specifically during initialization, exception handling, and data parsing—the system maintains stability even when external services return malformed data or experience downtime.