Skip to main content

Official Python SDK for the Ensoul API

Project description

Ensoul Python SDK

Python client library for the Ensoul personality simulation API.

Installation

Requires Python 3.11 or newer. On Python 3.9 or 3.10, pip install ensoul fails with no compatible version. Check your version with python --version and upgrade if needed.

pip install ensoul

Quick Start

from ensoul import Ensoul

client = Ensoul(api_key="your-api-key")

# Create a persona
persona = client.personas.create(name="Alex", domain="my_domain")

# Send a chat message
response = client.chat.send(persona.id, "Hello, who are you?")
print(response.response)

The API key can also be set via the ENSOUL_API_KEY environment variable, in which case no api_key argument is needed.

The client supports context managers for automatic cleanup:

with Ensoul(api_key="your-api-key") as client:
    persona = client.personas.get("persona-id")

Async Usage

import asyncio
from ensoul import AsyncEnsoul

async def main():
    async with AsyncEnsoul(api_key="your-api-key") as client:
        persona = await client.personas.create(name="Jordan", domain="my_domain")
        response = await client.chat.send(persona.id, "Tell me about yourself.")
        print(response.response)

asyncio.run(main())

Streaming

Chat supports server-sent events (SSE) for streaming responses. Each event's data is a JSON object. The delta text lives in the chunk field:

Field Type Notes
chunk str The text delta. Append these to build the full reply.
conversation_id str Stable across the stream. Pass it back to continue the conversation.
chunk_index int 0-based position of this chunk in the stream.
is_final bool True on the last event. Its chunk is empty ("").
token_usage dict | None Present only on the final event.

Use parse_chat_event to turn each raw SSEEvent into a typed ChatStreamEvent, then print chunk as it arrives:

from ensoul import Ensoul
from ensoul.streaming import parse_chat_event

client = Ensoul(api_key="your-api-key")

stream = client.chat.stream("persona-id", "What do you think about music?")
try:
    for event in stream.events():
        parsed = parse_chat_event(event)
        print(parsed.chunk, end="", flush=True)  # print text as it streams
        if parsed.is_final:
            print()  # newline after the stream completes
            if parsed.token_usage:
                print(f"tokens: {parsed.token_usage}")
finally:
    stream.close()

The async client returns an AsyncSSEStream that works the same way with async for:

import asyncio
from ensoul import AsyncEnsoul
from ensoul.streaming import parse_chat_event

async def main() -> None:
    client = AsyncEnsoul(api_key="your-api-key")
    stream = await client.chat.stream("persona-id", "What do you think about music?")
    async for event in stream:
        parsed = parse_chat_event(event)
        print(parsed.chunk, end="", flush=True)
        if parsed.is_final:
            print()

asyncio.run(main())

Pagination

List endpoints return a SyncPage (or AsyncPage) object. Use .auto_paging_iter() to iterate through all pages automatically:

# Manual page access
page = client.personas.list(per_page=50)
print(page.items)    # current page items
print(page.total)    # total count across all pages

# Automatic pagination — fetches subsequent pages as needed
for persona in client.personas.list().auto_paging_iter():
    print(persona.name)

Async pagination works the same way with async for.

Error Handling

All SDK errors inherit from EnsoulError. HTTP errors are subclasses of APIError:

from ensoul.errors import (
    EnsoulError,
    APIError,
    AuthenticationError,
    AuthorizationError,
    NotFoundError,
    RateLimitError,
    ValidationError,
    ConflictError,
    ServerError,
)

try:
    persona = client.personas.get("nonexistent-id")
except NotFoundError:
    print("Persona not found")
except AuthenticationError:
    print("Invalid or missing API key")
except RateLimitError:
    print("Rate limit exceeded — back off and retry")
except APIError as e:
    print(f"API error {e.status_code}: {e.message}")

Configuration

The client reads two environment variables as defaults:

Variable Purpose
ENSOUL_API_KEY API key (avoids passing api_key= in code)
ENSOUL_BASE_URL API base URL (default: https://api.ensoul-ai.com)

Demo API — the current hosted demo is available at:

export ENSOUL_BASE_URL="https://api.demo.ensoul-ai.com"
export ENSOUL_API_KEY="your-api-key"

With these set, Ensoul() connects to the demo with no constructor arguments.

You can also pass the base URL explicitly:

client = Ensoul(api_key="ens_...", base_url="https://api.demo.ensoul-ai.com")

Authentication

API key (recommended):

client = Ensoul(api_key="ens_...")
# or set ENSOUL_API_KEY in the environment
client = Ensoul()

Bearer token:

client = Ensoul(bearer_token="eyJ...")

OAuth2 token exchange (password flow, form-encoded):

token_response = client.auth.token(
    username="you@example.com",
    password="your-password",
)
authed_client = Ensoul(bearer_token=token_response.access_token)

Resources

Namespace Description
client.personas CRUD, list (paginated), batch create, personality vectors, filters, connections
client.chat Send messages, streaming SSE, conversation history
client.domains Domain configuration management
client.simulations Time-based evolution simulations
client.aggregate Aggregate queries with streaming results
client.memory Persona memory management
client.sessions Hierarchical session orchestration
client.frameworks Framework management
client.auth OAuth2 token exchange and API key management
client.health Service health checks
client.info Server info and configuration

Requirements

  • Python 3.11+
  • httpx — HTTP transport
  • pydantic 2.x — request and response models

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

ensoul-0.2.3.tar.gz (78.4 kB view details)

Uploaded Source

Built Distribution

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

ensoul-0.2.3-py3-none-any.whl (51.0 kB view details)

Uploaded Python 3

File details

Details for the file ensoul-0.2.3.tar.gz.

File metadata

  • Download URL: ensoul-0.2.3.tar.gz
  • Upload date:
  • Size: 78.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ensoul-0.2.3.tar.gz
Algorithm Hash digest
SHA256 1c3af6b31482e99a3434a75c795b1bce44a1343679a0bf50a73e0e622c6952f3
MD5 95cbf2822aee02c543f4e03624d403d2
BLAKE2b-256 f12315e27edee977cc9ca8d53e33bd22884b0ec071bd3fe6b2a89fa117e8c475

See more details on using hashes here.

Provenance

The following attestation bundles were made for ensoul-0.2.3.tar.gz:

Publisher: sdk-publish.yml on ensoul-ai/ensoul-sdk

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

File details

Details for the file ensoul-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: ensoul-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 51.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ensoul-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 3e87553d26389ced51b2b7860c8a45bcb970869665e440dbca7e3031f2f39fab
MD5 87ee0838bf68a6c1c3ff57eed666026c
BLAKE2b-256 38c856fa782110d858599fdd07d0dda9553a787b3a7611719430c2cfb8b2bc15

See more details on using hashes here.

Provenance

The following attestation bundles were made for ensoul-0.2.3-py3-none-any.whl:

Publisher: sdk-publish.yml on ensoul-ai/ensoul-sdk

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