MiniApps
MiniApp SDK
The small, stable contract every MiniApp imports. You don't write this yourself, Kai does. But knowing what's available helps you describe what your app can do.
The manifest
Every MiniApp has a kaiday.app.yaml at the root. It declares the entry point, the secrets the app needs, and which scopes it's allowed to use.
kaiday.app.yamlkind: dynamic runtime: python entrypoint: app:app auth: kaiday-user tables: reviews: fields: study_id: str decision: str created_at: datetime permissions: storage: [read, write] email: send agents: ask kb: read secrets: - MARKET_DATA_API_KEY egress: []
The runtime validates this manifest before mounting the app and enforces its declared tables and permissions on every SDK request.
The SDK surface
kaiday.db
Per-app namespaced Mongo. Read and write your own collections; you cannot read another app's data unless an admin grants a cross-app view.
pythonfrom kaiday import db # Each app gets its own namespace db.reviews.insert_one({"study_id": study_id, "decision": "defer"}) recent = db.reviews.find({"study_id": study_id}).limit(10)
kaiday.current_user
The authenticated caller. Call require() before accessing identity fields.
pythonfrom kaiday import current_user user = current_user.require() reviewer = {"id": user.id, "email": user.email, "name": user.name} is_workspace_admin = user.is_admin
kaiday.secrets
Per-company secrets, scoped to the app's manifest declarations. The raw secret never appears in your code.
pythonfrom kaiday import secrets market_data_token = secrets.MARKET_DATA_API_KEY
kaiday.config and kaiday.url
Read validated app configuration and build mount-aware links that continue to work under the app dispatcher.
pythonfrom kaiday import config, url benchmark = config.get("benchmark", "SPY") results_url = url("/results")
kaiday.storage
Object storage backed by MinIO. Use it for uploaded evidence, generated memos, and research exports. Files can be private (signed URL access) or public when explicitly intended.
pythonfrom kaiday import storage file = storage.upload("investment-memo.pdf", file_bytes, title="Investment memo") url = storage.signed_url(file.blob_key, expires=3600)
kaiday.design
Read company brand tokens and generate the CSS variables used by the financial starter templates.
pythonfrom kaiday import design css = design.css_vars()
kaiday.email
Send mail from your verified domain. Subject to the same SPF/DKIM that Email uses.
pythonfrom kaiday import email email.send( to="reviewer@example.com", subject="Study ready for review", text=f"Study {study_id} is ready for review.", )
kaiday.agents
Ask the scoped Kai agent for a single financial-analysis output. Tool-using chat remains outside the MiniApp runtime.
pythonfrom kaiday import agents memo = agents.ask( prompt="Draft an investment memo with thesis, evidence, risks, and limitations.", context={"study_id": study.id}, ) return render("memo.html", memo=memo)
kaiday.kb
Search or read workspace evidence when the manifest grants kb: read.
pythonfrom kaiday import kb evidence = kb.search("transaction-cost assumptions", limit=10)
How an app runs
kaiday.dbkaiday.current_userkaiday.secretskaiday.configkaiday.urlkaiday.storagekaiday.designkaiday.emailkaiday.agentskaiday.kbThe runtime architecture, in plain language:
- Every workspace gets one long-lived runtime container.
- The supervisor pulls every MiniApp repo this workspace owns.
- Each app is mounted under
/dyn/<workspace-slug>/<app-slug>. - A reverse proxy routes inbound requests to the right workspace's runtime.
- Inside the runtime, the SDK provides the contracts above.
What the SDK does not expose
The contract is deliberately small. There is no kaiday.calendar, no kaiday.crm, and no payment or checkout module. An app can only use the modules, tables, and permissions declared in its manifest.