Metadata-Version: 2.5
Name: elektric-ai
Version: 0.1.0
Summary: Native Python client for Elektric's automatically routed inference API
Project-URL: Repository, https://github.com/realVasileios/electric
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Requires-Dist: websockets<16,>=13
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Description-Content-Type: text/markdown

# Elektric Python SDK

Canonical documentation: [Quickstart](../../docs/getting-started.md) · [AI coding agents](../../docs/guides/ai-coding-agents.md) · [llms.txt](../../public/llms.txt)

One provider-neutral Python interface for chat, media, Web, tools, state, jobs, and realtime.

The distribution is `elektric-ai`; the Python import remains `elektric`.

This is the official `elektric-ai` distribution. Do not substitute a similarly named distribution.

## Install and configure

```bash
python -m pip install elektric-ai
```

```python
from elektric import Elektric

with Elektric() as client:
    response = client.chat(
        message="Explain quantum computing simply.",
        user_id="user-123",
        conversation_id="thread-123",
    )
    print(response.message, response.request_id)
```

The production URL is built in; `base_url` is only needed for local or staged deployments. Native chat requires customer-defined `user_id` and `conversation_id`; the `elektric-auto` model is implicit. No provider key, provider name, or model is accepted. AI executions are never automatically retried.

## Conversations

```python
conversation = client.conversations.get(conversation_id="thread-123")
recent = client.conversations.list(user_id="user-123", limit=20)
client.conversations.delete(conversation_id="thread-123")
```

GET messages are chronological and cursor-paginated with `message_cursor` (default/max 100). LIST is newest-updated-first with opaque cursors (default 20, max 100). Deleting a Conversation does not delete Memory, Knowledge, or other Conversations; a later chat may recreate a fresh thread with the same external ID.

## Memory management

Memory is durable user-specific information across Conversations and remains automatic during chat.

```python
memories = client.memory.list(user_id="user-123")
card = client.memory.get(user_id="user-123", memory_id=memories.data[0].id)
client.memory.update(user_id="user-123", memory_id=card.id, summary="User prefers concise prose.")
client.memory.delete(user_id="user-123", memory_id=card.id)
```

Manual create is deferred; the certified updater owns stable conceptual keys and the 30-card/1,000-token profile limits. Delete deactivates active Memory immediately but does not erase source Conversations or History.

## Async and streaming

```python
from elektric import AsyncElektric

async with AsyncElektric() as client:
    response = await client.chat(message="Hello", user_id="user-123", conversation_id="async-123")
    async for event in client.chat_stream(
        message="Count to three", user_id="user-123", conversation_id="async-stream"
    ):
        if event.type == "content_delta":
            print(event.text, end="")
```

Sync streaming is the same iterator pattern without `async`. Closing a local stream or wait does not imply remote cancellation.

## Web and tools

Set `web=True` and read `response.sources`. Tools use Elektric dictionaries with `name`, `description`, and `input_schema`; calls expose `id`, `name`, and parsed `arguments`. Execute them locally, then send the original user message followed by `{"role": "tool", "tool_call_id": call["id"], "content": result}`.

## Files, embeddings, and media

Use `files.upload/get/delete`, `assets.get/download/delete`, `embeddings.create`, and the discoverable `embedding_profiles` alias. Media methods are `audio.transcribe/speech`, `images.generate/edit`, `video.analyze/generate`, and `jobs.get/wait/cancel`. Video generation returns an `ElektricJob`; stopping a local wait never cancels it.

## Realtime

Realtime is intentionally async-only in Python:

```python
async with await client.realtime.connect(input=["text"], output=["text"]) as session:
    await session.send_text("Hello")
    async for event in session:
        print(event.type, event.data)
```

Sessions also provide `send_audio`, `commit_audio`, `interrupt`, and `close`.

## Errors and support

Catch `ElektricError` and inspect `type`, `code`, `status_code`, `request_id`, and safe `details`. Canonical subclasses include authentication, invalid-request, rate-limit, timeout, and service errors. Legacy billing, bad-request, and server subclasses remain compatible. Provider errors and secrets are never exposed or logged.

Python 3.10–3.12 metadata is supported. Both clients are context managers and should be closed. See [Elektric documentation](https://elektric.ai/docs). The native SDK is recommended for the full platform; OpenAI compatibility is for quick migration of existing code.

## Streaming Web sources

Pass `web=True` to synchronous or asynchronous `chat_stream`. A `StreamEvent(type="source")` carries an `ElektricSource`; source events may arrive before, during, or after content deltas and are de-duplicated by URL. The server sends finish before `[DONE]`.

## Knowledge management

Knowledge is project-level reference material used automatically when relevant. `client.knowledge.add(file)` accepts a path, bytes, or open binary file. Use `list`, `get`, and `delete`, and poll until `status == "ready"`. Retry is deferred: delete and re-upload failed sources.
