-
Sync + async pairing. Every public inference method ships a sync + async twin (infer/infer_async, ocr_image/ocr_image_async, clip_compare/clip_compare_async, sam2_segment_image/_async, …). The sync wrap_errors maps RetryError/HTTPError/ConnectionError; the async wrap_errors_async maps ClientResponseError/ClientConnectionError. A sync method decorated @wrap_errors_async (or vice-versa) lets un-redacted async exceptions escape (broke in #255; that PR was a one-line decorator swap on infer_async).
-
API keys never leak. Any string derived from an error, URL, or request that surfaces to the user must pass through deduct_api_key_from_string (http/utils/requests.py) — description, api_message, connection-error messages (raw api_message=error.message leaked the key in #248). Never call bare response.raise_for_status(); use api_key_safe_raise_for_status(response=...), which strips the key from response.url before raising (#212). Grep the diff for str(error), .message, response.url, and raise_for_status without the safe wrapper.
-
Client-mode gating. client_mode (HTTPClientMode.V0/V1) is auto-derived from api_url by _determine_client_mode (ALL_ROBOFLOW_API_URLS → V0 legacy hosted; else V1). V1-only endpoints (clip/cogvlm/sam/doctr/gaze/lmm, load/list models) must gate with self.__ensure_v1_client_mode() (raises WrongClientModeError) before building the request, and list it under Raises:. Skipping the gate produces confusing 404s against a V0 URL instead of a clear error.
-
New-endpoint shape. Resolve alias (resolve_roboflow_model_alias), load/encode input via load_static_inference_input (+ _async), inject via inject_images_into_payload / inject_nested_batches_of_images_into_payload, apply config via InferenceConfiguration.to_*_parameters, post, then api_key_safe_raise_for_status (canonical example: the core-model methods in #212).
-
InferenceConfiguration is the wire contract. frozen=True dataclass (http/entities.py); fields map to server query/body params via to_*_parameters() (V0 legacy vs V1 per-task). A field addition must be wired into the relevant mapping table, defaulted Optional[...] = None unless a hard default is intended, and documented — #1521 added workflow_run_retries_enabled, defaulted it from the config.py env flag WORKFLOW_RUN_RETRIES_ENABLED (via str2bool), and documented it.
-
Error taxonomy is public. http/errors.py: HTTPClientError (base) with subclasses incl. HTTPCallErrorError, WrongClientModeError, APIKeyNotProvided, FeatureDeprecatedError, plus the standalone RetryError. Renaming/removing one is a breaking change. New errors subclass HTTPClientError.
-
Deprecation is signalled, not silently broken. @deprecated(reason=...) / @experimental(info=...) (utils/decorators.py) emit InferenceSDKDeprecationWarning, gated by INFERENCE_WARNINGS_DISABLED. A hard removal raises FeatureDeprecatedError(feature=..., reason=..., removal_release=..., replacement=...), not a bare ValueError (test_detect_gazes_deprecated.py). infer_from_workflow is the canonical @deprecated case (superseded by run_workflow). MEMORY: only specific helpers escalate to FeatureDeprecatedError — don't over/under-apply.
-
HTTP session reuse + timeouts (sync path). The sync executor keeps a per-thread requests.Session via _get_thread_local_requests_session and runs a single-request package on the caller thread (make_parallel_requests short-circuits when len==1, avoiding a one-off ThreadPoolExecutor) so sequential workflow frames reuse TCP/TLS connections. requests.Session is not thread-safe, so parallel requests stay isolated per worker thread and reset the session on exit (_reset_thread_local_requests_session). A change that reintroduces a per-call Session(), shares one Session across threads, or routes single requests through the pool regresses this (#2538 recovered ~71% sequential FPS by reusing sync sessions). Retries flow through send_post_request(..., enable_retries=...), which maps RetryError → HTTPCallErrorError (#1521). Note the async path still opens a fresh aiohttp.ClientSession() per call — do not assume it reuses connections.
-
Exports. Top-level re-exports in inference_sdk/__init__.py (InferenceHTTPClient, InferenceConfiguration, VisualisationResponseFormat); WebRTC classes in both the from .sources import ... block and __all__ of inference_sdk/webrtc/__init__.py (#2200 added LocalStreamSource to both).
-
Dependency-light. Runtime deps pinned in requirements/requirements.sdk.http.txt / .webrtc.txt; a new third-party import needs a pin. Do not import heavy inference.core.*/model modules into inference_sdk.
-
Signatures + docstrings. Type-hinted public signatures with Google-style Args:/Returns:/Raises:. Image params typed ImagesReference = Union[np.ndarray, PIL.Image.Image, str].