Skip to main content

Getting Started

The strongly package is the official Python SDK for the Strongly.AI platform. It provides typed, synchronous and asynchronous clients covering every REST API domain: apps, workflows, agents, the AI gateway, MLOps, governance, FinOps, and more.

Installation​

pip install strongly

Requires Python 3.11 or newer.

Authentication​

Every request authenticates with a platform API key (it starts with sk-prod-). The SDK sends it in the X-API-Key header. Your organization and user identity are derived by the platform from the key, so you never set them yourself.

Provide the key in either of two ways:

from strongly import Strongly

# 1. Explicit
client = Strongly(api_key="sk-prod-...", base_url="https://strongly.example.com")

# 2. From the STRONGLY_API_KEY environment variable (recommended)
client = Strongly()

Give your Strongly platform's URL with the base_url argument or the STRONGLY_API_URL environment variable; there is no default. Inside a Strongly workspace, job or app the platform sets it and authenticates every call, so no key is needed there (its public address, for links, is STRONGLY_BASE_URL).

export STRONGLY_API_KEY="sk-prod-..."
export STRONGLY_API_URL="https://strongly.example.com"

Your first calls​

from strongly import Strongly

client = Strongly()

# Who am I?
me = client.users.me()
print(me.email, me.organization.id)

# List apps (auto-paginates as you iterate)
for app in client.apps.list(status="running"):
print(app.name, app.status)

# Create and read back a memory
memory = client.memory.create(kind="fact", content="Customer prefers email")
print(memory.id, memory.content)

Responses are typed pydantic models, so attributes autocomplete and validate.

Synchronous and asynchronous clients​

Every resource and method exists on both Strongly and AsyncStrongly with identical signatures. The async client awaits each call:

import asyncio
from strongly import AsyncStrongly

async def main():
async with AsyncStrongly() as client:
async for app in client.apps.list():
print(app.name)
await client.memory.create(kind="fact", content="...")

asyncio.run(main())

The sync client is also a context manager (with Strongly() as client: ...), which closes the underlying HTTP connection on exit.

Pagination​

list() methods return an auto-paginating iterator. Iterate it directly and the SDK fetches pages as needed, transparently walking the entire result set:

for workflow in client.workflows.list(search="invoice"):
print(workflow.id, workflow.name)

Filters are keyword-only. limit caps the total number of items returned (omit it to iterate everything); pages are fetched internally:

# At most 100 apps, regardless of how many match:
first_100 = list(client.apps.list(status="running", limit=100))

# Just the first match:
first = client.apps.list(status="running").first()

Request bodies​

Create and update methods take explicit keyword arguments, one per field. Pass the values you want to set; optional fields default to omitted:

from strongly import Strongly

client = Strongly()
client.apps.create(name="my-api", display_name="My API", cpu="0.5", memory="1GB")

The SDK serializes Python snake_case argument names to the platform's camelCase wire format automatically (display_name is sent as displayName). An argument a method does not take is a TypeError in Python, before anything is sent.

Responses​

Responses come back as idiomatic Python snake_case, never the platform's camelCase wire format. Typed models expose snake_case attributes, and the methods that return a plain dict (status, metrics, action results) return snake_case keys:

status = client.apps.status("app-1")
print(status.ready_replicas) # typed model, snake_case attribute

result = client.apps.start("app-1")
print(result["pod_ip"], result["success"]) # dict, snake_case keys

Free-form blobs you control, a workflow definition, a node's config, an object's metadata, are returned exactly as stored (keys untouched) so they round-trip back into a later request unchanged.

Error handling​

Failed requests raise typed exceptions. See Error Handling for the full hierarchy.

from strongly import Strongly, NotFoundError, RateLimitError

client = Strongly()
try:
app = client.apps.retrieve("does-not-exist")
except NotFoundError:
print("No such app")
except RateLimitError as e:
print("Slow down:", e)

Next steps​

Browse the resource pages in the sidebar; each lists every method with its real signature and behavior. Start with Apps, Workflows, Agents, or AI Inference.