Skip to main content

MISSILYA GROUP Core SDK — unified, vault-backed infrastructure for AI, payments, notifications, auth, and monitoring.

Project description

missilya-sdk

MISSILYA GROUP Core SDK — one versioned, vault-backed Python package that replaces the copy-pasted emergentintegrations code spread across the MISSILYA ecosystem. It gives every application a single, provider-agnostic API for AI, payments, notifications, auth, secrets, and monitoring, with credentials sourced from MISSILYA VAULT and no vendor lock-in.

  • Package: missilya-sdk · Import namespace: missilya_sdk
  • Runtime: staging & production (routes to real providers using vault keys)
  • Python: 3.11 – 3.13
  • Sandbox twin: missilya-sdk-sandbox — API-identical, deterministic, offline (use in development & CI)

Status: private, under review. After approval the package is published to the MISSILYA private pip registry so any project can pip install missilya-sdk.


Table of contents

  1. Why this exists
  2. Install
  3. Quickstart
  4. Core concepts
  5. Configuration & the vault
  6. Module reference
  7. The Adapter Engine & failover
  8. Multi-tenant usage
  9. Error handling
  10. Observability
  11. Security model
  12. Governance & CI
  13. Migration from emergentintegrations
  14. Sandbox parity & versioning
  15. Local development
  16. Project layout

1. Why this exists

emergentintegrations was vendored (copy-pasted) into ~35 repositories. Each copy drifted: no versioning, no tests, no CI, hardcoded API keys. This SDK fixes that:

Before (emergentintegrations) After (missilya_sdk)
Copy in every repo, silently diverging One versioned package, one source of truth
OpenAI-only, tightly coupled 100+ models via the Adapter Engine, swappable
Hardcoded keys / .env VAULT-first, fail-closed in production
No tests, no CI Strict typing, tests, parity check, CI gates
Direct vendor imports everywhere Apps import only missilya_sdk (CI-enforced)

2. Install

Install only the modules a service needs (optional extras keep the dependency surface small):

pip install "missilya-sdk[ai]"            # LLM, images, TTS, STT, translation
pip install "missilya-sdk[payments]"      # Stripe
pip install "missilya-sdk[notifications]" # Resend (email), Twilio (SMS/WhatsApp)
pip install "missilya-sdk[auth]"          # Google sign-in (RS256 verification)
pip install "missilya-sdk[monitoring]"    # Sentry
pip install "missilya-sdk[all]"           # everything
Extra Installs
[ai] litellm, openai, elevenlabs, deepl
[payments] stripe
[notifications] resend, twilio
[auth] cryptography (Google ID-token RS256 verification)
[monitoring] sentry-sdk
[all] all of the above
[dev] pytest, ruff, mypy, build, twine, …

Installing into a MISSILYA repo

Until the package is published to the private registry, depend on it directly from GitHub (pin a tag or commit for reproducibility):

pip install "missilya-sdk[all] @ git+https://github.com/MISSILYA-GROUP/MISSILYA-CORE-SDK.git@v0.2.0"

For development/CI, use the sandbox twin (offline, deterministic, no provider keys) and swap to core by environment — not by import:

pip install "missilya-sdk-sandbox @ git+https://github.com/MISSILYA-GROUP/MISSILYA-SANDBOX-SDK.git@v0.2.0"

Production readiness

Every module is type-checked (mypy --strict) and has 100% test coverage (enforced in CI). Unit tests exercise provider boundaries with mocks, so before relying on a provider-backed capability in production, run the live smoke suite once in an environment that has the real credentials (or vault access):

MISSILYA_RUN_INTEGRATION=1 pytest tests/integration -m integration --no-cov -v

Each smoke test self-skips unless its credentials are present, and makes the smallest real call that proves the round-trip (vault read, chat completion, Stripe test session, email/SMS/WhatsApp send, Google ID-token verify).

One-click in CI: the Live Integration Smoke GitHub Actions workflow (.github/workflows/integration.yml, manual Run workflow) runs the same suite using repository secrets — no local setup. Configure under Settings → Secrets and variables → Actions (each capability self-skips if its secret is absent, so you can validate incrementally):

Secret For
MISSILYA_VAULT_URL, MISSILYA_VAULT_CLIENT_ID/SECRET, MISSILYA_VAULT_PROJECT_ID vault read (requires a reachable vault.missilya.com)
OPENAI_API_KEY chat completion
STRIPE_TEST_SECRET_KEY checkout session (TEST key)
RESEND_API_KEY + var MISSILYA_SMOKE_EMAIL_TO email
TWILIO_ACCOUNT_SID/AUTH_TOKEN + vars TWILIO_SMS_FROM, MISSILYA_SMOKE_SMS_TO SMS
WHATSAPP_ACCESS_TOKEN + vars WHATSAPP_PHONE_NUMBER_ID, MISSILYA_SMOKE_WHATSAPP_TO WhatsApp
GOOGLE_OAUTH_CLIENT_ID, GOOGLE_TEST_ID_TOKEN Google sign-in

ai.generate_video is a stub. No cross-provider video API is wired into core yet; it raises ProviderError by design. The sandbox returns a fixture so app code can integrate against the shape. Do not depend on live video until a provider adapter is added.

For development and CI, install the offline twin instead — same import, no real calls: pip install missilya-sdk-sandbox.


3. Quickstart

from missilya_sdk.ai.chat import LlmChat, SystemMessage, UserMessage

chat = LlmChat(model="gpt-4o")                       # key resolved from VAULT
chat.add_message(SystemMessage("You are a MISSILYA assistant."))
chat.add_message(UserMessage("Explain our subscription tiers."))

print(chat.chat())                                   # -> str (legacy-compatible)

No API keys in code. No import openai. The SDK resolves the right credential from the vault, routes through the Adapter Engine, and returns a normalized result.


4. Core concepts

Concept What it is
Unified API missilya_sdk.<domain>.<capability> — apps never touch a vendor SDK.
Adapter Engine Internal layer that resolves credentials, picks a provider, normalizes responses, and fails over.
VAULT-first config Credentials come from MISSILYA VAULT; production fails closed if a secret is missing.
TenantContext Scopes every call (vault path, billing, audit) to one tenant.
Typed errors Every failure is a missilya_sdk.exceptions.* subclass of MissilyaError.
Sandbox parity The sandbox package mirrors this public API exactly, verified in CI.

5. Configuration & the vault

Credentials resolve in this order (config.get_config):

  1. MISSILYA VAULT (Infisical) — required for staging/production
  2. CI/vault-injected environment variable (deployment bridge)
  3. Local environment variable (development only)
  4. Non-secret default (if provided)
  5. Fail closedConfigurationError

In production, a secret resolved from a plain environment variable is rejected unless MISSILYA_ALLOW_ENV_SECRETS=1 (an approved CI/vault bridge).

Runtime environment variables

Variable Purpose
MISSILYA_VAULT_URL Vault base URL. Defaults to https://vault.missilya.com.
MISSILYA_VAULT_CLIENT_ID / ..._CLIENT_SECRET Machine-identity Universal Auth (recommended).
MISSILYA_VAULT_TOKEN Static service/access token (alternative to Universal Auth).
MISSILYA_VAULT_PROJECT_ID Infisical project for app secrets.
MISSILYA_VAULT_SHARED_PROJECT_ID Project holding shared provider keys.
MISSILYA_ENV development / staging / production.
MISSILYA_ALLOW_ENV_SECRETS Set 1 only for an approved CI/vault bridge in production.

See .env.example for the full list of secret names (OPENAI_API_KEY, STRIPE_SECRET_KEY, RESEND_API_KEY, JWT_SECRET, SENTRY_DSN, …).

How the vault call works

VaultClient speaks the Infisical REST API:

  • Universal Auth login: POST /api/v1/auth/universal-auth/login → short-lived access token (cached in memory until just before expiry).
  • Read secret: GET /api/v4/secrets/{name}?projectId=&environment=&secretPath=/{ "secret": { "secretValue": "..." } }.

Provider keys (e.g. OPENAI_API_KEY) fall back to the shared project; app-specific secrets come from the app project. Values are cached briefly, never logged, and the client retries transient failures with backoff.


6. Module reference

missilya_sdk.ai.chat — LLM chat

from missilya_sdk.ai.chat import LlmChat, SystemMessage, UserMessage, AssistantMessage

chat = LlmChat(model="gpt-4o", fallbacks=["claude-sonnet-4-20250514"])
chat.add_message(SystemMessage("Be concise."))
chat.add_message(UserMessage("Summarize Q2 in one sentence."))

text = chat.chat()                 # -> str (emergentintegrations-compatible)
resp = chat.complete()             # -> ChatResponse(content, model, provider, usage, raw)
print(resp.usage.total_tokens)

# Async + streaming
text = await chat.achat()
async for delta in chat.astream():
    print(delta, end="")

Model strings follow the LiteLLM convention: "gpt-4o", "claude-sonnet-4-...", "gemini/gemini-2.5-pro", "mistral/...", "deepseek/...".

missilya_sdk.ai.images — image generation

from missilya_sdk.ai.images import generate_image
img = generate_image("a neon skyline at dusk", model="dall-e-3", size="1024x1024")
print(img.url)

missilya_sdk.ai.tts / .stt — speech

from missilya_sdk.ai.tts import text_to_speech
from missilya_sdk.ai.stt import speech_to_text

audio = text_to_speech("Hello from MISSILYA", voice_id="JBFqnCBsd6RMkjVDRZzb")
open("hello.mp3", "wb").write(audio.audio)

transcript = speech_to_text(open("hello.mp3", "rb").read())
print(transcript.text)

missilya_sdk.ai.translation — translation

from missilya_sdk.ai.translation import translate
print(translate("Bonjour le monde", target_lang="EN-US").text)

missilya_sdk.payments.stripe — payments

from missilya_sdk.payments.stripe import StripeCheckout
from missilya_sdk.payments.checkout import CheckoutSessionRequest

checkout = StripeCheckout()
session = checkout.create_session(CheckoutSessionRequest(
    line_items=[{"price": "price_123", "quantity": 1}],
    success_url="https://app.missilya.com/success",
    cancel_url="https://app.missilya.com/cancel",
    customer_email="client@example.com",
))
print(session.url)

# Webhook (signature verified against vault STRIPE_WEBHOOK_SECRET)
event = checkout.handle_webhook(request_body, signature_header)

missilya_sdk.notifications — email / SMS / WhatsApp

from missilya_sdk.notifications.email import send_email
from missilya_sdk.notifications.sms import send_sms
from missilya_sdk.notifications.whatsapp import send_whatsapp

send_email(to="user@example.com", subject="Welcome", html="<h1>Hi</h1>")
send_sms(to="+10000000000", body="Your code is 123456")
send_whatsapp(to="+10000000000", body="Your order shipped")

missilya_sdk.whatsapp — two-way WhatsApp (Meta Cloud API or Twilio)

from missilya_sdk.whatsapp import WhatsAppClient, parse_inbound, verify_signature

wa = WhatsAppClient()                       # provider from WHATSAPP_PROVIDER (default "meta")
wa.send_text("+10000000000", "Your order shipped")
wa.send_template("+10000000000", "order_update", language="en_US")
wa.send_media("+10000000000", "https://cdn.example.com/receipt.pdf", kind="document")

# Inbound webhook (framework-agnostic):
verify_signature(raw_body, request.headers["X-Hub-Signature-256"])   # fail-closed
for msg in parse_inbound(raw_body):
    print(msg.from_number, msg.text)
    wa.mark_read(msg.message_id)

The Meta Cloud API is the default backend; set WHATSAPP_PROVIDER=twilio to use Twilio instead. Credentials (WHATSAPP_ACCESS_TOKEN, WHATSAPP_PHONE_NUMBER_ID, WHATSAPP_APP_SECRET, WHATSAPP_VERIFY_TOKEN) come from MISSILYA VAULT.

missilya_sdk.auth.jwt — JWT helpers

from missilya_sdk.auth.jwt import create_token, verify_token

token = create_token({"sub": "user-1"}, expires_in=3600)   # signed with vault JWT_SECRET
claims = verify_token(token)                                 # raises AuthenticationError if invalid

missilya_sdk.auth.google — Google Sign-In (OIDC → Missilya JWT)

from missilya_sdk.auth import sign_in_with_google, verify_google_token

# Verify a Google ID token from the client (validates signature, issuer, aud, exp):
identity = verify_google_token(google_id_token)             # -> GoogleIdentity(sub, email, ...)

# Or verify AND mint a first-party Missilya session token in one step:
session = sign_in_with_google(google_id_token)
session.token       # a Missilya JWT (verify with auth.jwt.verify_token)
session.identity    # the verified GoogleIdentity

RS256 verification needs the [auth] extra: pip install "missilya-sdk[auth]". The audience defaults to the vault-resolved GOOGLE_OAUTH_CLIENT_ID.

missilya_sdk.vault.client — direct vault access

from missilya_sdk.vault.client import VaultClient
client = VaultClient(url="https://vault.missilya.com",
                     client_id="...", client_secret="...", project_id="...")
value = client.get_secret("SOME_APP_SECRET", environment="production")

Application code rarely calls VaultClient directly for provider keys — the capability modules resolve their own credentials internally.

Public import surface (v0.1.0)

from missilya_sdk import MissilyaSDK, TenantContext, get_config
from missilya_sdk.ai.chat import LlmChat, UserMessage, SystemMessage, AssistantMessage, ChatResponse, ChatUsage
from missilya_sdk.ai.images import generate_image, ImageResult
from missilya_sdk.ai.tts import text_to_speech, SpeechResult
from missilya_sdk.ai.stt import speech_to_text, TranscriptResult
from missilya_sdk.ai.translation import translate, TranslationResult
from missilya_sdk.ai.video import generate_video, VideoJob
from missilya_sdk.payments.stripe import StripeCheckout
from missilya_sdk.payments.checkout import CheckoutSessionRequest, CheckoutSession, WebhookEvent
from missilya_sdk.notifications import send_email, send_sms, send_whatsapp, DeliveryResult
from missilya_sdk.auth.jwt import create_token, verify_token, decode_token
from missilya_sdk.monitoring import get_logger, new_correlation_id, track_event, init_sentry, capture_exception, capture_message
from missilya_sdk.exceptions import MissilyaError, ConfigurationError, ProviderError, RateLimitError, VaultError

7. The Adapter Engine & failover

Every LLM call flows through one engine so the application never targets a vendor:

App → LlmChat → Adapter Engine
                 ├─ resolve credential from VAULT (per provider)
                 ├─ dispatch via LiteLLM to the chosen model
                 ├─ on failure, fail over to the next model in `fallbacks`
                 └─ normalize response + usage; emit redacted telemetry
chat = LlmChat(
    model="gpt-4o",
    fallbacks=["claude-sonnet-4-20250514", "gemini/gemini-2.5-pro"],
)

If OpenAI errors, the engine automatically retries with Anthropic, then Gemini — no application change. Errors are normalized to typed exceptions (RateLimitError, ProviderTimeoutError, ProviderAuthError, ProviderError).


8. Multi-tenant usage

from missilya_sdk import TenantContext
from missilya_sdk.ai.chat import LlmChat, UserMessage

ctx = TenantContext(tenant_id="civytax", env="production")
chat = LlmChat(model="gpt-4o", context=ctx)
chat.add_message(UserMessage("Calculate taxes for ..."))
answer = chat.chat()   # key resolved from the civytax scope; usage tagged to civytax

The context drives the vault project/path, tags telemetry for per-tenant billing, and adds traceability headers. A convenience facade is also available:

from missilya_sdk import MissilyaSDK
sdk = MissilyaSDK(tenant_id="civytax", environment="production")
chat = sdk.chat(model="gpt-4o")

9. Error handling

All failures are subclasses of MissilyaError:

MissilyaError
├── ConfigurationError
├── ProviderError
│   ├── RateLimitError
│   ├── ProviderTimeoutError
│   └── ProviderAuthError
├── AuthenticationError
├── VaultError
│   ├── VaultConnectionError
│   └── VaultSecretNotFound
└── ValidationError
from missilya_sdk.exceptions import MissilyaError, RateLimitError

try:
    answer = chat.chat()
except RateLimitError:
    ...   # back off / queue
except MissilyaError as exc:
    log.error("sdk_error", error=str(exc))

10. Observability

from missilya_sdk.monitoring import get_logger, new_correlation_id, init_sentry, capture_exception

log = get_logger(__name__)        # structured, secret-redacting logger
init_sentry()                     # DSN from vault SENTRY_DSN; no-op if absent

def handle(req):
    new_correlation_id()          # correlate every log line for this request
    try:
        ...
    except Exception as exc:
        capture_exception(exc)    # report to Sentry if configured
        raise

Logs emit structured JSON and automatically redact API keys, bearer tokens, sk-…/sk_live_…/whsec_… patterns, card data, and other sensitive fields. track_event(...) / track_latency(...) record usage and latency.


11. Security model

  • No plaintext secrets anywhere in code or .env (production fails closed).
  • Secrets never logged — redaction is applied before anything is emitted.
  • Least privilege — runtime uses a read-only machine identity scoped to one project/environment.
  • Production guardsStripeCheckout requires a live key in production; the config layer refuses plain-env secrets in production by default.
  • Provenance — releases record SHA-256 hashes of build artifacts.

12. Governance & CI

  • Forbidden-import gate: tools/check_forbidden_imports.py fails CI if app code imports openai/stripe/twilio/anthropic/litellm/resend/… directly.
  • Quality gate: ruff (lint) + mypy --strict (types) + pytest (tests) on Python 3.11/3.12/3.13.
  • Secret scan: gitleaks on every push/PR.
  • Release: tag → build sdist/wheel → twine check → SHA-256 ledger → publish to the private registry (manual production approval gate).
  • Container: Dockerfile + GHCR publish workflow.
  • Zone: classified A (foundation) in repo.classification.yml.

13. Migration from emergentintegrations

Mostly a find-and-replace on imports; see docs/migration-guide.md.

Legacy MISSILYA SDK
from emergentintegrations.llm.chat import LlmChat, UserMessage from missilya_sdk.ai.chat import LlmChat, UserMessage
from emergentintegrations.payments.stripe.checkout import StripeCheckout from missilya_sdk.payments.stripe import StripeCheckout
resend.Emails.send(...) from missilya_sdk.notifications.email import send_email

The LlmChat / StripeCheckout APIs are preserved, so most migrations need no business-logic changes — just the import path and removing hardcoded keys.


14. Sandbox parity & versioning

  • The sandbox package exposes an identical public API (same names, signatures, return shapes). This is verified statically by repos/sdk-tools/check_sdk_parity.py and as a test.
  • Versions are kept in lock-step (src/missilya_sdk/_version.py); a feature cannot land in core without matching sandbox behavior.
  • The package follows SemVer. Current version: 0.1.0.

15. Local development

python -m venv .venv
./.venv/Scripts/python -m pip install -e ".[all,dev]"   # Windows
# source .venv/bin/activate && pip install -e ".[all,dev]"   # macOS/Linux

ruff check src tests tools
mypy src/missilya_sdk
pytest -q
python -m build && twine check dist/*

16. Project layout

src/missilya_sdk/
├── __init__.py            # public top-level exports
├── config.py              # VAULT-first config resolution
├── context.py             # TenantContext, MissilyaSDK facade
├── exceptions.py          # typed error hierarchy
├── ai/                    # chat (+_engine adapter), images, tts, stt, translation, video
├── payments/              # stripe, checkout models
├── notifications/         # email, sms, whatsapp
├── auth/                  # jwt
├── vault/                 # Infisical client
└── monitoring/            # logging, analytics, sentry
tests/                     # unit + smoke + parity tests
tools/check_forbidden_imports.py
docs/                      # getting-started, migration-guide
.github/workflows/         # test, publish, release, docker-publish
Dockerfile · repo.classification.yml · .env.example

License

Proprietary — © 2026 MISSILYA GROUP. See LICENSE. Private to MISSILYA GROUP; redistribution requires written authorization from Yvon Kamach (CEO).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

missilya_sdk-0.2.1.tar.gz (61.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

missilya_sdk-0.2.1-py3-none-any.whl (58.2 kB view details)

Uploaded Python 3

File details

Details for the file missilya_sdk-0.2.1.tar.gz.

File metadata

  • Download URL: missilya_sdk-0.2.1.tar.gz
  • Upload date:
  • Size: 61.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for missilya_sdk-0.2.1.tar.gz
Algorithm Hash digest
SHA256 661d2f8f964578c636f38fdc61526b336b8749b93e463c65bb746aa6d2568473
MD5 79ed68ced6c9cd6201fa50cd42c72edf
BLAKE2b-256 e511bf882af60f23650d9039ddd063046ccdfe65709c10b1e62ca3478519f919

See more details on using hashes here.

Provenance

The following attestation bundles were made for missilya_sdk-0.2.1.tar.gz:

Publisher: publish.yml on MISSILYA-GROUP/MISSILYA-CORE-SDK

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file missilya_sdk-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: missilya_sdk-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 58.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for missilya_sdk-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bd145ab9042469251a21b1516ff913317fb36cbe035aa49b3957a654e595c849
MD5 263b0e359b7c920215895958d4747f08
BLAKE2b-256 aae31ad04218c95e673f7da6ae47e27fe6d8a98edb71ba28c3e09c477da59042

See more details on using hashes here.

Provenance

The following attestation bundles were made for missilya_sdk-0.2.1-py3-none-any.whl:

Publisher: publish.yml on MISSILYA-GROUP/MISSILYA-CORE-SDK

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page