Metadata-Version: 2.2
Name: swfte-sdk
Version: 1.2.0
Summary: Official Python SDK for Swfte — unified API for 200+ AI models, agents, workflows, chatflows, RAG, voice and MCP. https://www.swfte.com
Author-email: "Swfte, Inc." <sdk@swfte.com>
License: MIT License
        
        Copyright (c) 2025 Swfte, Inc.
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://www.swfte.com
Project-URL: Documentation, https://www.swfte.com/developers
Project-URL: Repository, https://github.com/SwfteAI/swfte-python
Project-URL: Changelog, https://github.com/SwfteAI/swfte-python/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/SwfteAI/swfte-python/issues
Project-URL: Pricing, https://www.swfte.com/pricing
Project-URL: Security, https://www.swfte.com/security
Keywords: ai,llm,openai,anthropic,gemini,sdk,api
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.32.4
Requires-Dist: urllib3>=2.8.0
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pytest-httpx>=0.21.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=7.0.0; extra == "docs"
Requires-Dist: furo>=2024.0.0; extra == "docs"
Requires-Dist: sphinx-copybutton>=0.5.0; extra == "docs"
Requires-Dist: sphinx-autodoc-typehints>=1.24.0; extra == "docs"
Requires-Dist: myst-parser>=2.0.0; extra == "docs"

# Swfte Python SDK

[![PyPI version](https://img.shields.io/pypi/v/swfte-sdk.svg)](https://pypi.org/project/swfte-sdk/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)

The official Python SDK for [**Swfte**](https://www.swfte.com) — the unified AI infrastructure platform giving teams one API for **200+ models** from OpenAI, Anthropic, Google, Mistral, Meta and self-hosted GPU deployments, plus production-grade [agents](https://www.swfte.com/products/agents), [workflows](https://www.swfte.com/products/workflows), [chatflows](https://www.swfte.com/products/chatflows), [RAG](https://www.swfte.com/products/rag), [voice](https://www.swfte.com/products/voice), and [MCP servers](https://www.swfte.com/products/mcp).

## About Swfte

[**Swfte**](https://www.swfte.com) is the unified AI infrastructure platform — one API for **200+ models** from OpenAI, Anthropic, Google, Mistral, Meta and self-hosted GPU deployments, plus production-grade [agents](https://www.swfte.com/products/agents), [workflows](https://www.swfte.com/products/workflows), [chatflows](https://www.swfte.com/products/chatflows), [RAG](https://www.swfte.com/products/rag), [voice](https://www.swfte.com/products/voice), and [MCP servers](https://www.swfte.com/products/mcp).

Read the full company profile in [ABOUT.md](ABOUT.md), or visit [swfte.com](https://www.swfte.com) to get started for free.

| Resource | Link |
|---|---|
| Product home | [https://www.swfte.com](https://www.swfte.com) |
| Documentation | [swfte.com/resources](https://www.swfte.com/resources) |
| API reference | [swfte.com/developers](https://www.swfte.com/developers) |
| Pricing | [swfte.com/pricing](https://www.swfte.com/pricing) |
| Security | [swfte.com/security](https://www.swfte.com/security) |
| Status | [status.swfte.com](https://status.swfte.com) |
| GitHub org | [github.com/SwfteAI](https://github.com/SwfteAI) |

### Other official Swfte SDKs

- [swfte-python](https://github.com/SwfteAI/swfte-python) — Python SDK ([PyPI](https://pypi.org/project/swfte-sdk/))
- [swfte-node](https://github.com/SwfteAI/swfte-node) — Node.js / TypeScript SDK ([npm](https://www.npmjs.com/package/@swfte/sdk))
- [swfte-java](https://github.com/SwfteAI/swfte-java) — Java SDK ([Maven Central](https://search.maven.org/artifact/com.swfte/swfte-sdk))
- [swfte-chat-widget](https://github.com/SwfteAI/swfte-chat-widget) — embeddable chat widget ([npm](https://www.npmjs.com/package/@swfte/chat-widget))
- [swfte-chatflow-widget](https://github.com/SwfteAI/swfte-chatflow-widget) — embeddable conversational form widget ([npm](https://www.npmjs.com/package/@swfte/chatflow-widget))

## Documentation

Full API reference and guides are available at [swfte.com/developers](https://www.swfte.com/developers). Runnable Python recipes for the top-15 V2 controllers live in [`docs/cookbook/`](docs/cookbook/).

## Installation

```bash
pip install swfte-sdk   # the package is swfte-sdk; you import it as `swfte`
```

## Quick Start

```python
from swfte import SwfteClient

client = SwfteClient(api_key="sk-swfte-...")

response = client.chat.completions.create(
    model="openai:gpt-4",
    messages=[{"role": "user", "content": "Hello, world!"}],
)

print(response["choices"][0]["message"]["content"])
```

## Usage

### Chat Completions

```python
response = client.chat.completions.create(
    model="anthropic:claude-3-opus",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain quantum computing in one sentence."},
    ],
    temperature=0.7,
    max_tokens=256,
)
```

### Streaming

```python
stream = client.chat.completions.create(
    model="openai:gpt-4",
    messages=[{"role": "user", "content": "Write a short poem."}],
    stream=True,
)

for chunk in stream:
    content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "")
    print(content, end="", flush=True)
```

### Agents

```python
# Create an agent
agent = client.agents.create(
    name="Research Assistant",
    system_prompt="You are a research assistant specializing in AI.",
    provider="OPENAI",
    model="gpt-4",
)

# List agents
agents = client.agents.list()

# Update an agent
client.agents.update(agent.id, description="Updated description")

# Chat with an agent: POST /v1/agents/{id}/chat/{user_id}, reply text in .response
reply = client.agents.chat(agent.id, "What changed in Q3?", user_id="user-42")
print(reply.response)

# Continue the same conversation (user_id defaults to "sdk-user" when omitted)
follow_up = client.agents.chat(
    agent.id, "And Q4?", user_id="user-42", conversation_id=reply.conversation_id
)

# Delete an agent
client.agents.delete(agent.id)
```

### Workflows

```python
# Create a workflow
workflow = client.workflows.create(
    name="Content Pipeline",
    nodes=[
        {"id": "start", "type": "TRIGGER", "config": {"triggerType": "MANUAL"}},
        {"id": "llm", "type": "LLM", "config": {"model": "gpt-4", "prompt": "Summarize: {{input}}"}},
        {"id": "end", "type": "END", "config": {}},
    ],
    edges=[
        {"id": "e1", "source": "start", "target": "llm"},
        {"id": "e2", "source": "llm", "target": "end"},
    ],
)

# Production: run the PUBLISHED version (POST /v2/workflows/{id}/invoke, 202 + executionId)
invocation = client.workflows.invoke(workflow.id, {"input": "Hello"})
status = client.workflows.get_execution_status(invocation.execution_id)
print(status.status_raw, status.progress)

# ...or invoke and poll until the run finishes (timeout/poll_interval in seconds)
from swfte import WorkflowExecutionError, WorkflowTimeoutError

try:
    done = client.workflows.invoke_and_wait(
        workflow.id, {"input": "Hello"}, timeout=120, poll_interval=2
    )
    print(done.status_raw, done.outputs)  # SUCCESS / SUCCEEDED / COMPLETED
except WorkflowExecutionError as err:     # FAILED, TIMEOUT, CANCELLED/CANCELED
    print("run ended", err.status, err)
except WorkflowTimeoutError as err:       # gave up polling; the run continues
    print("still running", err.execution_id)

# Test run of the current (unpublished) definition — Studio's draft path
execution = client.workflows.execute(workflow.id, {"input": "Hello", "testingFlag": True})
```

`invoke()` runs the published snapshot and is what production callers should
use; unpublished edits do not affect it, and a never-published workflow answers
409. `execute()` runs the editable definition (the draft) and exists for test
runs. Neither is retried by the SDK, so a network blip never starts a run twice.

### Catalog

```python
# Find proven artifacts across kinds
page = client.catalog.search(
    q="invoice triage",
    kinds=["workflow", "agent"],
    scope="all",
    min_evidence="corroborated",
    limit=10,
)
for item in page["items"]:
    print(item["catalogRef"], item["evidence"]["level"])

# Evidence, reviews and dependencies for one entry
detail = client.catalog.get("workflow", page["items"][0]["id"])

# How to call it: method, path, input/output JSON Schema and code snippets
contract = client.catalog.contract("workflow", page["items"][0]["id"])
print(contract["invoke"]["method"], contract["invoke"]["path"])
```

### GPU Model Deployments

```python
# Deploy a model to GPU infrastructure
deployment = client.deployments.create(
    model_name="meta-llama/Llama-3.2-8B-Instruct",
    model_type="chat",
)

# Wait for deployment to be ready
ready = client.deployments.wait_for_ready(deployment.id, timeout_ms=600000)
print(f"Endpoint: {ready.endpoint_url}")

# Clean up
client.deployments.delete(deployment.id)
```

### Images

```python
response = client.images.generate(
    model="openai:dall-e-3",
    prompt="A sunset over a mountain range, oil painting style",
    size="1024x1024",
    quality="hd",
)
```

### Embeddings

```python
response = client.embeddings.create(
    model="openai:text-embedding-3-small",
    input="The quick brown fox jumps over the lazy dog",
)
```

### Audio

```python
# Speech to text
transcript = client.audio.transcriptions.create(
    model="openai:whisper-1",
    file=open("recording.mp3", "rb").read(),
)

# Text to speech
audio_bytes = client.audio.speech.create(
    model="openai:tts-1",
    input="Hello, welcome to Swfte.",
    voice="alloy",
)
```

### Secrets

```python
# Store an API key securely
secret = client.secrets.create(
    name="my-api-key",
    secret_type="API_KEY",
    value="sk-...",
    environment="production",
)

# Validate a secret
is_valid = client.secrets.validate(secret.id)
```

### ChatFlows, Datasets, RAG, MCP, Voice and more (V2)

Version 1.1.0 adds first-class clients for the full V2 surface. See [`docs/cookbook/`](docs/cookbook/) for a runnable example per resource.

```python
# ChatFlows — conversational forms with field extraction and branching
flow = client.chatflows.create({"name": "Lead Q", "fields": [...]})
client.chatflows.deploy(flow["id"])
session = client.chatflows.start_session(flow["id"], channel="WEB")

# RAG — hybrid search and reranking
hits = client.rag.search(query="refund policy", dataset_ids=["ds-faq"], top_k=5)

# MCP — connect a remote tool server, list and execute tools
client.mcp.connect_server("hubspot", endpoint="https://mcp.example.com/sse")
result = client.mcp.execute("hubspot.create_contact", {"email": "ada@example.com"})

# Voice — list calls, fetch transcripts and recordings
calls = client.voice_calls.list(status="completed")
transcript = client.voice_calls.transcript(calls["content"][0]["sid"])

# Cost control — enforce caps and routing rules
client.cost_control.set_workspace_cap({"period": "MONTH", "currency": "USD", "limit": 1000})
```

Other clients exposed on `SwfteClient`: `client.datasets`, `client.documents`, `client.files`, `client.modules`, `client.marketplace`, `client.audit`, `client.agent_wizard`.

### Conversations

```python
# Create a conversation
conversation = client.conversations.create(title="Support Chat")

# Add messages
client.conversations.add_message(conversation.id, role="user", content="Hello!")
client.conversations.add_message(conversation.id, role="assistant", content="Hi there!")

# Retrieve message history
messages = client.conversations.get_messages(conversation.id)
```

## Configuration

```python
client = SwfteClient(
    api_key="sk-swfte-...",           # Required. Also reads SWFTE_API_KEY env var.
    base_url="https://api.swfte.com/agents/v2/gateway",  # Default
    timeout=60,                        # Request timeout in seconds
    max_retries=3,                     # Chat attempts after a pre-send connect timeout only
    workspace_id="ws-...",             # Workspace scoping. Also reads SWFTE_WORKSPACE_ID.
    # api_base_url="https://api.swfte.com/agents",  # Optional; derived from base_url
)
```

| Parameter | Type | Default | Description |
|---|---|---|---|
| `api_key` | `str` | `SWFTE_API_KEY` env | Your Swfte API key (`sk-swfte-...`) or personal access token (`pat_...`) |
| `base_url` | `str` | `https://api.swfte.com/agents/v2/gateway` | Gateway URL (chat completions, images, embeddings, audio, models) |
| `api_base_url` | `str` | `SWFTE_API_BASE_URL` env, else `base_url` minus `/v2/gateway`, `/v1/gateway` or `/gateway` | agents-service root used by agents, workflows, catalog and the other management resources |
| `timeout` | `int` | `60` | Request timeout (seconds) |
| `max_retries` | `int` | `3` | Attempts for non-streaming chat only after `requests.exceptions.ConnectTimeout`, which occurs before sending. Generic connection errors, read timeouts, HTTP errors and all other calls are never retried. Values below 1 mean one attempt |
| `workspace_id` | `str` | `SWFTE_WORKSPACE_ID` env | Workspace ID |

## Error Handling

```python
from swfte import SwfteClient, AuthenticationError, RateLimitError, APIError

client = SwfteClient(api_key="sk-swfte-...")

try:
    response = client.chat.completions.create(
        model="openai:gpt-4",
        messages=[{"role": "user", "content": "Hello"}],
    )
except AuthenticationError:
    print("Invalid API key")
except RateLimitError:
    print("Rate limit exceeded, retry later")
except APIError as e:
    print(f"API error: {e}")
```

| Exception | Description |
|---|---|
| `SwfteError` | Base exception for all SDK errors |
| `AuthenticationError` | Invalid or missing API key |
| `RateLimitError` | Rate limit exceeded (HTTP 429) |
| `APIError` | General API error; `status_code` and parsed `body` are set by `agents.chat`, `workflows.invoke*`, `get_execution_status`, `catalog.*` |
| `InvalidRequestError` | Malformed request (HTTP 400), or a missing required argument caught before the call |
| `WorkflowExecutionError` | `invoke_and_wait` / `wait_for_completion`: the run ended FAILED, TIMEOUT or CANCELLED/CANCELED (also a `RuntimeError`) |
| `WorkflowTimeoutError` | `invoke_and_wait` / `wait_for_completion`: gave up polling; the run is not cancelled (also a `TimeoutError`) |

Every call maps 401/403 to `AuthenticationError` and 429 to `RateLimitError`.
Other HTTP errors are `APIError` (chat, `agents.chat`, `workflows.invoke*`,
`get_execution_status`, `catalog.*`) or `requests.HTTPError` (the remaining
management resources).

## Supported Providers

| Provider | Models | Qualifier Prefix |
|---|---|---|
| OpenAI | GPT-4, GPT-4o, o1, DALL-E, Whisper, TTS | `openai:` |
| Anthropic | Claude 3.5, Claude 3 Opus/Sonnet/Haiku | `anthropic:` |
| Google | Gemini 2.0, Gemini 1.5 Pro/Flash | `google:` |
| Self-hosted | Any model via RunPod/vLLM deployment | `runpod:` |

## Requirements

- Python 3.10 or later
- `requests` >= 2.32.4
- `urllib3` >= 2.8.0

## Contributing

We welcome contributions. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and our [Code of Conduct](CODE_OF_CONDUCT.md).

All contributors must sign the [Swfte CLA](https://cla.swfte.com) before their first pull request can be merged.

## Security

- **API key handling.** Pass the key with `api_key=` or `SWFTE_API_KEY`; do not
  commit it. The key is sent only as an `Authorization: Bearer` header and is not
  retained in ordinary `vars(client)` or `repr(client)`, and SDK failure
  diagnostics redact it. Clients cannot be pickled. Explicit `client.api_key`
  access remains available for compatibility; avoid logging it or request headers.
  Successful API values are returned unchanged. The SDK does not log.
- **TLS.** Certificates are always verified. A `base_url` / `api_base_url` (or
  `SWFTE_API_BASE_URL`) that uses `http://` to a non-loopback host raises
  `InvalidRequestError` when the client is constructed, because the key would
  travel in cleartext. `http://` is accepted only for `localhost`, `127.0.0.1`
  and `::1`.
- **Retries.** Only `chat.completions.create` (non-streaming) retries, up to
  `max_retries` attempts, and only after `ConnectTimeout` before the request body
  was sent. Generic `ConnectionError` can mean a lost response after the server
  already executed the call; it is never retried. Read timeouts, HTTP errors
  (including 401/403/429/5xx) and every other call are
  not retried, so a call that may already have run is never repeated.
- **Timeouts.** Every request has a timeout (`timeout`, 60 seconds by default).
- **Redirects.** SDK requests never follow redirects, including 302 and 307.
  A redirect raises `APIError` with its HTTP status and response body. Stripping
  `Authorization` alone would still forward prompts, files or audio on 307/308.
  Configure the final endpoint URL directly instead of depending on redirects.

Report vulnerabilities to security@swfte.com (see [SECURITY.md](SECURITY.md)).

## License

This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.

Copyright (c) 2024-2026 Swfte, Inc.

## Resources

- [Swfte](https://www.swfte.com) — product home
- [swfte.com/resources](https://www.swfte.com/resources) — guides, cookbooks, recipes
- [swfte.com/developers](https://www.swfte.com/developers) — full API reference
- [swfte.com/pricing](https://www.swfte.com/pricing) — pay-as-you-go, transparent pricing
- [swfte.com/security](https://www.swfte.com/security) — security posture and compliance
- [status.swfte.com](https://status.swfte.com) — uptime and incident history
- [swfte.com/marketplace](https://www.swfte.com/marketplace) — agent, workflow and tool marketplace

### Other official Swfte SDKs

- [swfte-python](https://github.com/SwfteAI/swfte-python) — this repo ([PyPI](https://pypi.org/project/swfte-sdk/))
- [swfte-node](https://github.com/SwfteAI/swfte-node) — Node.js / TypeScript SDK ([npm](https://www.npmjs.com/package/@swfte/sdk))
- [swfte-java](https://github.com/SwfteAI/swfte-java) — Java SDK ([Maven Central](https://search.maven.org/artifact/com.swfte/swfte-sdk))
- [swfte-chat-widget](https://github.com/SwfteAI/swfte-chat-widget) — embeddable chat widget ([npm](https://www.npmjs.com/package/@swfte/chat-widget))
- [swfte-chatflow-widget](https://github.com/SwfteAI/swfte-chatflow-widget) — embeddable conversational form widget ([npm](https://www.npmjs.com/package/@swfte/chatflow-widget))
