Skip to main content
Pre-release

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

HaltState SDK

PyPI

Action control and Proof Packs for autonomous AI agents. Perform pre-action checks, approvals, and post-action reporting with minimal code.

Semiotic Probe (source candidate, not activated)

probe = client.connect_semiotic_probe("openai", "gpt-4.1", lambda raw, limit: isolated_model(raw, max_tokens=limit))
# Or use probe.poll_once() and probe.close() in an application-owned lifecycle.

The hook must be fresh and isolated: no history, memory, retrieval, tools, or side effects.

Canonical public base URL: https://haltstate.ai

Canonical governance namespace: /api/haltstate/sentinel/*

Current SDKs default to https://haltstate.ai. Guard endpoints use the branded /api/haltstate/sentinel/* namespace when available. The released check(), report(), and approval-polling paths still use supported legacy /api/sentinel/* compatibility aliases until matching branded backend routes are registered.

Replay safety status

Replay-ledger hardening is implemented and locally verified in this source tree. Production activation remains pending the caller-first quiesce/drain window, migration 106, matching API/SDK deployment with no mixed workers, and the delayed/replay route smokes; this is not a production-live claim.

On the hardened path, each tenant and idempotency key binds to one exact operation: agent, action, resource, normalized parameters, and risk class. The stored decision carries the evaluated policy version; a retry with changed operation data is rejected. Approvals expire, and an eligible operation receives at most one permit. Exact outcome-report retries receive the original receipt.

The durable lifecycle is recorded in an append-only, hash-chained event log. That log is not externally anchored or immune to a database superuser. Destination idempotency remains the customer's responsibility: HaltState cannot guarantee exactly-once execution inside an external payment, email, or infrastructure system. Hosted LLM inference is likewise not claimed to be bit-for-bit deterministic.

Post-cutover idempotency epoch

During the controlled replay-ledger cutover, configure the UUID epoch issued for that activation:

client = HaltStateClient(
    tenant_id="acme",
    api_key="hs_xxx",
    idempotency_epoch="11111111-2222-4333-8444-555555555555",
)

After configuration, guard() calls that omit idempotency_key generate a qualified key in the form hsr1:<epoch>:<uuid>. The SDK never prefixes, rewrites, or upgrades an explicit caller-supplied key. Consequently, explicit keys sent after cutover must already be fully qualified for the active epoch. Keep idempotency_epoch unset only for preactivation compatibility, where omitted keys retain the legacy plain-UUID behavior. Keep this HaltState guard key separate from the destination's stable business idempotency key; the destination key must not rotate with the guard epoch.

Configure the epoch only after guarded callers and schedulers are quiesced, guard ingress is closed, legacy API workers are stopped, and old work is drained or reconciled. Reopen with no mixed workers. Once epoch-qualified work is admitted, do not roll back to a pre-replay binary under open ingress; remain fail closed and roll forward.

Installation

PyPI currently serves 0.7.0. The replay-safe contract in this tree is the unpublished 0.8.0.dev0 candidate and must be installed from the reviewed source checkout until it is released.

# Published baseline:
pip install haltstate-sdk

# Replay-safe source candidate, from the repository root:
pip install ./packages/haltstate-sdk

Quickstart (sync)

from haltstate import HaltStateClient

client = HaltStateClient(
    tenant_id="your_tenant_id",
    api_key="hs_xyz",
    base_url="https://haltstate.ai",
    fail_open=False,
)

decision = client.check(
    action="payment.process",
    params={"amount": 5000, "currency": "USD"},
    agent_id="payment-bot-01",
)

if decision.allowed:
    process_payment(...)
    client.report(decision, status="success", result={"transaction_id": "tx_123"}, action="payment.process", agent_id="payment-bot-01")
elif decision.requires_approval:
    print(f"Approval required: {decision.reason}")
else:
    print(f"Action denied: {decision.reason}")

Guard Pattern

For actions requiring human approval, use the idempotent guard pattern:

from haltstate import HaltStateClient, ApprovalPending, ActionDenied

def process_high_value_payment(invoice_id: str, amount: float):
    operator_epoch = "11111111-2222-4333-8444-555555555555"
    destination_key = f"payment-{invoice_id}"
    guard_key = f"hsr1:{operator_epoch}:{destination_key}"
    report_id = "40000000-0000-4000-8000-000000000501"
    client = HaltStateClient(
        tenant_id="acme",
        api_key="hs_xxx",
        base_url="https://haltstate.ai",
    )

    try:
        with client.guard(
            action="payment.process",
            agent_id="payment-bot",
            params={"invoice_id": invoice_id, "amount": amount},
            idempotency_key=guard_key,
            resource=f"invoice/{invoice_id}",
            risk_class="high",
            report_id=report_id,
        ) as permit:
            permit.validate_for_execution()
            result = execute_payment_once(
                invoice_id=invoice_id,
                amount=amount,
                idempotency_key=destination_key,
            )
            print(f"Approved by {permit.approver} at {permit.approved_at}")
            return result

    except ApprovalPending:
        print("Awaiting human approval...")
        return {"status": "pending"}

    except ActionDenied as e:
        print(f"Denied: {e.reason}")
        raise

Key features:

  • Exact operation binding: The same key and same proposal replay the stored decision; changed agent, action, resource, risk, or parameters conflict.
  • Expiring approval authority: Approvals expire, and the SDK refuses an expired executable response before entering the action.
  • One-permit rule: A retry after permit issuance receives an ActionAlreadyStarted error, not replacement authority. A lost permit or missing outcome report requires destination reconciliation.
  • Durable outcome reporting: Exact report retries reuse their receipt; exhausted reporting retries raise OutcomeReportError.
  • Replay evidence: Policy-versioned decision, approval, permit, and outcome events form an append-only hash chain.

Retries while an approval is still pending can safely poll the same exact operation. A restart after permit issuance must not blindly execute the action again; reconcile against an idempotent destination first.

Persist the permit, report_id, outcome, and exact payload before an outcome retry. If the context manager raises OutcomeReportError after the side effect returns, resume only the receipt call:

receipt = client.report_guard_outcome(
    permit,
    report_id=report_id,
    outcome="success",
    result={"destination_key": destination_key},
)

Do not rerun the payment to obtain that receipt. Error outcomes use the same public method with outcome="error" and the same caller-stable UUID.

Decorators

from haltstate import HaltStateClient, haltstate_guard

client = HaltStateClient(tenant_id="acme", api_key="hs_xxx", base_url="https://haltstate.ai")

@haltstate_guard(client, action="email.send", agent_id="email-bot")
def send_email(to, subject, body):
    return mailer.send(to, subject, body)

Async

from haltstate import AsyncHaltStateClient

async def main():
    async with AsyncHaltStateClient(tenant_id="acme", api_key="hs_xxx", base_url="https://haltstate.ai") as client:
        res = await client.check("database.drop", params={"table": "users"})
        if res.allowed:
            await client.report(res, status="success", action="database.drop", agent_id="ops-bot")

Exceptions

from haltstate import (
    HaltStateError,           # Base error
    HaltStateAuthError,       # Invalid API key
    HaltStateConnectionError, # Network/timeout
    ApprovalPending,          # Awaiting approval (guard pattern)
    ActionDenied,             # Human rejected (guard pattern)
    ActionExpired,            # Approval expired (guard pattern)
    ActionAlreadyStarted,     # Permit already issued; never rerun the action
    OutcomeReportError,       # Durable outcome receipt was not confirmed
)

Docs

Full documentation at haltstate.ai/docs:

  • Quickstart - 5-minute setup
  • Guard Pattern - HITL approval flow
  • API Reference - All methods
  • Error Handling - Exception handling
  • Governance alignment - Operational evidence mapping

Legacy route aliases remain supported for existing installations, but new integrations should target the HaltState-branded public contract.

Legacy migration note

If upgrading from the legacy package/import namespace:

Existing code using the legacy import namespace continues to work, but new integrations should use from haltstate import ....

# Legacy (still works)
from janus import JanusClient, janus_guard

# New
from haltstate import HaltStateClient, haltstate_guard

Both import styles work - no code changes required for existing users.

License

MIT

Metadata

Release files for haltstate-sdk 0.8.0.dev1

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

Source distribution (sdist)

Source distribution for haltstate-sdk 0.8.0.dev1
File Size Uploaded
haltstate_sdk-0.8.0.dev1.tar.gz 46.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for haltstate-sdk 0.8.0.dev1
File Interpreter ABI Platform
haltstate_sdk-0.8.0.dev1-py3-none-any.whl Python 3 none any Details

Total release size: 83.0 kB

Release files / haltstate_sdk-0.8.0.dev1.tar.gz

Download URL haltstate_sdk-0.8.0.dev1.tar.gz
Size 46.2 kB
Tags Source
SHA-256 checksum
How to use checksums
7d1be4ee1168099689ea61ffe858bf514b5e1f2b8b94193a9a4d65e5a321f0f2
BLAKE2b-256 checksum
How to use checksums
48e49aa783b02f8dac1e868706e51057d8bf864dba17aa8311444a0f661d6488
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release files / haltstate_sdk-0.8.0.dev1-py3-none-any.whl

Download URL haltstate_sdk-0.8.0.dev1-py3-none-any.whl
Size 36.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
99958165bae215b3cb98ad3e223cc8a11f2318943db08bdd6232823fe96c9b85
BLAKE2b-256 checksum
How to use checksums
043d0e1dcda9b25f4e98255ed5d07d7ac58d3239dfa223e15ee49423aa1fd244
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

0.8.0.dev1 This release

2 release files

0.7.0

2 release files

0.6.0

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