litellm-ibm-bob
LiteLLM custom provider for IBM Bob (bobshell). Replicates the wire
protocol of the official bob CLI — including HMAC request signing, key-shape
backend selection, and automatic instance/team derivation against
/admin/v1/profile.
Install & develop
This project uses uv. All commands assume an active virtualenv:
uv venv # creates .venv if not present
source .venv/bin/activate # activate the venv for the rest of the session
uv sync # install runtime + dev deps in editable mode
If a command in this README doesn't start with source .venv/bin/activate,
run it inside the activated venv (or prefix with uv run).
Usage from LiteLLM
import litellm
import litellm_ibm_bob # importing this registers the `ibm-bob` provider
resp = litellm.completion(
model="ibm-bob/premium",
messages=[{"role": "user", "content": "hi"}],
api_key="<BOBSHELL_API_KEY>",
# instance_id / team_id are optional — derived automatically via
# /admin/v1/profile, the same way `bob` does. Pass them explicitly only
# when you need to override (mirrors bob's --instance-id / --team-id flags).
)
print(resp.choices[0].message.content)
Environment / kwarg surface (matches bob itself — no BOBSHELL_INSTANCE_ID
or BOBSHELL_TEAM_ID are read, since bob doesn't read them either):
| Source | Purpose |
|---|---|
BOBSHELL_API_KEY env, or api_key= kwarg |
API key. Auto-classified (sk-/pk- legacy, JWT, opaque). |
CUSTOM_BASE_URL env, or api_base= kwarg |
Override backend host (mirrors bob's $CUSTOM_BASE_URL). |
instance_id= kwarg |
Override auto-derived instance (mirrors bob --instance-id). |
team_id= kwarg |
Override auto-derived team (mirrors bob --team-id). |
Backend routing
| Key shape | Backend | Auth header | HMAC signed |
|---|---|---|---|
sk-…, pk-… (legacy) |
prod.ibm-bob-staging.cloud.ibm.com |
Bearer … |
no |
| Parses as a JWT | api.us-east.bob.ibm.com |
Bearer … |
yes |
Anything else (e.g. bob_prod_…) |
api.us-east.bob.ibm.com |
Apikey … |
yes |
Testing
The full suite reads exactly one env var, BOBSHELL_API_KEY. Tests for code
paths incompatible with the supplied key auto-skip.
source .venv/bin/activate
# Unit tests — no network, runs anywhere
pytest tests/unit -q
# Integration tests — live calls. Skips automatically when BOBSHELL_API_KEY
# is unset. Provides:
# - legacy-key tests pass when BOBSHELL_API_KEY is sk-/pk-
# - new-key tests pass when BOBSHELL_API_KEY is JWT/opaque
BOBSHELL_API_KEY=bob_prod_... pytest tests/integration -v
Maintainer helper scripts
These live in scripts/ at the repo root. They are not packaged in the
distributable wheel — installing the package does not give the user these
helpers. Run them directly with python scripts/<name>.py … inside the venv.
scripts/extract_secrets.py
When to run: Whenever you bump the pinned upstream bob CLI version. The
runtime package reads only src/litellm_ibm_bob/_secrets.json; this script is
the only supported way to regenerate it.
What it does: Reads a bob Node.js bundle (the bob symlink at
/opt/homebrew/bin/bob, the underlying bundle/bob.js, or the pretty-printed
source). Locates the embedded BUILD_TIME_HMAC_SECRET marker, derives the
AES-256-CBC key via sha256(content-with-marker-stripped), decrypts the
secret, and writes a minimal JSON file containing only the two fields the
runtime needs: version and build_time_hmac_secret.
source .venv/bin/activate
# Regenerate the committed _secrets.json from your locally installed bob
python scripts/extract_secrets.py /opt/homebrew/bin/bob
# Preview without writing
python scripts/extract_secrets.py /opt/homebrew/bin/bob --stdout
# Write to a custom path
python scripts/extract_secrets.py /opt/homebrew/bin/bob \
--output /tmp/new-secrets.json
After regenerating, commit the updated src/litellm_ibm_bob/_secrets.json and
ship a new release. The wheel build (uv build) embeds the JSON file
automatically; verify with unzip -l dist/*.whl.
scripts/http_cli.py
When to run: For manual troubleshooting only — verifying API-key behaviour, exploring undocumented endpoints, checking why a signature is rejected, or capturing a response body for a unit-test fixture. Not invoked by any other part of this codebase, and not needed by end users of the provider.
What it does: Makes a single signed HTTP request against the Bob backend
using the same auth/signing pipeline as the runtime provider. Auto-detects
backend host and auth scheme from the BOBSHELL_API_KEY shape. Override
flags exactly mirror bob's CLI flags (--instance-id, --team-id,
--base-url).
source .venv/bin/activate
export BOBSHELL_API_KEY=...
# Smoke-test the modern signed backend
python scripts/http_cli.py GET /inference/v1/model/info
# Smoke-test the legacy backend (auto-selected when key starts with sk-/pk-)
python scripts/http_cli.py GET /v1/model/info
# POST a chat completion from a file
python scripts/http_cli.py POST /inference/v1/chat/completions \
--body @payload.json
# Override anything `bob` lets you override
python scripts/http_cli.py \
--instance-id <uuid> --team-id <uuid> \
--base-url https://api.dev.bob.ibm.com \
--show-headers \
GET /admin/v1/profile
# Disable signing (useful for staging hosts that don't validate signatures)
python scripts/http_cli.py --no-sign GET /v1/model/info
Code quality
source .venv/bin/activate
ruff format src tests scripts
ruff check src tests scripts
Ruff is configured for lint + format. The ANN ruleset enforces that public
APIs carry type annotations (Ruff itself does not perform type checking).
Build
source .venv/bin/activate
uv build # produces dist/*.whl and dist/*.tar.gz
unzip -l dist/litellm_ibm_bob-*.whl # verify _secrets.json is bundled
Metadata
Release files for litellm-ibm-bob 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| litellm_ibm_bob-0.1.0.tar.gz | 12.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| litellm_ibm_bob-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.9 kB
Release files / litellm_ibm_bob-0.1.0.tar.gz
| Download URL | litellm_ibm_bob-0.1.0.tar.gz |
|---|---|
| Size | 12.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
58977125fba95b57ef98152127d7f216d545262d9341caf2bf14e5d2f572d835
|
|
BLAKE2b-256 checksum How to use checksums |
44babe4ede5281732d57d0deebdc606937f2b4f21920bc70ef049bbf64fba0e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency logRelease files / litellm_ibm_bob-0.1.0-py3-none-any.whl
| Download URL | litellm_ibm_bob-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
55766b955fe7857323922fd0a46cf9eea3de1e29667ccef68eb650df23e38075
|
|
BLAKE2b-256 checksum How to use checksums |
b57ce838acc2f73c9e9fb34da1e8073c4c24cc5428b4a93b1777042313e802df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency log