Extending: adding a provider
Each provider is an adapter that inherits from Provider and translates the
normalized types to the native SDK.
Steps
- Create
jangada/providers/<name>.pywith a class that inherits fromProviderand implements the 6 methods +_build_client/_build_async_client. - Define
nameandenv_key. - Import the SDK only inside the methods (lazy imports — invariant).
- Register it in
registry.pywith a lazy loader. - Add the extra in
pyproject.toml.
Contract (Provider)
class Provider:
name: str
env_key: str | None
def _build_client(self) -> Any: ...
def _build_async_client(self) -> Any: ...
def complete(self, messages, **opts) -> Completion: ...
async def acomplete(self, messages, **opts) -> Completion: ...
def parse(self, messages, schema, **opts) -> Completion: ...
async def aparse(self, messages, schema, **opts) -> Completion: ...
def stream(self, messages, **opts) -> Iterator[str]: ...
def astream(self, messages, **opts) -> AsyncIterator[str]: ...Shortcut for the OpenAI dialect
If the provider speaks chat.completions (OpenAI style), inherit from
_OpenAICompatible and just adjust the attributes:
class MyProvider(_OpenAICompatible):
name = "my"
env_key = "MY_API_KEY"
sdk_module = "my_sdk"
sync_class = "Client"
async_class = "AsyncClient"
supports_parse_helper = False # True if it has a native .parse()Invariants to respect
- Lazy imports:
import jangada_aimust work without the SDK. - Normalized types at the boundary: outside the adapters only
Message/Completioncirculate; native objects stay inCompletion.raw. - Always translate errors: wrap SDK calls in
try/exceptand re-raise viaclassify(e, self.name)— see Errors. - Sync/async parity: every method has an
a*version. - Per-model quirks go in
profiles.py— see Parameters.
Tests
Use the FakeProvider pattern registered at runtime; see tests/conftest.py.
Tutorial: MCP agent from scratch
Goal: connect to an MCP (Model Context Protocol) server and let the model use the tools on its own — it decides which tool to call, jangada runs it and sends it back, until the...
Flows and orchestration (Flow and Graph)
Jangada provides two ways to chain calls, both aggregating usage/cost.