You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**That's it!** With no `api_base`, the client defaults to the hosted gateway at `https://api.otari.ai`. Change the model string to switch between LLM providers through the gateway.
42
42
43
+
Prefer async? Use `AsyncOtariClient`, which exposes the same API with `await` (see [Async usage](#async-usage)).
44
+
43
45
Prefer to keep secrets out of code? Set `OTARI_AI_TOKEN` in your environment and `OtariClient()` picks up the token automatically.
44
46
45
47
## Self-hosting the gateway
@@ -118,6 +120,8 @@ Prefer a hosted experience? The [otari platform](https://otari.ai/) provides a m
118
120
119
121
## Usage
120
122
123
+
> **Migrating from a previous version?**`OtariClient` is now **synchronous** — call its methods directly (no `await`). For asynchronous code, switch to `AsyncOtariClient`, which keeps the previous `await`-based API. See [Async usage](#async-usage).
124
+
121
125
### Authentication Modes
122
126
123
127
The client supports two authentication modes, matching the TypeScript SDK:
Every method on `OtariClient` has an asynchronous counterpart on `AsyncOtariClient`. It accepts the same constructor arguments and exposes the same methods, but they are coroutines you `await` (and streams are async iterables):
220
+
221
+
```python
222
+
import asyncio
223
+
224
+
from otari import AsyncOtariClient
225
+
226
+
227
+
asyncdefmain() -> None:
228
+
asyncwith AsyncOtariClient(platform_token="tk_your_api_token") as client:
229
+
response =await client.completion(
230
+
model="openai:gpt-4o-mini",
231
+
messages=[{"role": "user", "content": "Hello!"}],
232
+
)
233
+
print(response.choices[0].message.content)
234
+
235
+
stream =await client.completion(
236
+
model="openai:gpt-4o-mini",
237
+
messages=[{"role": "user", "content": "Tell me a story."}],
238
+
stream=True,
239
+
)
240
+
asyncfor chunk in stream:
241
+
content = chunk.choices[0].delta.content
242
+
if content:
243
+
print(content, end="", flush=True)
244
+
245
+
246
+
asyncio.run(main())
247
+
```
248
+
213
249
### Error Handling
214
250
215
251
In platform mode, HTTP errors are mapped to typed exceptions:
@@ -218,7 +254,7 @@ In platform mode, HTTP errors are mapped to typed exceptions:
218
254
from otari import OtariClient, AuthenticationError, RateLimitError
219
255
220
256
try:
221
-
response =awaitclient.completion(
257
+
response = client.completion(
222
258
model="openai:gpt-4o-mini",
223
259
messages=[{"role": "user", "content": "Hello!"}],
224
260
)
@@ -242,10 +278,20 @@ except RateLimitError as e:
242
278
243
279
### Context Manager
244
280
245
-
The client supports async context manager for automatic cleanup:
281
+
The client supports a context manager for automatic cleanup:
282
+
283
+
```python
284
+
with OtariClient(api_base="http://localhost:8000") as client:
285
+
response = client.completion(
286
+
model="openai:gpt-4o-mini",
287
+
messages=[{"role": "user", "content": "Hello!"}],
288
+
)
289
+
```
290
+
291
+
`AsyncOtariClient` supports the async equivalent:
246
292
247
293
```python
248
-
asyncwithOtariClient(api_base="http://localhost:8000") as client:
294
+
asyncwithAsyncOtariClient(api_base="http://localhost:8000") as client:
249
295
response =await client.completion(
250
296
model="openai:gpt-4o-mini",
251
297
messages=[{"role": "user", "content": "Hello!"}],
@@ -257,7 +303,7 @@ async with OtariClient(api_base="http://localhost:8000") as client:
257
303
-**Simple, unified interface** - Single client for all providers through the gateway, switch models with just a string change
258
304
-**Developer friendly** - Full type hints for better IDE support and clear, actionable error messages
259
305
-**Leverages the OpenAI SDK** - Built on the official OpenAI Python SDK for maximum compatibility
260
-
-**Async-first** - Built on `AsyncOpenAI` for modern async Python applications
306
+
-**Sync and async** - Use the synchronous `OtariClient` or the asynchronous `AsyncOtariClient`, both with the same typed interface
261
307
-**Stays framework-agnostic** so it can be used across different projects and use cases
262
308
-**Battle-tested** - Powers our own production tools ([any-agent](https://github.com/mozilla-ai/any-agent))
0 commit comments