Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Mango Python SDK

Typed synchronous and asynchronous clients for every operation in Mango's current OpenAPI: Agents, Environments and Work, Sessions and Threads, Events, Resources, Files, Skills, Memory, Vaults, Webhooks, Deployments, and probes. The distribution name is mango-sdk; Python imports use mango_sdk. This is an alpha SDK, not a stable release. Mango's development API can change in place; use an SDK version built for the server revision you deploy.

Install

Python 3.11 or newer is required. This checkout prepares 0.1.0a3. Select a matching version or inspected wheel/source package from the release record, which confirms registry availability. The previously published alpha 1 has an earlier interface.

To use this checkout before publication or during development, from the repository root:

python3 -m venv .venv
.venv/bin/python -m pip install ./sdk/python

For SDK development, use cd sdk/python && uv sync --frozen. This creates an isolated .venv, installs the editable package, and uses the checked-in lockfile. No hosted-agent account or credential is required.

Start a Session

import os
from mango_sdk import Mango

with Mango(
    base_url=os.environ.get("MANGO_URL", "http://localhost:8080"),
    api_key=os.environ["MANGO_API_KEY"],
) as client:
    # Omitted config defaults to self-hosted execution.
    environment = client.environments.create(name="python-example")
    agent = client.agents.create(name="assistant", model=os.environ["MANGO_MODEL"], system="Be concise and helpful.")
    session = client.sessions.create(agent={"type": "agent", "id": agent["id"]}, environment_id=environment["id"])
    client.sessions.events.send(session["id"], events=[{
        "type": "user.message",
        "content": [{"type": "text", "text": "Hello!"}],
    }])
    for event in client.sessions.events.iter(session["id"], order="asc"):
        print(event)

Methods are grouped by resource: client.agents.create, client.sessions.threads.list, and client.sessions.threads.events.stream. Path IDs are positional in HTTP hierarchy order. Request fields and query filters are keyword arguments; a prebuilt typed request can be expanded with **request. Bracketed query names use types and created_at_gte; the transport preserves the wire spelling and repeated values. base_url may include a reverse-proxy prefix; do not append /v1. Public probes are under client.system.

Request and response dictionaries have static types in mango_sdk.models. Tagged unions preserve literal discriminators; all component schemas are emitted. Closed objects are TypedDicts, not runtime validation models. Open JSON objects, including custom-tool input_schema, use dictionaries so JSON Schema keywords such as properties, required, and $defs remain expressible. The server validates their constraints. Omit a dictionary key to leave a field unchanged; pass None only to send explicit JSON null on a nullable field. False, 0, "", and [] are not silently dropped.

list_* returns one typed page. iter_* fetches all pages lazily, preserving query filters. Files use after_id/before_id; other resources use next_page. Do not use an unbounded iterator if you only need one page.

Async client and streaming

import asyncio
import os
from mango_sdk import AsyncMango

async def watch(session_id: str) -> None:
    async with AsyncMango(api_key=os.environ["MANGO_API_KEY"]) as client:
        session = await client.sessions.retrieve(session_id)
        print(session["status"])
        async with client.sessions.events.stream(
            session_id, event_deltas=["agent.message"],
        ) as stream:
            async for envelope in stream:
                print(envelope.event, envelope.data)
                if envelope.event in ("session.status_idle", "session.deleted"):
                    break

# asyncio.run(watch("sesn_..."))

Synchronous streaming uses with client.sessions.events.stream(id) as stream and for envelope in stream. Always use the context manager, especially when breaking early. Downloads use the same lifecycle and iter_bytes() (an async iterator on the async client); read() explicitly buffers the complete payload. The async streaming factory is deliberately not awaited; the context opens it.

Streams default to no read timeout and have no finite overall deadline. HTTP connection/write/pool timeouts still apply. A custom httpx.Timeout can override these through stream_timeout. Closing the stream or cancelling its consuming async task releases the connection. Streams parse split UTF-8, comments, multiline data, and CR/LF delimiters incrementally. Unterminated SSE lines and complete SSE frame data are each limited to 64 MiB; oversized input raises ResponseDecodeError and closes the stream. HTTP error bodies are read only up to 64 KiB (APIError.body_truncated indicates truncation).

Streams are live-only. They do not replay prior events, do not support Last-Event-ID, and the SDK does not silently reconnect. For gap-free application recovery, open a stream first, list history while it remains open, then merge and deduplicate persisted events by ID. Preview frames are ephemeral and must not be treated as authoritative history. This SDK exposes those primitives but does not yet supply an automatic history-and-live merger.

Uploads, downloads, and errors

from mango_sdk import APIError, Mango, Upload

with Mango(api_key="workspace-key") as client:
    with open("analysis.csv", "rb") as source:
        uploaded = client.files.upload(file=Upload("analysis.csv", source, "text/csv"))
    skill = client.skills.create(files=[
        Upload("analysis/SKILL.md", b"---\nname: analysis\ndescription: Analyze data\n---\n"),
    ])
    # Download the immutable upload using the same Workspace credential.
    with client.files.download(uploaded["id"]) as stream:
        for chunk in stream.iter_bytes():
            consume(chunk)  # Your application owns the destination.
    try:
        client.sessions.retrieve("sesn_missing")
    except APIError as error:
        print(error.status_code, error.type, error.request_id)

The caller owns file handles. Multipart uploads stream file contents through HTTPX; async multipart file reads use ordinary blocking file handles. For unusually slow sources, prepare local files outside the event loop first.

No HTTP request is automatically retried. An interrupted mutation may already have committed. For example, correlate a tool-result action against persisted events before resubmitting. Redirects are never followed, protecting bearer credentials and avoiding mutation replay. Network failures remain normal HTTPX exceptions; HTTP failures use APIError, while invalid JSON/SSE and broken cursor progression use ResponseDecodeError and PaginationError respectively.

Development checks

uv sync --frozen
uv run python generate.py --check
uv run pytest
uv run mypy
uv run ruff check src tests generate.py examples

generate.py consumes ../openapi.json and ../operations.json. Regenerate the shared snapshot first with go run ./scripts/sdk-contract from the repository root, then run uv run python generate.py. Generated bindings are reproducible; the handwritten HTTP transport is not generated from any vendor implementation. Tests are offline and deterministic. The optional tests/conformance.py targets Mango's own local HTTP-handler harness, not a live model or CMA service.

Metadata

Release files for mango-sdk 0.1.0a3

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

Source distribution (sdist)

Source distribution for mango-sdk 0.1.0a3
File Size Uploaded
mango_sdk-0.1.0a3.tar.gz 36.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mango-sdk 0.1.0a3
File Interpreter ABI Platform
mango_sdk-0.1.0a3-py3-none-any.whl Python 3 none any Details

Total release size: 76.0 kB

Release files / mango_sdk-0.1.0a3.tar.gz

Download URL mango_sdk-0.1.0a3.tar.gz
Size 36.7 kB
Tags Source
SHA-256 checksum
How to use checksums
181313bdabb8defce25e7dbd1fd6fc9fda97496f0d9ea5564bfba256e3cd0718
BLAKE2b-256 checksum
How to use checksums
89caa428507b1aa2c11e0c1af6959babc4fbc1c7e62a1b5ffc4a167ff87dc485
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 17, 2026.

Transparency log

Release files / mango_sdk-0.1.0a3-py3-none-any.whl

Download URL mango_sdk-0.1.0a3-py3-none-any.whl
Size 39.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e32e424015497c65bf88061be417a0cdd748bca4b3ee562c7bc9ce313924267a
BLAKE2b-256 checksum
How to use checksums
8ed5504399fa8b7df746c5c68ca713ad17a7f5b1266b474bd2b59b0a15e44582
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 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0a3 This release

2 release files

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