SDK Reference

Build on Molly — OpenAI-compatible, sovereign by default.

The Molly SDK speaks the OpenAI wire format. If you already have OpenAI code, point the base URL at Molly and you're running against your own sovereign multi-agent orchestrator — chat, stream, and train private specialists with no ML engineering required.

Overview

Every request routes through Molly's CEO orchestrator, which dispatches to LoRA specialists across a 4-tier stack — T0 on-device, T1 LAN, T2 self-hosted, T3 external API. Local is the default; higher tiers are policy-gated.

  • OpenAI-compatible: reuse the official openai clients for Python & Node.
  • One model name: pass "molly" — the orchestrator selects the specialist.
  • Plug-and-play training: submit a dataset, poll status, deploy a specialist.
  • Provenance: responses are backed by Merkle-tree traceability.

Install

Install the native Molly client, or use the official OpenAI SDK pointed at Molly's base URL.

shell
# Native Molly client (OpenAI-compatible)
pip install molly

# Or use the official OpenAI SDK
pip install openai

Authentication

Authenticate with a bearer API key from your workspace. Keys are prefixed mk-. Store it in an environment variable — never commit it.

FieldValue
Base URLhttps://app.iamolly.ai/api/molly/v1
Auth headerAuthorization: Bearer mk-...
Default modelmolly (the orchestrator)
.env
MOLLY_API_KEY=mk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MOLLY_BASE_URL=https://app.iamolly.ai/api/molly/v1

Python quickstart

Use the official OpenAI SDK and set base_url to Molly. Call the orchestrator with the model name "molly".

chat.py
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["MOLLY_API_KEY"],
    base_url="https://app.iamolly.ai/api/molly/v1",
)

resp = client.chat.completions.create(
    model="molly",            # the orchestrator picks the specialist
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Summarize our Q3 support tickets."},
    ],
)

print(resp.choices[0].message.content)

Streaming

Set stream=True to receive tokens incrementally as server-sent events.

stream.py
stream = client.chat.completions.create(
    model="molly",
    messages=[{"role": "user", "content": "Draft a release note."}],
    stream=True,
)

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

Training jobs (plug-and-play)

Point Molly at your data — it trains, evaluates, and deploys a private LoRA specialist. Submit the dataset, poll status, then deploy. The native molly client exposes the training endpoints.

train.py
import os, time
from molly import Molly

client = Molly(api_key=os.environ["MOLLY_API_KEY"])

# 1. Upload a dataset (JSONL of chat examples)
dataset = client.datasets.upload(
    file=open("support_tickets.jsonl", "rb"),
    name="support-v1",
)

# 2. Submit a training job -> auto train + eval
job = client.training.create(
    base="molly",
    dataset=dataset.id,
    specialist="support-agent",
)

# 3. Poll until the eval-gated job completes
while job.status not in ("succeeded", "failed"):
    time.sleep(5)
    job = client.training.retrieve(job.id)
    print(job.status, job.eval_score)

# 4. Deploy the specialist into the orchestrator
if job.status == "succeeded":
    client.specialists.deploy(job.specialist_id)
    print("Deployed. Routable via model='molly'.")
Federated & private.

Only distilled adapter deltas leave a node — never raw data. Every trained adapter is recorded in the Merkle-tree provenance log.

Node / TypeScript quickstart

Same approach in Node: use the official openai package and set baseURL.

chat.ts
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.MOLLY_API_KEY,
  baseURL: "https://app.iamolly.ai/api/molly/v1",
});

const resp = await client.chat.completions.create({
  model: "molly",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Summarize our Q3 support tickets." },
  ],
});

console.log(resp.choices[0].message.content);

Streaming (Node)

stream.ts
const stream = await client.chat.completions.create({
  model: "molly",
  messages: [{ role: "user", content: "Draft a release note." }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

Error handling & rate limits

Molly returns standard HTTP status codes with an OpenAI-style error body. The default rate limit is 60 requests per minute; exceeding it returns 429. Back off and retry using the Retry-After header.

StatusMeaning
401Invalid or missing API key
403Policy-gated tier not permitted for this key
404Model or specialist not found
429Rate limit exceeded (60 req/min)
500Internal orchestration error
retry.py
import time
from openai import RateLimitError, APIError

def chat_with_retry(messages, retries=3):
    for attempt in range(retries):
        try:
            return client.chat.completions.create(
                model="molly", messages=messages,
            )
        except RateLimitError:
            time.sleep(2 ** attempt)  # exponential backoff
        except APIError as e:
            print(f"API error: {e}")
            raise
    raise RuntimeError("exhausted retries")
Tip.

Local T0/T1 requests are not billed and count against a separate, higher limit. Rate limits apply per API key and can be raised on Team and Enterprise plans.