Skip to main content

prismal-sdk

Typed Python client for prismal-server — the reference host for the prismal agent engine. prismal-sdk speaks only the wire contract the host already fixed (REST + SSE chat, AG-UI, WebSocket, usage/budget reads, standard A2A v0.3 and v1.0 JSON-RPC): it is a thin, business-logic-free client, not a second copy of the engine.

Status

v0.3.0 — targets prismal-server 0.3. On top of v0.1 (threads, SSE chat, A2A v0.3), it adds per-turn usage and the usage/budget reads, AG-UI 1.0 streaming and interrupt resume (run_agui), WebSocket sessions with cancellation, A2A v1.0 (negotiation, ListTasks) and the admin reports. Unit-tested offline against the documented wire contract (≈ 640 tests, 98% branch coverage), and the contract suite runs in CI on every pull request against prismal-server from PyPI in fake-LLM mode. See CHANGELOG.md.

pip install prismal-ai-sdk     # or: pip install 'prismal-ai-sdk[ws]' for client.ws()

SDDs: v0.3 in specs/client-v0.3-agui-resume/ (SPEC · TASKS); v0.2 in specs/client-v0.2-usage-agui/ (PLAN · ARCHITECTURE · SPEC · TASKS); v0.1 in specs/client-sdk-bootstrap/.

Why this exists

prismal is a pure agent engine (no server). prismal-server puts it on the network and fixed a wire contract specifically so a client could be built against it independently (prismal-server/specs/reference-host-bootstrap/SPEC.md §9, "SDK wire contract"). prismal-sdk is that client — and the last piece blocking every front-end repo in the prismal-ai organization (prismal-tui, prismal-dashboard, prismal-webchat, prismal-chatbot), none of which can start until there is a typed, tested way to create a thread, stream a chat turn, and talk A2A over HTTP.

Install

uv add prismal-ai-sdk       # once published
uv add 'prismal-ai-sdk[ws]'    # + the WebSocket client (adds `websockets`)
# or, from a clone:
uv pip install -e ".[dev]"

The base install depends on httpx and pydantic only; websockets comes with the [ws] extra and is imported only when you open a WebSocket session.

Requires Python 3.10+ — deliberately wider than the engine's >=3.13 floor, because the SDK has zero import-time dependency on prismal or prismal_server (see ARCHITECTURE.md ADR-003/004).

Quickstart

from prismal_sdk import PrismalClient

with PrismalClient("http://localhost:8000") as client:
    print(client.healthz())                       # HealthStatus(status='ok')

    thread = client.create_thread()
    for event in client.send_message(thread.thread_id, "Hello, prismal!"):
        print(type(event).__name__, event)

Async:

import asyncio
from prismal_sdk import AsyncPrismalClient

async def main():
    async with AsyncPrismalClient("http://localhost:8000") as client:
        thread = await client.create_thread()
        async for event in client.send_message(thread.thread_id, "Hello!"):
            print(event)

asyncio.run(main())

A2A:

with PrismalClient("http://localhost:8000") as client:
    card = client.agent_card()
    result = client.a2a.message_send({"message": {"role": "user", "parts": [{"text": "Hi"}]}})

Usage, AG-UI and WebSocket (v0.2):

with PrismalClient("http://localhost:8000") as client:
    thread = client.create_thread()
    for event in client.send_message(thread.thread_id, "Hola"):
        if isinstance(event, DoneEvent) and event.usage:
            print(event.usage.total_tokens, event.usage.cost_usd)

    for event in client.send_message(thread.thread_id, "Hola", protocol="ag-ui"):
        print(event.type)                         # RUN_STARTED … RUN_FINISHED

    print(client.budget().status)                 # within / soft_exceeded / …

    with client.ws(thread.thread_id) as session:  # needs prismal-ai-sdk[ws]
        for event in session.send_message("¿Seguimos?"):
            ...

AG-UI interrupt resume (v0.3, host ≥ 0.3):

with PrismalClient("http://localhost:8000") as client:
    thread_id = client.create_thread().thread_id
    events = list(client.run_agui(thread_id, "Deploy the release"))
    finished = events[-1]                         # RunFinished
    if finished.is_interrupted:
        answers = [i.resolve({"action": "approve"}) for i in finished.interrupts]
        events = list(client.run_agui(thread_id, resume=answers))

More in examples/: quickstart.py, streaming_chat.py, a2a_agent_card.py, usage_and_budget.py, agui_stream.py, agui_resume.py, websocket_chat.py, a2a_v1_tasks.py, admin_reports.py.

What's in the box

Capability Sync Async
Health / readiness PrismalClient.healthz() / .readyz() AsyncPrismalClient.healthz() / .readyz()
Threads & chat streaming .create_thread() / .send_message() same, async/await + async for
A2A (Agent Card + JSON-RPC) .agent_card() / .a2a.send() / .a2a.stream() same
Per-turn usage (v0.2) DoneEvent.usage / PrismalUsageEvent same
Usage & budget reads (v0.2) .usage() / .iter_usage_turns() / .budget() same
AG-UI 1.0 streaming (v0.2) .send_message(..., protocol="ag-ui") same
AG-UI run input & interrupt resume (v0.3) .run_agui(thread_id, content) / .run_agui(thread_id, resume=[...]) same, async for
WebSocket sessions (v0.2, [ws]) .ws(thread_id) → send_message / cancel same, async with
A2A v1.0 (v0.2) a2a_protocol= · .a2a.negotiated_version() · .a2a.tasks_list() same
Admin reads (v0.2) .decisions_report() / .routing_report() / .audit() / .tenants() same
Typed exceptions PrismalAPIError hierarchy + PrismalWebSocketError + A2AJsonRpcError shared with sync
Auth Authorization: Bearer + optional X-Org-Id shared with sync
Retry/backoff bounded, transient network errors only shared with sync

See docs/ for the details: streaming · agui · websocket · usage · a2a-v1 · admin · auth · errors.

Development

uv pip install -e ".[dev]"
uv run pytest                      # unit suite (no network)
uv run pytest -m contract          # opt-in: against a running prismal-server
uv run ruff check . && uv run ruff format --check .
uv run mypy src

The unit suite runs fully offline against httpx.MockTransport fakes and an in-process WebSocket server; the contract suite (deselected by default) round-trips against a real prismal-server and skips when none answers. The v0.2 and v0.3 parts (tests/contract/test_v0{2,3}_contract.py) need a 0.3 host in fake-LLM mode — deterministic answers, no provider credentials. The published wheel is enough (it needs Python 3.13, so keep it in its own venv):

uv venv --python 3.13 /tmp/host && uv pip install --python /tmp/host/bin/python 'prismal-server>=0.3,<0.4'
PRISMAL_SERVER_HOST_FAKE_LLM_MODE=true PRISMAL_SERVER_HOST_WS_ENABLED=true \
PRISMAL_SERVER_HOST_AGUI_ENABLED=true PRISMAL_AGUI_EVENTS_ENABLED=true \
PRISMAL_SERVER_HOST_ADMIN_ENABLED=true /tmp/host/bin/uvicorn prismal_server.app:app

# here (the WebSocket turn needs the [ws] extra)
PRISMAL_BASE_URL=http://localhost:8000 uv run --extra ws pytest -m contract

Two cases skip by design against a fake-mode host: tasks_list (fake mode composes no inbound A2A handler) and the admin 200 bodies (set PRISMAL_ADMIN_TOKEN to a token holding prismal:admin; without it the suite checks that each admin read raises ForbiddenError).

CI runs the same suite on every pull request (job contract): it installs prismal-server from PyPI and starts it exactly like this. Dispatch the CI workflow with server_version to pin another host version.

Releasing

Releases ship from main (.github/workflows/release.yml). Set the final version in pyproject.toml and src/prismal_sdk/__init__.py, update CHANGELOG.md, and merge develop into main. The workflow publishes to PyPI with trusted publishing when that version is not on PyPI yet, then tags v<version> and creates the GitHub release; a .devN version or an already-published one ends green without uploading.

One-time PyPI setup (maintainer account): add a trusted publisher — a pending publisher until the project exists — at https://pypi.org/manage/account/publishing/ with project prismal-ai-sdk, owner prismal-ai, repository prismal-sdk, workflow release.yml, environment pypi.

The PyPI distribution is prismal-ai-sdk; the repository and the import module stay prismal-sdk / prismal_sdk. PyPI refuses prismal-sdk: its name-collision check treats l and i alike, so it equals the unrelated prismai-sdk.

The contract with the host

This SDK imports nothing from prismal or prismal_server — an AST import-guard test enforces it (tests/unit/test_import_guard.py), and the rule + review checklist live in CLAUDE.md. It is verified against prismal-server's documented wire contract, never against its source:

  • POST /threads → {thread_id}, POST /threads/{id}/messages → SSE (token/tool_call/state/done/error).
  • GET /.well-known/agent-card.json, POST /a2a — standard A2A v0.3.x and v1.0 JSON-RPC/SSE (A2A-Version header).
  • v0.2: GET /v1/usage, GET /v1/budget, GET /v1/admin/*, GET /ws/threads/{id} (WebSocket), and AG-UI on the chat route via Accept: text/event-stream; profile=ag-ui.
  • v0.3: POST /v1/agui (AG-UI RunAgentInput, including resume).
  • Authorization: Bearer (+ optional X-Org-Id) — the only two prismal-specific headers.
  • GET /openapi.json — available for verifying the SDK's hand-written models stay in sync with the host.

License

See LICENSE.

Metadata

Release files for prismal-ai-sdk 0.3.0

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

Source distribution (sdist)

Source distribution for prismal-ai-sdk 0.3.0
File Size Uploaded Provenance Actions
prismal_ai_sdk-0.3.0.tar.gz 39.9 kB Without provenance Details for prismal_ai_sdk-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for prismal-ai-sdk 0.3.0
File Interpreter ABI Platform Actions
prismal_ai_sdk-0.3.0-py3-none-any.whl Python 3 none any Details for prismal_ai_sdk-0.3.0-py3-none-any.whl

Total release size: 91.3 kB

Release files / prismal_ai_sdk-0.3.0.tar.gz

Download URL prismal_ai_sdk-0.3.0.tar.gz
Size 39.9 kB
Tags Source
SHA-256 checksum
How to use checksums
82fdae18f3ba35a40a43875a40242b09fbf60e2e9a4e98a7c618add3e2dbf964
BLAKE2b-256 checksum
How to use checksums
0ceef2680e3810e3dd00a11fcb59f53e94570f0b05c393cda3af209754b871b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / prismal_ai_sdk-0.3.0-py3-none-any.whl

Download URL prismal_ai_sdk-0.3.0-py3-none-any.whl
Size 51.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dceb0dd452d3ddc2c6ef19011af1ea414772611304b45c9ef85fd8f6b6d83d91
BLAKE2b-256 checksum
How to use checksums
949b61d4e66e9d7a523a9ffe974b169c296f56918ddf658a3da1b93728c7e8b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for prismal-ai-sdk 0.3.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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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

0.3.0 This release

2 release files No 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