Payment confirmed SDK v1.0.0

You actually own this now.
Let's build something real.

You paid, you're in. This page walks you through plugging the Mulberry SDK into a real project — no fluff, no hand-wavy "and then magic happens." Every step has code you can actually run.

🐍

Python SDK

Linux · Python 3.11+ · zero deps

Download ZIP
🦀

Rust Crate

Linux · Rust 1.75+ · crates.io ready

Download ZIP
📄

Your SDK key

Starts with mbs_linux_ — keep it secret

Step 0 of 6
1

Install the SDK

Pick your language. Python is easier to start with — you can paste code and run it immediately. Rust is faster and catches more bugs at compile time (the compiler basically yells at you until the code is correct, which is actually a good thing).

Terminal
# create a virtual environment first (best practice, trust me)
python3 -m venv .venv
source .venv/bin/activate

# then install
pip install mulberry-sdk
Cargo.toml
[dependencies]
mulberry-sdk = "1.0.0"
What just happened? You pulled the SDK from a package registry (PyPI for Python, crates.io for Rust). The registry is basically a giant shelf of code other people wrote so you don't have to.
2

Store your key safely

Your SDK key is a secret. Don't paste it directly into your code — if you push that to GitHub, anyone can find it and use your account. Use an environment variable instead.

Terminal — set it once per session
export MULBERRY_KEY="mbs_linux_your_key_here"
Want it permanent? Add that line to your ~/.bashrc or ~/.zshrc file and it'll be set every time you open a terminal.
Or use a .env file (never commit this file)
# .env
MULBERRY_KEY=mbs_linux_your_key_here
Add .env to .gitignore — open or create .gitignore and add a line that just says .env. Now Git will never accidentally include it in a commit.
3

Configure the SDK at startup

Call MulberrySDK.configure() once, as early as possible when your program starts. It fires off a background validation check — your app keeps running while that happens, it doesn't freeze.

main.py
import os
from mulberry import MulberrySDK

# read your key from the environment — never hardcode it
key = os.environ["MULBERRY_KEY"]

# configure once at startup
MulberrySDK.configure(key=key)

print("SDK configured. Validation running in background...")
src/main.rs
use mulberry_sdk::MulberrySDK;

fn main() {
    let key = std::env::var("MULBERRY_KEY")
        .expect("MULBERRY_KEY env var not set");

    MulberrySDK::configure(key, None);

    println!("SDK configured. Validation running in background...");
}
Why background validation? Hitting a network endpoint takes time (30–300ms). If we blocked your whole app waiting for a response, every user would notice a freeze at startup. Running it in a background thread means your app stays snappy.

Run it and check for errors

python3 main.py — if you see "SDK configured" with no crash, you're good. A KeyError means the env var isn't set yet.

4

Check validation status

After startup, you can check whether your key was accepted. Since validation happens in the background, wait a moment before checking — or gate your features behind it.

main.py — continued
import time
import os
from mulberry import MulberrySDK

MulberrySDK.configure(key=os.environ["MULBERRY_KEY"])

# give the background thread a moment to finish
time.sleep(1)

if MulberrySDK.is_valid():
    print(f"Authenticated! Tier: {MulberrySDK.tier()}")
else:
    print("Key not validated yet — check your key or network")
src/main.rs — continued
use std::time::Duration;
use mulberry_sdk::MulberrySDK;

fn main() {
    let key = std::env::var("MULBERRY_KEY").expect("MULBERRY_KEY not set");
    MulberrySDK::configure(key, None);

    // give the background thread a moment
    std::thread::sleep(Duration::from_secs(1));

    if MulberrySDK::is_valid() {
        println!("Authenticated! Tier: {}", MulberrySDK::tier());
    } else {
        eprintln!("Key not validated — check your key or network");
    }
}
Expected output: Authenticated! Tier: developer — that's your plan level. If you see Key not validated, double-check that MULBERRY_KEY is set and starts with mbs_linux_.
5

Send your first AI message

Now you'll use the AIMessage type to structure a conversation and pass it to a provider. This is the same shape every AI API uses — a list of messages with roles.

messages.py
from mulberry import AIMessage, AIRole

conversation = [
    AIMessage(
        role=AIRole.system,
        content="You are a helpful coding assistant."
    ),
    AIMessage(
        role=AIRole.user,
        content="What does the 'import' keyword do in Python?"
    ),
]

# print to see the structure
for msg in conversation:
    print(f"[{msg.role.value}] {msg.content}")
src/main.rs
use mulberry_sdk::{AIMessage, AIRole};

let conversation = vec![
    AIMessage::new(AIRole::System, "You are a helpful coding assistant."),
    AIMessage::new(AIRole::User,   "What does 'use' do in Rust?"),
];

for msg in &conversation {
    println!("[{:?}] {}", msg.role, msg.content);
}
Why three roles? system sets the AI's "personality" or rules. user is what the human typed. assistant is what the AI replied. You build the full history and send it each time — the AI has no memory of its own.
6

Wire up a custom provider

The SDK ships protocols, not implementations — you plug in whatever AI endpoint you want. Here's a minimal provider that hits the Mulberry cloud router.

provider.py
from typing import Optional, Sequence
from mulberry import AIProvider, AIMessage

class MulberryCloudProvider(AIProvider):
    @property
    def identifier(self) -> str:
        return "mulberry-cloud"

    @property
    def endpoint(self) -> str:
        return "https://api.mulberryide.com/v1/chat"

    def build_request(
        self,
        messages: Sequence[AIMessage],
        credential: str
    ) -> dict:
        return {
            "url": self.endpoint,
            "headers": {"Authorization": f"Bearer {credential}"},
            "json": {
                "messages": [
                    {"role": m.role.value, "content": m.content}
                    for m in messages
                ],
            },
        }

    def parse_stream_chunk(self, line: str) -> Optional[str]:
        # SSE lines look like: data: {"delta": "hello"}
        if not line.startswith("data: "):
            return None
        import json
        payload = json.loads(line[6:])
        return payload.get("delta")
src/provider.rs
use mulberry_sdk::{AIProvider, AIMessage};

pub struct MulberryCloudProvider;

impl AIProvider for MulberryCloudProvider {
    fn identifier(&self) -> &str { "mulberry-cloud" }

    fn endpoint(&self) -> &str {
        "https://api.mulberryide.com/v1/chat"
    }

    fn build_request(
        &self,
        messages: &[AIMessage],
        credential: &str,
    ) -> serde_json::Value {
        serde_json::json!({
            "url": self.endpoint(),
            "authorization": format!("Bearer {}", credential),
            "messages": messages,
        })
    }

    fn parse_stream_chunk(&self, line: &str) -> Option<String> {
        let data = line.strip_prefix("data: ")?;
        let json: serde_json::Value =
            serde_json::from_str(data).ok()?;
        Some(json["delta"].as_str()?.to_string())
    }
}
What is SSE? Server-Sent Events — the server streams the AI response word by word instead of waiting until it's all done. That's why chatbots "type" the answer in real time rather than pausing and dumping it all at once.
🎉

You just built an SDK integration from scratch.

You installed a library, secured a secret key, configured a background validator, modelled a conversation, and implemented a provider interface. That's real software engineering — not just vibing.

Keep building

You've got the foundation. Here's where to go from here.

🔐

Credential store

Implement CredentialStore to swap in a real secret vault like keyring or HashiCorp Vault.

Docs
📊

Interaction logging

Implement InteractionLogger to track latency, token counts, and errors across every call.

Docs
🧠

Governance layer

Use MulberryGovernance on Swift, or build your own policy layer on Linux using the same patterns.

Docs