spareparts-sdk
Drop-in OpenTelemetry tracing for OpenAI, Anthropic, and Gemini LLM calls, captured locally and optionally exported to Spare Parts Core.
import spareparts_sdk as spareparts
spareparts.init(service_name="mechanic-assistant")
with spareparts.workflow("diagnose"):
response = client.messages.create(...)
Install with the providers you use:
pip install 'spareparts-sdk[anthropic]' # or [openai], [gemini], [all]
Tracing
After init(), any instrumented provider call in this process is traced and written to a
local SQLite file (./.spareparts/traces.db by default). Each span row carries the model,
provider, prompt/completion content, input/output/cache token counts, cost, latency,
status, and any exception type and message.
init() takes:
| argument | default | what it does |
|---|---|---|
project_id |
None |
Tags every span for later filtering. |
sample_rate |
1.0 |
Head sampling ratio. Parent-based, so a sampled trace keeps all its child spans. |
capture_content |
True |
False strips prompts/completions and keeps only metadata. |
redact |
None |
Callable applied to every prompt/completion string before export. |
max_content_chars |
24000 |
Per-field cap; longer values get a …[truncated] marker. |
service_name |
"llm-app" |
Logical service name on every span. |
environment |
"production" |
Deployment environment on every span. |
local_dir |
".spareparts" |
Directory holding traces.db. |
endpoint |
None |
Core base URL for authenticated remote span export. |
api_key |
None |
Workspace API key or lease-bound runner token; never persisted. |
attributes |
None |
Stable attribution fields added to every emitted span. |
project_id, environment, service_name, and local_dir resolve the same way:
explicit kwarg > env var (SPAREPARTS_PROJECT, SPAREPARTS_ENV,
SPAREPARTS_SERVICE_NAME, SPAREPARTS_LOCAL_DIR) > a repo-root spareparts.toml's
[capture] table > the default above.
# spareparts.toml
[capture]
project = "sparepartslabs/spareparts"
service_name = "spareparts-api"
environment = "production"
local_dir = ".spareparts"
Remote export
Pass endpoint and api_key together to send the same canonical spans to Core. Failed batches stay pending in memory; call flush() before completing a short-lived job so it can retry or fail the job instead of losing telemetry. Span IDs make retries idempotent.
spareparts.init(endpoint="https://api.example", api_key=token, capture_content=False)
# run model work
if not spareparts.flush():
raise RuntimeError("telemetry was not accepted")
Workflow tracking
workflow(name) opens a named parent span. Every LLM call made inside becomes a child of
it, so a trace's root span name identifies the feature the calls belong to, which is what
makes per-feature cost and latency grouping possible. It works as a context manager or as
a decorator on sync and async functions:
@spareparts.workflow("mechanic-assistant")
async def _ai_reply(message: str) -> str:
response = await client.messages.create(...)
return response.content[0].text
An exception raised inside a workflow propagates unchanged; the span is marked error and
keeps the exception type and message.
Reading traces
traces.db is plain SQLite with a single spans table:
sqlite3 .spareparts/traces.db \
"SELECT started_at, name, model, input_tokens, output_tokens, cost, latency_ms
FROM spans ORDER BY started_at DESC LIMIT 20;"
Group a run's cost by feature via the root span:
SELECT root.name, COUNT(*) AS calls, ROUND(SUM(child.cost), 4) AS cost_usd
FROM spans child
JOIN spans root ON root.span_id = child.parent_span_id
GROUP BY root.name
ORDER BY cost_usd DESC;
The schema is the contract with anything that reads the file, so it changes only as a public interface would.
Tests
pip install -e '.[dev]'
pytest
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spareparts_sdk-0.2.0.tar.gz.
File metadata
- Download URL: spareparts_sdk-0.2.0.tar.gz
- Upload date:
- Size: 64.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
265b991b0709a19a5d9026ea763e6dee870186b03c234ff3331f917bddf0f1c0
|
|
| MD5 |
1ac14e9d228a7275ba4ab187788a2c58
|
|
| BLAKE2b-256 |
cb22441df30a2d61df01fd3ab9ab2bcf2bfaafd4a4aee84a5bc5b71086f432b4
|
Provenance
The following attestation bundles were made for spareparts_sdk-0.2.0.tar.gz:
Publisher:
publish.yml on sparepartslabs/spareparts-sdk-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spareparts_sdk-0.2.0.tar.gz -
Subject digest:
265b991b0709a19a5d9026ea763e6dee870186b03c234ff3331f917bddf0f1c0 - Sigstore transparency entry: 2579580540
- Sigstore integration time:
-
Permalink:
sparepartslabs/spareparts-sdk-py@9bda495eccd66f384f6906e1d5260e59879f929e -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sparepartslabs
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9bda495eccd66f384f6906e1d5260e59879f929e -
Trigger Event:
push
-
Statement type:
File details
Details for the file spareparts_sdk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: spareparts_sdk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e35f5637d7775fcdd94469523db5843d23f76e835f1b5befd111459a18cf5d6d
|
|
| MD5 |
0ca666971378f4a1941eb1135aa837cf
|
|
| BLAKE2b-256 |
86cc195bb0599f3302aa0812c51ca3353e21b0c89d0829795cf014ea9a1c1b1d
|
Provenance
The following attestation bundles were made for spareparts_sdk-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on sparepartslabs/spareparts-sdk-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spareparts_sdk-0.2.0-py3-none-any.whl -
Subject digest:
e35f5637d7775fcdd94469523db5843d23f76e835f1b5befd111459a18cf5d6d - Sigstore transparency entry: 2579580547
- Sigstore integration time:
-
Permalink:
sparepartslabs/spareparts-sdk-py@9bda495eccd66f384f6906e1d5260e59879f929e -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/sparepartslabs
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9bda495eccd66f384f6906e1d5260e59879f929e -
Trigger Event:
push
-
Statement type: