Skip to main content

Imperal SDK

Build AI agents. Ship to marketplace. Get paid.

The SDK for the first AI Cloud OS.

PyPI version Python Tests License

Getting Started | Features | Docs (source) | OpenAPI | Discord | Marketplace


What is Imperal?

Imperal is an AI Cloud Operating System — a complete platform where developers build AI-powered extensions (agents, tools, workflows), users install and use them, and everyone benefits from a shared ecosystem.

Think Shopify for AI agents. You build it. Users install it. The platform handles auth, billing, LLM routing, real-time sync, and everything else.

The SDK is how you build for the platform. One pip install. Five minutes to your first working AI agent.

pip install imperal-sdk

5-Minute Quickstart

imperal init my-agent --template chat
cd my-agent

That generates a complete AI agent:

from pydantic import BaseModel
from imperal_sdk import Extension, ChatExtension, ActionResult

ext = Extension("my-agent", version="1.0.0")
chat = ChatExtension(ext, tool_name="my_agent", description="My first AI agent")


class GreetParams(BaseModel):
    name: str = "World"


@chat.function("greet", description="Greet someone", action_type="read")
async def fn_greet(ctx, params: GreetParams) -> ActionResult:
    """Say hello to someone."""
    return ActionResult.success(
        data={"message": f"Hello, {params.name}!"},
        summary=f"Greeted {params.name}",
    )

Validate it:

imperal validate
# Extension: my-agent v1.0.0
# Tools: 1, Functions: 1, Events: 0
# 0 errors, 0 warnings

Test it:

from imperal_sdk.testing import MockContext

async def test_greet():
    ctx = MockContext(role="user")
    result = await fn_greet(ctx, GreetParams(name="World"))
    assert result.status == "success"
    assert result.data["message"] == "Hello, World!"

What You Get

For Extension Developers

Feature Description
Typed Everything Generic ActionResult[T], Page[T], typed Protocols, Pydantic params — full IDE autocomplete
Machine-Validated Contracts JSON Schema for imperal.json (v1.5.9), ActionResult + Event payloads (v1.5.10), OpenAPI 3.x for Auth Gateway / Registry / Sharelock Cases (v1.5.11). See docs/openapi/.
10 SDK Clients ctx.store, ctx.ai, ctx.billing, ctx.skeleton, ctx.notify, ctx.storage, ctx.http, ctx.config, ctx.extensions, ctx.time
Error Hierarchy ImperalError > APIError > NotFoundError, RateLimitError — catch what you need
MockContext Drop-in test replacement with 10 mock clients. Test without a server.
CLI Tools imperal init, imperal validate, imperal dev — scaffold, validate, develop
Lifecycle Hooks @ext.on_install, @ext.on_upgrade("0.9.0"), @ext.on_uninstall, @ext.health_check
Events System @ext.on_event("deal.created") — subscribe to typed platform events
Webhooks @ext.webhook("/stripe", secret_header="Stripe-Signature") — external HTTP ingestion
Inter-Extension API @ext.expose("get_deal") + ctx.extensions.call("crm", "get_deal") — typed cross-extension calls
UI Contributions Panels, Widgets, Commands, Context Menus, Settings, Themes — declare UI from Python
Validator 12 rules (V1-V12) catch issues before deployment. Claude-friendly fix reports.
Pagination Page[T] with cursor, iteration, auto-pagination — built into every list operation

For the Platform

Feature What It Means
BYOLLM Users bring their own LLM keys. Anthropic, OpenAI, Google, Ollama, any OpenAI-compatible API.
Multi-Model Routing Different models for routing (fast/cheap), execution (accurate), navigation (conversational)
2-Step Confirmation Destructive actions require user approval. Kernel-enforced, not extension-optional.
RBAC + Scopes Fine-grained permissions per user, per extension, per function
Token Economy Built-in billing: token wallet, usage metering, subscription plans, marketplace payouts
Automation Engine Event-driven rules with cron scheduling. Users create "if X then Y" without code.
Self-Hosted Run on your servers. Your data never leaves.

Extension Architecture

@chat.function("create_deal", action_type="write", event="deal.created")
     |
     v
[ Kernel Pipeline ]
     |
     +-- Scope Check (RBAC)
     +-- 2-Step Confirmation (if destructive)
     +-- Execute Function
     +-- Truth Gate (ActionResult.status)
     +-- Event Publishing (automations)
     +-- Action Recording (audit trail)
     |
     v
ActionResult.success(data={"deal_id": "d1"}, summary="Deal created")

Every function call goes through the full kernel pipeline. Security, billing, events — all automatic. You just write the business logic.


SDK Type System

# Generic ActionResult — works with dict or Pydantic models
from pydantic import BaseModel

class Deal(BaseModel):
    id: str
    name: str
    value: float

result = ActionResult.success(data=Deal(id="d1", name="Acme", value=50000), summary="Created")
result.to_dict()  # {"status": "success", "data": {"id": "d1", "name": "Acme", "value": 50000}, ...}

# Cursor-based pagination
page = await ctx.store.query("deals", where={"status": "open"}, limit=20)
for deal in page:  # Page[Document] supports iteration
    print(deal.data["name"])
if page.has_more:
    next_page = await ctx.store.query("deals", cursor=page.cursor)

# Error hierarchy — catch what you need
from imperal_sdk.errors import NotFoundError, RateLimitError
try:
    deal = await ctx.store.get("deals", "nonexistent")
except NotFoundError as e:
    print(f"{e.resource} '{e.id}' not found")  # "deal 'nonexistent' not found"

Multi-Model LLM

Extensions never import LLM libraries directly. The platform handles provider routing, failover, and per-user model preferences.

# Extensions use ctx.ai — the platform routes to the right model
result = await ctx.ai.complete("Summarize this deal", model="")  # uses user's configured model

# Or use the LLM provider directly for advanced use cases
from imperal_sdk import get_llm_provider
provider = get_llm_provider()
resp = await provider.create_message(
    messages=[{"role": "user", "content": "Hello"}],
    purpose="execution",       # routing | execution | navigate
    user_id="imp_u_xxx",       # BYOLLM: uses the user's own API key
)

Supported: Anthropic (Claude), OpenAI (GPT), Google (Gemini), Ollama, vLLM, LM Studio, any OpenAI-compatible API.


System Features

Extensions have access to platform-level capabilities through the SDK. No kernel SDK needed.

Scheduled Tasks (Cron)

@ext.schedule("daily_report", cron="0 9 * * *")
async def daily_report(ctx):
    """Runs every day at 9 AM UTC."""
    stats = await ctx.store.query("metrics", where={"date": "today"})
    await ctx.notify.push(title="Daily Report", body=f"{len(stats)} events today")
    return ActionResult.success(summary="Report sent")

@ext.schedule("hourly_sync", cron="0 * * * *")
async def hourly_sync(ctx):
    """Sync data every hour."""
    data = await ctx.http.get("https://api.example.com/data")
    await ctx.store.create("synced_data", data.json())

Dynamic Scheduling (User-Created Intervals)

For user-driven schedules (e.g., monitors with custom intervals), use a single cron + last_run_at check:

import time

@ext.schedule("monitor_runner", cron="0 * * * *")  # check every hour
async def monitor_runner(ctx):
    """Run monitors that are due based on user-configured intervals."""
    monitors = await ctx.store.query("monitors", where={"active": True})
    now = time.time()
    for m in monitors:
        interval_sec = m["interval_hours"] * 3600  # 1h, 6h, 12h, 24h
        if now - m.get("last_run_at", 0) >= interval_sec:
            await run_scan(ctx, m["id"])
            await ctx.store.update("monitors", m["id"], {"last_run_at": now})

This is the standard production pattern. No ctx.scheduler API needed — the cron trigger + per-record interval check handles any user-configured frequency.

When to use which:

Pattern Use Case
@ext.schedule(cron=...) Fixed intervals: daily reports, hourly syncs, cleanup
Cron + last_run_at Dynamic: user-created monitors, per-item schedules
@ext.on_event(...) Reactive: trigger on events from other extensions

Push Notifications

@chat.function("send_alert", description="Send push notification", action_type="write")
async def send_alert(ctx, params: AlertParams) -> ActionResult:
    await ctx.notify.push(
        title=params.title,
        body=params.message,
    )
    return ActionResult.success(summary=f"Alert sent: {params.title}")

Event System (Cross-Extension)

# Subscribe to events from other extensions
@ext.on_event("mail.received")
async def on_new_email(ctx, event):
    """Triggered when any email arrives."""
    subject = event.data.get("subject", "")
    if "urgent" in subject.lower():
        await ctx.notify.push(title="Urgent email!", body=subject)

# Publish events from your functions
@chat.function("create_deal", action_type="write", event="crm.deal_created")
async def create_deal(ctx, params: DealParams) -> ActionResult:
    deal = await ctx.store.create("deals", params.dict())
    return ActionResult.success(data=deal, summary="Deal created")
    # Platform auto-publishes crm.deal_created event — other extensions can subscribe

System Tray (v1.5.4)

Inject icons, badges, and dropdown panels into the OS top bar:

from imperal_sdk import ui

@ext.tray("unread", icon="Mail", tooltip="Unread messages")
async def tray_unread(ctx, **kwargs):
    count = await ctx.store.count("messages", where={"read": False})
    return ui.Stack([
        ui.Badge(str(count), color="red" if count > 0 else "gray"),
    ])

@ext.tray("alerts", icon="Bell", tooltip="Active alerts")
async def tray_alerts(ctx, **kwargs):
    alerts = await ctx.store.query("alerts", where={"active": True}, limit=5)
    return ui.Stack([
        ui.Badge(str(len(alerts)), color="red"),
        # Dropdown panel — shown when user clicks the tray icon
        ui.List(items=[
            ui.ListItem(id=a["id"], title=a["title"], subtitle=a["severity"])
            for a in alerts
        ]),
    ])

Webhooks (External HTTP)

@ext.webhook("/stripe", method="POST", secret_header="Stripe-Signature")
async def handle_stripe(ctx, headers, body, query_params):
    """Receive Stripe webhook at POST /v1/ext/{app_id}/webhook/stripe"""
    import json
    data = json.loads(body)
    if data["type"] == "payment_intent.succeeded":
        await ctx.store.create("payments", {"amount": data["data"]["object"]["amount"]})
    return {"received": True}

Inter-Extension Calls (IPC)

# Expose a method for other extensions to call
@ext.expose("get_deal", action_type="read")
async def api_get_deal(ctx, deal_id: str) -> ActionResult:
    deal = await ctx.store.get("deals", deal_id)
    return ActionResult.success(data=deal)

# Call another extension's exposed method
result = await ctx.extensions.call("crm", "get_deal", deal_id="d123")

System Prompt Guidelines

Important: Extensions must NOT identify as a specific assistant. The platform injects OS identity automatically.

# WRONG — deploy validation will fail (R10)
chat = ChatExtension(ext, tool_name="my_tool", description="...",
    system_prompt="You are a CRM assistant for Imperal Cloud.")

# CORRECT — describe what the module DOES, not what the AI IS
chat = ChatExtension(ext, tool_name="my_tool", description="...",
    system_prompt="CRM module — manage deals, contacts, and pipelines.")

The kernel injects the AI identity ({assistant_name}) and full platform capabilities into every LLM call. Your system_prompt should only contain module-specific rules and capabilities.


Testing

Every extension is testable without a server:

from imperal_sdk.testing import MockContext

async def test_full_workflow():
    ctx = MockContext(role="admin", config={"api_url": "https://example.com"})

    # MockStore — in-memory, full CRUD
    doc = await ctx.store.create("deals", {"name": "Big Deal", "value": 50000})
    assert doc.id is not None

    page = await ctx.store.query("deals", where={"name": "Big Deal"})
    assert len(page) == 1

    # MockAI — configurable responses
    ctx.ai.set_response("summarize", "This is a big deal worth $50K")
    result = await ctx.ai.complete("Summarize this deal")
    assert "50K" in result.text

    # MockHTTP — register mock endpoints
    ctx.http.mock_get("api.example.com", {"status": "ok"})
    resp = await ctx.http.get("https://api.example.com/health")
    assert resp.ok

    # MockNotify — verify notifications were sent
    await ctx.notify.send("Deal created!", channel="email")
    assert len(ctx.notify.sent) == 1

Validation

$ imperal validate ./my-extension

── Imperal Extension Validator v1.0 ────────────────────

Extension: crm v1.0.0
Tools: 1, Functions: 12, Events: 5

RESULTS: 1 error, 2 warnings

  ERROR  [V5] @chat.function 'create_deal' must return ActionResult
         Fix: Add return type annotation: -> ActionResult

  WARN   [V10] @chat.function 'update_deal' (action_type="write") has no event=
         Fix: Add event='crm.update_deal' to the decorator

  WARN   [V9] No @ext.health_check registered
         Fix: Add @ext.health_check decorator to a health check function

12 rules. Catches type issues, missing annotations, banned imports, missing events. Runs in CI, in CLI, and at kernel load time.


Lifecycle & Events

@ext.on_install
async def setup(ctx):
    """Called once when user installs your extension."""
    await ctx.store.create("settings", {"initialized": True})

@ext.on_upgrade("0.9.0")
async def migrate(ctx):
    """Called when upgrading from 0.9.x."""
    await ctx.store.query("deals")  # migrate data

@ext.health_check
async def health(ctx):
    """Called every 60s. Return health status."""
    return HealthStatus.ok({"connections": 5})

@ext.on_event("email.received")
async def on_email(ctx, event):
    """React to platform events from other extensions."""
    await ctx.notify.send(f"New email: {event.data['subject']}")

@ext.webhook("/stripe", method="POST", secret_header="Stripe-Signature")
async def handle_stripe(ctx, request):
    """Receive webhooks from external services."""
    data = request.json()
    return WebhookResponse.ok({"received": True})

Declarative UI (v1.5.0)

Build full Panel UI from Python — zero React, zero rebuilds. 57 components across 7 modules.

from imperal_sdk import Extension, ui

ext = Extension("inventory", version="1.0.0")

@ext.panel("sidebar", slot="left", title="Inventory", icon="Package",
           default_width=300, refresh="on_event:item.created,item.deleted")
async def panel_sidebar(ctx, **kwargs):
    """Panel handler — returns UINode tree. Auto-discovered by the platform."""
    items = await ctx.store.query("items", limit=50)
    return ui.Stack([
        ui.Header("Inventory", level=3, subtitle=f"{len(items)} items"),
        ui.Button("+ New Item", variant="primary", on_click=ui.Call("create_item")),
        ui.List(
            items=[
                ui.ListItem(
                    id=i["id"], title=i["name"],
                    subtitle=f"Qty: {i['qty']}",
                    badge=ui.Badge("Low", color="red") if i["qty"] < 5 else None,
                    expandable=True,
                    expanded_content=[
                        ui.KeyValue(items=[
                            {"key": "SKU", "value": i["sku"]},
                            {"key": "Price", "value": f"${i['price']}"},
                        ], columns=2),
                        ui.Button("Delete", variant="danger",
                                  on_click=ui.Call("delete_item", item_id=i["id"])),
                    ],
                )
                for i in items
            ],
            searchable=True,
        ),
    ])

55 components:

  • Layout (8): Stack, Grid, Tabs, Page, Section, Row, Column, Accordion
  • Display (9): Text, Header, Icon, Image, Code, Markdown, Divider, Empty, Html
  • Interactive (7): Button, Card, Menu, Dialog, Tooltip, Link, SlideOver
  • Input (11): Input, TextArea, Toggle, Select, MultiSelect, Form, Slider, DatePicker, FileUpload, RichEditor, TagInput
  • Data (11): List, ListItem, DataTable, DataColumn, Stat, Stats, Badge, Avatar, KeyValue, Timeline, Tree
  • Feedback (5): Alert, Progress, Chart, Loading, Error
  • Actions (4): Call, Navigate, Send, Open

Zero-rebuild panel discovery: @ext.panel() auto-publishes to the config store. New extensions show panels instantly — no frontend changes.

v1.5.0 highlights:

  • ui.Html(theme="light") — white-bg email rendering with auto-resize iframe
  • ui.List(selectable=True, bulk_actions=[...]) — multi-select with checkbox hover, bulk action bar
  • ui.List(on_end_reached=action) — infinite scroll with IntersectionObserver sentinel
  • ui.Stack(sticky=True) — pin toolbars to top of scroll container
  • System padding: horizontal Stacks get px-3 py-1 by default

System features: Pagination, infinite scroll, multi-select, bulk actions, drag-drop, hover actions, search, expandable cards, inline editing, collapsible sections — all kernel-enforced


Project Structure

my-extension/
  main.py              # Extension + ChatExtension + @chat.functions
  imperal.json         # Manifest (optional — auto-discovered from code)
  tests/
    test_main.py       # Tests using MockContext
  requirements.txt     # imperal-sdk>=1.0.0


Built by Imperal, Inc.

The AI Cloud OS.

Metadata

Release files for imperal-sdk 1.5.27

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for imperal-sdk 1.5.27
File Size Uploaded
imperal_sdk-1.5.27.tar.gz 347.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for imperal-sdk 1.5.27
File Interpreter ABI Platform
imperal_sdk-1.5.27-py3-none-any.whl Python 3 none any Details

Total release size: 508.5 kB

Release files / imperal_sdk-1.5.27.tar.gz

Download URL imperal_sdk-1.5.27.tar.gz
Size 347.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5e5074d6b0236a98a913cddcc638faf8688eed3c29bb86b7ed5c1889427f8866
BLAKE2b-256 checksum
How to use checksums
e491fd0163bea9ce1e17ed977865224013fe6f3ac072078c064a4ae6ea283a2e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.

Transparency log

Release files / imperal_sdk-1.5.27-py3-none-any.whl

Download URL imperal_sdk-1.5.27-py3-none-any.whl
Size 161.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
82aabe08031519afa9cdf0509ee2e9e9eb624d3096de6b60783786dcfebd5816
BLAKE2b-256 checksum
How to use checksums
1fc903cc9d9f135e179acf45cb17d7443e9ba5ae44846efb879f6fad21824a70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.

Transparency log

Release history Release notifications | RSS feed

6.0.2

2 release files

6.0.1

2 release files

6.0.0

2 release files

5.16.0

2 release files

5.13.1

2 release files

5.13.0

2 release files

5.12.1

2 release files

5.12.0

2 release files

5.11.0

2 release files

5.10.0

2 release files

5.9.22

2 release files

5.9.21

2 release files

5.9.20

2 release files

5.9.19

2 release files

5.9.18

2 release files

5.9.17

2 release files

5.9.16

2 release files

5.9.13

2 release files

5.9.12

2 release files

5.9.11

2 release files

5.9.10

2 release files

5.9.9

2 release files

5.9.8

2 release files

5.9.7

2 release files

5.9.6

2 release files

5.9.5

2 release files

5.9.4

2 release files

5.9.3

2 release files

5.9.2

2 release files

5.9.1

2 release files

5.9.0

2 release files

5.8.2

2 release files

5.8.1

2 release files

5.8.0

2 release files

5.7.3

2 release files

5.7.2

2 release files

5.7.1

2 release files

5.7.0

2 release files

5.6.1

2 release files

5.6.0

2 release files

5.5.1

2 release files

5.5.0

2 release files

5.4.3

2 release files

5.4.2

2 release files

5.4.1

2 release files

5.4.0

2 release files

5.3.0

2 release files

5.2.2

2 release files

5.2.1

2 release files

5.2.0

2 release files

5.1.0

2 release files

5.0.3

2 release files

5.0.2

2 release files

5.0.1

2 release files

5.0.0

2 release files

4.2.16

2 release files

4.2.15

2 release files

4.2.14

2 release files

4.2.13

2 release files

4.2.12

2 release files

4.2.11

2 release files

4.2.10

2 release files

4.2.9

2 release files

4.2.8

2 release files

4.2.7

2 release files

4.2.6

2 release files

4.2.5

2 release files

4.2.4

2 release files

4.2.3

2 release files

4.2.2

2 release files

4.2.1

2 release files

4.2.0

2 release files

4.1.9

2 release files

4.1.8

2 release files

4.1.7

2 release files

4.1.6

2 release files

4.1.5

2 release files

4.1.4

2 release files

4.1.3

2 release files

4.1.2

2 release files

4.1.1

2 release files

4.1.0

2 release files

4.0.1

2 release files

4.0.0

2 release files

3.7.0

2 release files

3.6.0

2 release files

3.5.2

2 release files

3.5.1

2 release files

3.5.0

2 release files

3.4.1

2 release files

3.4.0

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.1

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

This release

1.5.27 This release

2 release files

1.5.26

2 release files

1.5.25

2 release files

1.5.24

2 release files

1.5.23

2 release files

1.5.22

2 release files

1.5.21

2 release files

1.5.20

2 release files

1.5.19

2 release files

1.5.18

2 release files

1.5.17

2 release files

1.5.16

2 release files

1.5.14

2 release files

1.5.13

2 release files

1.5.12

2 release files

1.5.9

2 release files

1.5.8

2 release files

1.5.7

2 release files

1.5.6

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page