Metadata-Version: 2.4
Name: stablebrowse
Version: 0.3.0
Summary: Python client for the stablebrowse browser agent API
Author: stablebrowse
License: MIT
Project-URL: Homepage, https://docs.stablebrowse.com/introduction
Project-URL: Documentation, https://docs.stablebrowse.com/introduction
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx<1.0,>=0.27

# stablebrowse (Python)

Python client for the stablebrowse browser agent API.

## Install

From PyPI (once published):

```bash
pip install stablebrowse
```

From source (for local development):

```bash
cd sdks/python
pip install -e .
```

Requires Python 3.9+. Depends on `httpx`.

## Quick start

```python
from stablebrowse import Stablebrowse

# Bearer token comes from either the constructor or the
# STABLEBROWSE_API_KEY environment variable.
client = Stablebrowse(api_key="sb_live_...")

# (Optional) upload per-end-user social-media credentials.
client.end_users("alice").credentials.set(
    twitter_auth_token="...",
    twitter_ct0="...",
)

# Sync-feeling submit. Polls internally until the task terminates.
result = client.tasks.run(
    end_user_id="alice",
    task="find the top AI tweets today",
)
print(result.result)
```

## Async primitives

If you want to drive the poll loop yourself — for example, to push progress
into your own queue, or to run many submissions in parallel with your own
scheduler — use the raw methods:

```python
submission = client.tasks.submit(end_user_id="alice", task="...")
while True:
    task = client.tasks.get(submission.task_id)
    if task.is_terminal:
        break
    time.sleep(2)
```

## Multi-turn conversations

Pass the `session_id` you got from the first call to continue a conversation:

```python
first = client.tasks.run(end_user_id="alice", task="who's trending on X?")
follow = client.tasks.run(
    end_user_id="alice",
    task="what about in music specifically?",
    session_id=first.session_id,
)
```

The server builds `previousContext` from the last completed turn so the
agent has the earlier answer when it reasons about the follow-up.

## End users and credentials

Each business scopes end-users by opaque identifier — "alice" inside your
business is independent of any other business's "alice":

```python
alice = client.end_users("alice")

alice.credentials.set(
    tiktok_session_id="...",
    tiktok_csrf_token="...",
)

status = alice.credentials.get()
assert status.platforms["tiktok"] is True

# Remove all creds
alice.credentials.delete()

# Or a specific subset
alice.credentials.delete(fields=["twitter_auth_token", "twitter_ct0"])
```

Field names are snake_case in Python and get translated to camelCase on the
wire automatically.

## API key management

Create and revoke keys in the dashboard under **Settings → API Keys**.
Key lifecycle is dashboard-only by design — a leaked key can't mint more.

## Errors

Every exception derives from `StablebrowseError`:

- `TaskFailed` — `run()` saw the task finish with status=failed. The
  failed `Task` is on `.task`.
- `TaskTimeout` — the poll deadline expired before the task terminated.
  The still-running `Task` is on `.task` so you can keep polling.
- `StablebrowseError` — every other HTTP or transport error. `.status_code`
  and `.body` are populated when the server returned structured JSON.

## Configuration

The constructor reads a couple of env vars if you don't pass them:

- `STABLEBROWSE_API_KEY` — bearer token
- `STABLEBROWSE_BASE_URL` — override the API base, useful for pointing at
  beta or a local gateway
