Skip to main content

Official Python client for the LEO Soul hosted API (metacognitive layer for LLM agents).

Project description

LEO Soul — Python client

Official, zero-dependency Python client for the LEO Soul hosted API — the stateless metacognitive layer for LLM agents.

pip install leo-soul-client

Quickstart

from leo_soul_client import LeoSoul

soul = LeoSoul(api_key="sk_live_...")             # from your dashboard

result = soul.turn(
    messages=[{"role": "user", "content": "Delete all my production data now."}],
    backend="openai",
    backend_kwargs={"api_key": "sk-...", "model": "your-model"},  # your model + key
)

print(result.action)      # answer | asked | confirmed | held | refused | escalated
print(result.reply)       # the processed reply to send to your user
store(result.soul_state)  # persist this; pass it back next turn — that's the learning

The one rule: round-trip soul_state

state = None
for user_msg in conversation:
    result = soul.turn(messages=[*history, user_msg], soul_state=state, backend="openai",
                       backend_kwargs={"api_key": OPENAI_KEY, "model": "your-model"})
    state = result.soul_state   # store it (a few KB of JSON) and send it back next turn

We keep none of it — soul_state is your agent's memory and it lives on your side.

Features

  • Zero dependencies — pure standard library. No native build, installs anywhere.
  • Exactly-once retries — automatic retries on 429/5xx reuse a single Idempotency-Key, so a retried turn is never double-metered.
  • Typed resultsresult.reply, .soul_state, .trace, .action, .rate_limit (limit/remaining/reset), .request_id.
  • Clear errorsAuthError (401/403), QuotaExceeded (402), RateLimitError (429, with .retry_after), UpstreamProviderError (502 — your model provider failed, with .kind and .retryable), LeoSoulError (everything else), each carrying .status, .type, and .request_id.
  • An explicit failure policyon_unavailable decides what happens if LEO Soul is ever unreachable. See below; it defaults to failing closed.

Self-hosted / on-prem

Point the client at your own deployment:

soul = LeoSoul(api_key="sk_live_...", base_url="https://soul.your-company.internal")

Personas

result = soul.turn(
    messages=msgs,
    persona={
        "identity": "a careful financial-support assistant",
        "values": ["truthfulness over agreeableness"],
        "red_lines": ["never give individualized investment advice"],
    },
    backend="openai",
    backend_kwargs={"api_key": OPENAI_KEY, "model": "your-model"},
)

Or reference a saved persona from your dashboard with persona_id=....

Error handling

from leo_soul_client import (
    RateLimitError, QuotaExceeded, AuthError, UpstreamProviderError, LeoSoulError,
)

try:
    result = soul.turn(messages=msgs, backend="mock")
except QuotaExceeded as e:
    ...  # upgrade the plan; e.request_id for support
except RateLimitError as e:
    time.sleep(e.retry_after)
except AuthError:
    ...  # bad key / IP not allowlisted
except UpstreamProviderError as e:
    # YOUR model provider failed, not LEO Soul. e.kind is auth / rate_limit /
    # timeout / connection / server_error / bad_request.
    if e.retryable:
        retry_later()
    else:
        alert(f"fix your provider config: {e}")

What happens when LEO Soul is unreachable

This client sits in your request path, so an outage of ours is a decision your product has to make — not one we should make silently for you.

# The default. Raises, so nothing unchecked reaches a user.
soul = LeoSoul(api_key="sk_live_...")           # on_unavailable="fail_closed"

# Availability over scrutiny: call your provider directly and flag the result.
soul = LeoSoul(
    api_key="sk_live_...",
    on_unavailable="fail_open",
    on_degraded=lambda reason, err: pager.warn(reason),   # wire to your alerting
)

result = soul.turn(messages=msgs, backend="openai", backend_kwargs=kw)
if result.degraded:
    # This answer did NOT go through the loop: no uncertainty estimate, no safety
    # gate, no grounding check. Label it, or hold it.
    ...

Why fail-closed is the default. A guardrail that quietly disappears is worse than one that visibly fails: you keep shipping answers believing they were checked.

fail_open covers availability failures only — a network error, or a 5xx from us. It deliberately does not cover 402 (quota: a billing state, not an outage), 401/403 (config errors it would hide), 429 (self-healing, has Retry-After), or 502 (your provider is the broken thing, so calling it directly fails too).

With no fallback= supplied it calls your provider over the OpenAI chat-completions shape — OpenAI, Azure OpenAI, Groq, Together, Fireworks, OpenRouter, vLLM, Ollama. For anything else, pass your own fallback(messages, backend, backend_kwargs) -> str. If neither can run you get FallbackUnavailable rather than silence.

Full guide: https://soul.kadropiclabs.com/documentation#resilience


© Kadropic Labs. Part of Project LEO.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

leo_soul_client-0.2.0.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

leo_soul_client-0.2.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file leo_soul_client-0.2.0.tar.gz.

File metadata

  • Download URL: leo_soul_client-0.2.0.tar.gz
  • Upload date:
  • Size: 12.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for leo_soul_client-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d887a50786f98671b9da5ac0598cb9246bbc23fe693d548bac1af76b24989d20
MD5 4b16c05e91d05cd0b93a2fb83b6ee51e
BLAKE2b-256 8bb9e5d47ab85245e881b4eb5c4e82fe56fdbbd1dcbe160140a635589b01f719

See more details on using hashes here.

Provenance

The following attestation bundles were made for leo_soul_client-0.2.0.tar.gz:

Publisher: publish-sdk.yml on Kadropic-Labs/Soul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leo_soul_client-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: leo_soul_client-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for leo_soul_client-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7d9716871c9f06dc2fc0ca6741e5e697ac7b325eceb7520363655d1e45db006e
MD5 cd2c082fd54e95710673be576044a660
BLAKE2b-256 59501664af2564b5cb017621a7d0c0e0d7933c2a901f844347a05a4f89b89167

See more details on using hashes here.

Provenance

The following attestation bundles were made for leo_soul_client-0.2.0-py3-none-any.whl:

Publisher: publish-sdk.yml on Kadropic-Labs/Soul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page