Skip to main content

band-sdk-core

Shared Band event-payload validation, memory-taxonomy, and inbound-delivery runtime state, compiled from Rust into a native Python extension (import band_sdk_core). Every function is synchronous, pure computation — no network, filesystem, or logging.

band-sdk-core (Rust)  -->  band-sdk-core (this package, PyPI)  -->  band-sdk-python

If you're using band-sdk-python, it already depends on this package — you don't need to install it yourself. Install it directly only if you're calling into it without that SDK. Full picture: repository architecture.

Install

pip install band-sdk-core

Wheels are prebuilt (abi3, Python >= 3.11) for Linux (manylinux/musllinux, x86_64/aarch64), macOS (arm64/x86_64), and Windows (amd64/arm64) — no Rust toolchain needed to install.

Quickstart

import band_sdk_core

try:
    payload = band_sdk_core.validate_event_payload("room_deleted", {"id": "room-1"})
except ValueError as e:
    for path, code, message in e.issues:
        print(f"{path}: {code} - {message}")

validate_event_payload is the platform's inbound WebSocket payload policy: normalize a well-formed payload, or reject a malformed one with every violation reported at once, never just the first.

Public surface

validate_event_payload(event_type, raw, trace_context=None)

event_type is a platform name ("message_created", "agent.control", …) or an EventType. raw is a JSON-shaped Python value. Success returns the normalized payload (event_created returns the input unchanged). Failure raises ValueError with .args == (message,) (str(e) is ordinary), .issues (a tuple of (path, code, message)), and .trace_context. There is no custom exception class.

Room-activity observations

normalize_room_activity_snapshot(raw, self_agent_id, trace_context=None) accepts the decoded data object containing working_agents, validates every row, and returns list[RoomActivityPeer] as native dicts. It excludes all self executions, keeps the last duplicate (agent_id, execution_id) and sorts by agent/execution with null execution IDs first. Output omits execution IDs. Missing detail and unknown string kinds become reasoning; malformed fields reject the whole observation with structured ValueError. The canonical field rules live on the Rust normalize_room_activity_snapshot.

from band_sdk_core import normalize_room_activity_snapshot

peers = normalize_room_activity_snapshot({"working_agents": [
    {"agent_id": "peer", "working": True,
     "activity": {"kind": "tool_call", "name": "search"}}
]}, "self")
assert peers == [{"agent_id": "peer", "agent_name": "",
                  "activity": {"kind": "tool_call", "name": "search"}}]

Input must be JSON-native lists/dicts with string keys, finite JSON numbers and Unicode scalar strings. Unsupported values (including tuples, nonfinite numbers, out-of-range integers and surrogate strings) raise TypeError. Python integers must be in [-2**63, 2**64 - 1], inclusive; floats must be finite. These are Python conversion limits, not the JSON number grammar. JavaScript uses its finite Number representation; larger finite numeric extras may therefore be representable there but rejected as Python integers. Maximum depth is 64 (root zero), with 65,536 values and 1 MiB of UTF-8 string content including keys and string arguments. Extra fields are checked too. Cycles and excessive input reject safely; a later valid call can succeed. The SDK owns I/O and availability. Success is best-effort declared activity, not proof that peers are idle.

EventType

The closed set of inbound event names.

Delivery-state runtime classes

ClaimRegistry, RetryTracker, ParticipantRoster, and SubscriptionTracker are the inbound-delivery runtime state classes — lifecycle and design decisions live as rustdoc on each type in crates/core/src/runtime/.

A participant is any mapping; add/set_all read id, name, type, handle, description from it and list() returns dicts with exactly those five keys. id is required and must be a string; the other four are each a string or None. A non-mapping value, a missing/non-string id, or another field that is not a string or None raises TypeError. set_all takes an optional trace_context and raises ValueError — leaving the roster unchanged, with .issues and .trace_context attached like validate_event_payload's error — if its snapshot names the same id twice. RetryTracker's max_tracked must be at least 1; 0 raises ValueError. ClaimRegistry's max_completed must be at least 1 too — 0 also raises ValueError.

ClaimRegistry keeps one terminal intent per message until remember_completed or matching confirm_settlement: remember_ack_pending records a processed write and remember_failed_ack_pending a failed one carrying its error. The first intent wins; a different one raises ValueError — leaving the entry unchanged, with .issues and .trace_context attached — and an identical repeat is a no-op. pending_ack returns {"status", "error"?, "parked"} or None. park_ack takes a ParkedReason and raises TypeError for any other value, including its wire-name string; ParkedReason.from_wire_name converts.

SubscriptionTracker provides synchronous, transport-independent decisions for agent-topic joins and the two-topic room subscription transaction. It returns opaque integer tickets; callers supply the matching ticket when recording each completion. Failed rollbacks and failed or unknown leaves require explicit reconciliation before a fresh claim is allowed.

SubscriptionTracker lifecycle

from band_sdk_core import LeaveOutcome, RoomStatus, RoomSubscribeResult, SubscriptionTracker

tracker = SubscriptionTracker()
ticket = tracker.begin_room_subscribe("room-1")
if ticket is None:
    raise RuntimeError("room is not claimable")

result = tracker.record_room_participants_join_failed("room-1", ticket, False)
if result is RoomSubscribeResult.RollbackFailed:
    assert tracker.room_status("room-1") is RoomStatus.NeedsReconciliation
    assert tracker.acknowledge_room_reconciled("room-1") is True
    ticket = tracker.begin_room_subscribe("room-1")
    assert ticket is not None
    assert tracker.record_both_room_topics_joined("room-1", ticket) is RoomSubscribeResult.Subscribed
    leave_ticket = tracker.unsubscribe_room("room-1")
    assert leave_ticket is not None
    assert tracker.mark_room_leave_complete("room-1", leave_ticket, LeaveOutcome.Left) is True
else:
    match result:
        case (
            RoomSubscribeResult.Subscribed
            | RoomSubscribeResult.JoinFailed
            | RoomSubscribeResult.RolledBack
            | RoomSubscribeResult.Stale
        ):
            pass
        case _:
            raise AssertionError(f"unhandled subscription result: {result}")

DecisionRegistry lifecycle

DecisionRegistry tracks chat-mediated asks: whoever claims one first owns its outcome. Every registration returns (token, ticket), and later calls name that exact registration, so a stale holder gets ClaimOutcome.Stale instead of acting on a newer ask that reused the token. max_pending must be at least 1, and seed a non-negative 64-bit integer; either out of range raises ValueError. An omitted seed draws a fresh one. is_authorized_sender takes a set, frozenset, or None.

from band_sdk_core import ClaimOutcome, DecisionRegistry, is_authorized_sender

registry = DecisionRegistry(max_pending=10)
registration = registry.register_minted("room-1")
assert registration is not None
token, ticket = registration

assert registry.unclaimed_in_room("room-1") == [token]
assert registry.try_claim(token, ticket) is ClaimOutcome.Claimed
assert registry.try_claim(token, ticket) is ClaimOutcome.AlreadyClaimed
assert registry.cancel_room("room-1").claimed == [token]
assert is_authorized_sender(frozenset({"alice"}), "alice") is True

Session — WebSocket reconnect state machine

Session/SessionPolicy are a sans-io session state machine plus reconnect backoff/jitter policy; classify_close/classify_upgrade classify a WebSocket close code or HTTP upgrade-rejection status. Session never sleeps, connects, or closes a socket itself — the caller drives its own transport and reports what happened through on_connected/ on_socket_close/on_upgrade_rejected/on_supersede. Decisions live as rustdoc in crates/core/src/runtime/session.rs.

Session lifecycle

from band_sdk_core import Session, SessionPolicy, SessionState

session = Session(SessionPolicy.default())
epoch = session.begin_attempt(0.0)
assert epoch is not None

connected = session.on_connected(epoch, 0.0)
assert connected.state is SessionState.Up

disconnected = session.on_socket_close(epoch, 5.0, 1006, 0.5)
assert disconnected.state is SessionState.Reconnecting
assert disconnected.retry_after_s is not None

Memory taxonomy

MemorySystem, MemoryType, MemorySegment, MemoryStoreScope, MemoryListScope, MemoryStatus are the canonical memory taxonomy — design decisions live as rustdoc in crates/core/src/memory.rs. Each is a closed set with a wire_name property and a from_wire_name static method (None for an unrecognized string), mirroring EventType.

validate_memory_type_for_system(system, memory_type, trace_context=None)

system/memory_type are each a wire-name string or the matching MemorySystem/MemoryType instance (mirroring validate_event_payload's acceptance of either an event name or an EventType), and it returns None on success. Failure raises ValueError with the same .issues/.trace_context contract as validate_event_payload — an unrecognized system and an unrecognized memory_type are independent issues, both reported when both strings are invalid.

One-shot delivery lifecycle

evaluate_delivery_event, evaluate_next_message, evaluate_drain_candidate, and evaluate_adapter_result are the stateless one-shot delivery lifecycle decisions — design decisions live as rustdoc in crates/core/src/runtime/delivery.rs. Each returns a plain dict tagged by its own "decision" string; there is no cross-invocation state, so there is no class here to construct.

evaluate_delivery_event(event_type, room_id, payload, agent_id, trace_context=None) routes one inbound event: "ignored" for an unrecognized or out-of-scope event_type; "cleanup" for room_removed/room_deleted; "skip_self" or "invocation" for message_created, depending on whether the sender is this agent (sender_type == "Agent" and sender_id == agent_id). message_created delegates to validate_event_payload for payload-shape validation, so a malformed payload raises the same ValueError, and additionally rejects an empty payload["id"] — a message with no identity cannot be claimed or acknowledged. room_removed/room_deleted need no payload shape and read id straight off the raw payload.

room_id resolves from the caller-supplied room_id first, else the payload's own chat_room_id (message events) or id (room events). An empty string counts as absent at both steps. Unresolvable raises ValueError with one issue on path room_id: code missing when the fallback field is absent or empty, wrong_type when it is present but not a string.

evaluate_next_message(triggering_message_id, next_message_id) compares the triggering message against the platform's authoritative "next open message" for a room (already fetched by the caller): "no_pending", "already_processed", or "ready_to_claim".

evaluate_drain_candidate(candidate, seen_ids, agent_id) classifies one already-fetched drain candidate — candidate is a mapping with id, sender_id, sender_type, or None when the fetch returned nothing: "no_candidate", "self_echo" (checked before the snapshot, so an echo never halts a drain), "out_of_snapshot" (stop), or "drain" (continue). The caller's own bounded or unbounded loop owns the cap; this function classifies one candidate per call.

evaluate_adapter_result(room_id, message_id, succeeded) maps an adapter outcome to "processed" or "failed".

is_self_echo(sender_id, sender_type, agent_id) is the one definition of "self echo" (sender_type == "Agent" and sender_id == agent_id) that evaluate_delivery_event and evaluate_drain_candidate use internally, exposed for a host's own call sites that classify a sender without going through either function.

Turn outcome

TurnLedger judges one agent turn — design decisions live as rustdoc in crates/core/src/turn.rs. Create one per turn, record the TurnEffect of each successful tool call (a failed call records nothing), and ask for the verdict() when the model stops: TurnVerdict.Complete once the turn replied, declined, or did real work, else TurnVerdict.MissingReply (fail the turn with missing_reply_message()). settle() marks a turn the SDK answered itself and note_reported() one whose failure was already reported; both complete it. reply_settled() is True once a recorded call posted to the room or declined to, so no fallback text is due. record takes a TurnEffect only; a wire-name string raises TypeError (convert one with TurnEffect.from_wire_name).

band_tool_effects() maps every canonical Band tool name to its TurnEffect; normalize an alias to its canonical name before the lookup. no_reply_tool() returns band_no_reply's definition as a ToolSpec dict (name, description, parameters).

from band_sdk_core import TurnEffect, TurnLedger, TurnVerdict, band_tool_effects

ledger = TurnLedger()
ledger.record(band_tool_effects()["band_send_event"])
assert ledger.verdict() == TurnVerdict.MissingReply

ledger.record(TurnEffect.Reply)
assert ledger.verdict() == TurnVerdict.Complete
assert ledger.reply_settled()

Values across the language boundary

JSON objects become Python dicts. JSON null becomes None. An explicit null stays distinct from an absent key — a distinction the payload validator uses. Values that cannot be converted raise TypeError, which except Exception catches.

Build / test

just check type-checks and lints this crate. Linking the extension happens through uv / maturin (just test-py, just build-py), not cargo test.

just test-py     # uv sync, pytest, isolated wheel install
just build-py    # uv build (wheel only)

Wheels are platform-specific. Recipes use uv and honor UV_PYTHON, or PYTHON / PYTHON_BIN. Windows builds need the MSVC toolchain rustup's default host target uses.

The wheel is abi3 for Python >= 3.11. This is a mixed Python/Rust maturin package: python/band_sdk_core/ holds the typed surface — __init__.pyi, an empty py.typed, and an __init__.py that re-exports the compiled extension and defines the delivery decisions' TypedDict return shapes (pure typing constructs with no pyo3 equivalent). just test-py checks the stub matches the runtime package and that both ship in the wheel.

License

Proprietary, binary-only Band SDK License Agreement — see the bundled LICENSE. The Rust implementation source is private.

Fenced delivery settlement

guarded_claim uses the same eligibility decision for every discovery path. Pending originals stay excluded even when parked. Record terminal intent before awaiting transport; call confirm_settlement only after durable acceptance and a current-execution check. An uncertain response leaves the exact intent retained. Retry confirmation restores charged attempts into a replacement tracker without marking the input completed; it keeps the stricter retry ceiling.

from band_sdk_core import ClaimRegistry, RetryTracker

claims = ClaimRegistry()
previous = RetryTracker(max_retries=3)
assert claims.guarded_claim("room", "message", previous) == "runnable"
assert previous.record_attempt("message") == (1, False)
pending = claims.record_failed_settlement("room", "message", "failure", previous, True)
claims.release("room", "message")
current = RetryTracker(max_retries=3)
assert claims.guarded_claim("room", "message", current) == "pending"
assert claims.confirm_settlement("room", "message", pending["token"], current)
assert not claims.is_completed("room", "message")
assert current.record_attempt("message") == (2, False)

Metadata

Release files for band-sdk-core 6.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for band-sdk-core 6.1.0
File
band_sdk_core-6.1.0-cp311-abi3-win_arm64.whl CPython 3.11 abi3 Windows ARM64 Details
band_sdk_core-6.1.0-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
band_sdk_core-6.1.0-cp311-abi3-musllinux_1_2_x86_64.whl CPython 3.11 abi3 Linux musl 1.2+ x86-64 Details
band_sdk_core-6.1.0-cp311-abi3-musllinux_1_2_aarch64.whl CPython 3.11 abi3 Linux musl 1.2+ ARM64 Details
band_sdk_core-6.1.0-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details
band_sdk_core-6.1.0-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details
band_sdk_core-6.1.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details
band_sdk_core-6.1.0-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details

Total release size: 5.0 MB

Release files / band_sdk_core-6.1.0-cp311-abi3-win_arm64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-win_arm64.whl
Size 422.6 kB
Tags CPython 3.11 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
ef67b65f781d1bf5d00a47b39732d9bf4cbe56117989534dd917c92a66f2375a
BLAKE2b-256 checksum
How to use checksums
9e36b0252a7b602446c6b4d05c2306e0b0a24c5f1ec82125b8f7c08f316c24ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-win_amd64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-win_amd64.whl
Size 444.1 kB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
3241447f9511fffc22bcd6bc6e51cc420adbf2f6897450aa1ee3900402a22db1
BLAKE2b-256 checksum
How to use checksums
4718115cc67ad3cf2583aa10c7b8824d593bd4b8383b29aa92eddb2dadbaf2c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-musllinux_1_2_x86_64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-musllinux_1_2_x86_64.whl
Size 854.5 kB
Tags CPython 3.11 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
6cfd79449111fccb36a2657a012001c553c4d87fa3da2abd1dc79ed138bfca1b
BLAKE2b-256 checksum
How to use checksums
0dc01009d01c890e45f9b93af943272a04d10964760aa86f1e3d044ce4936ee2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-musllinux_1_2_aarch64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-musllinux_1_2_aarch64.whl
Size 814.5 kB
Tags CPython 3.11 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
0cc732a9b8308e98483f10c46e9e9ea3debafd0a4c00954ab5d9911eb149297d
BLAKE2b-256 checksum
How to use checksums
d58d5a71407dc67c9839eccde40f99996e326fe574945b0e0bd650765684f100
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-manylinux_2_28_x86_64.whl
Size 630.6 kB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
47470f3d32156b154d12d93d857358e32b8cfaefb8fd2ba7e9049373be580b10
BLAKE2b-256 checksum
How to use checksums
e44b806224d3496c8e9fec69f5d6d90b9e7e505ca496021a5b86385beccc3c2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-manylinux_2_28_aarch64.whl
Size 634.2 kB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
e462d231d62b3c0ba150f63902ff8f265e0028100a9f4d910eba8ac7e9db0c13
BLAKE2b-256 checksum
How to use checksums
ef7f2e0123a96c13b95cc7d3fa0de9058d8b150c874f751c467b2e82376fef51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-macosx_11_0_arm64.whl
Size 581.2 kB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e3c3e89a8970ede6eed172d0e9cecc5add4eb11d42521a543f9d2115e47b6e52
BLAKE2b-256 checksum
How to use checksums
c62e434197bd3ffe8e3fc165f78857c67038a88b4d8f0800747259a6507ef271
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Release files / band_sdk_core-6.1.0-cp311-abi3-macosx_10_12_x86_64.whl

Download URL band_sdk_core-6.1.0-cp311-abi3-macosx_10_12_x86_64.whl
Size 580.5 kB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
1599b18c1490fc06c8c2e457d216a03b9881ed1275450cad8b1df41cd30ec9ea
BLAKE2b-256 checksum
How to use checksums
1a910ddecddd13ec18b8d3b2ee1c9be76881c4af0d8c184249f0bceb2ea793f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 25, 2026.

Transparency log

Security for band-sdk-core 6.1.0

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.

Full provenance

All 8 files in this release have been uploaded with provenance metadata.

Select from 8 files

Attestation for band_sdk_core-6.1.0-cp311-abi3-win_arm64.whl

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 Oct 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

6.1.0 This release

8 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page