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.
Starts with mbs_linux_ — keep it secret
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).
# create a virtual environment first (best practice, trust me) python3 -m venv .venv source .venv/bin/activate # then install pip install mulberry-sdk
[dependencies] mulberry-sdk = "1.0.0"
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.
export MULBERRY_KEY="mbs_linux_your_key_here"
~/.bashrc
or ~/.zshrc file and it'll be set every time you open a terminal.
# .env MULBERRY_KEY=mbs_linux_your_key_here
.gitignore
and add a line that just says .env. Now Git will never accidentally
include it in a commit.
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.
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...")
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..."); }
python3 main.py — if you see "SDK configured" with no crash,
you're good. A KeyError means the env var isn't set yet.
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.
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")
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"); } }
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_.
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.
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}")
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); }
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.
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.
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")
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()) } }
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.
You've got the foundation. Here's where to go from here.
Implement CredentialStore to swap in a real secret vault like keyring or HashiCorp Vault.
Implement InteractionLogger to track latency, token counts, and errors across every call.
Use MulberryGovernance on Swift, or build your own policy layer on Linux using the same patterns.