providers/. They keep secrets,
client construction, and resource cleanup separate from sensor logic, while preserving ordinary
Python types at the call site.
Define a provider
Create aProvider subclass in providers/:
pydantic-settings. In this example, set
QUALITY_SLACK_WEBHOOK_URL in the server environment rather than storing the webhook in
streambuild_project.toml.
The class name determines the provider name: QualitySlack becomes quality_slack. Set
provider_name explicitly when a different lower-snake-case name is clearer.
Inject a provider
Add a typed parameter with the provider’s resolved name to a sensor:quality_slack to the discovered provider and validates the annotation. A
missing provider or incompatible annotation fails loudly instead of passing an untyped object into
the handler.
Manage client lifecycle
Providers are instantiated for a sensor tick but initialized only when requested. Overridesetup(ctx) for connections or clients and teardown() for cleanup:
Choose the boundary
Use a provider for dependencies that need configuration or lifecycle management, such as API clients, notification services, and credentials. Keep event filtering, cursor decisions, retryable steps, and idempotency in the sensor itself.
This split lets multiple sensors share one dependency definition without sharing mutable state
between ticks.

