Skip to main content

mirastack-agents-sdk

Python SDK for building MIRASTACK agents — the external gRPC plugins that perform READ, MODIFY, and ADMIN actions on platform engineering systems. Agents are pure compute: they receive params via gRPC and use the EngineContext proxy to interact with the engine.

License: GNU AGPL v3 — see LICENSE.

Release Cadence

This SDK ships lockstep with the Go SDK (mirastack-agents-sdk-go) at matching MAJOR.MINOR tags. Every minor or major bump in either SDK forces a paired release of the other so plugin authors writing in either language consume the same engine handshake contract. See CHANGELOG.md for the policy and per-version notes.

All MIRASTACK agents — Python and Go — are required to track the latest paired SDK minor; the engine's CI gate enforces this before each engine release.

Installation

pip install mirastack-agents-sdk

Quick Start

from mirastack_sdk import (
    Plugin, PluginInfo, PluginSchema, Action, IntentPattern,
    Permission, DevOpsStage, ExecuteRequest, ExecuteResponse,
    respond_map, serve,
)

class MyAgent(Plugin):
    def info(self) -> PluginInfo:
        return PluginInfo(
            name="my-agent",
            version="0.1.0",
            description="Example observability agent",
            actions=[
                Action(
                    id="query",
                    description="Query metrics for a service",
                    permission=Permission.READ,
                    stages=[DevOpsStage.OBSERVE],
                    input_params=[{"name": "service", "type": "string", "required": True}],
                ),
            ],
            intents=[
                IntentPattern(pattern=r"query.*metrics|show.*metrics", description="Query metrics", priority=1),
            ],
        )

    def schema(self) -> PluginSchema:
        return PluginSchema(actions=self.info().actions)

    async def execute(self, req: ExecuteRequest) -> ExecuteResponse:
        service = req.params.get("service", "")
        return respond_map({"service": service, "status": "ok"})

    async def health_check(self) -> None: pass

    async def config_updated(self, config: dict) -> None: pass

if __name__ == "__main__":
    serve(MyAgent())

Plugin Interface

class Plugin(ABC):
    def info(self) -> PluginInfo: ...
    def schema(self) -> PluginSchema: ...
    async def execute(self, req: ExecuteRequest) -> ExecuteResponse: ...
    async def health_check(self) -> None: ...
    async def config_updated(self, config: dict[str, str]) -> None: ...

Response Helpers

from mirastack_sdk import respond_map, respond_json, respond_error, respond_raw

return respond_map({"metric": 42.0, "service": "api"})   # typed dict response
return respond_json(my_dataclass)                         # any serialisable type
return respond_error("backend unavailable")               # error response
return respond_raw(b'{"raw": "json"}')                    # raw JSON passthrough

Agent-Specific Features

Actions — Tool Catalog Registration

Action(
    id="restart_service",
    description="Restart a Kubernetes deployment",
    permission=Permission.MODIFY,   # READ | MODIFY | ADMIN
    stages=[DevOpsStage.OPERATE],
    input_params=[
        {"name": "namespace",  "type": "string", "required": True},
        {"name": "deployment", "type": "string", "required": True},
    ],
    output_params=[{"name": "status", "type": "string"}],
)

Intent Patterns — Natural Language Routing

IntentPattern(
    pattern=r"restart.*deployment|rollout.*restart",
    description="Restart a Kubernetes deployment",
    priority=10,
)

Prompt Templates

from mirastack_sdk import PromptTemplate

PromptTemplate(
    name="my_agent_analysis",
    description="Analysis prompt contributed to the engine PromptTemplate Store",
    content="Analyse the following data: {{ data }}",
)

Engine Context

from mirastack_sdk import EngineContext

class MyAgent(Plugin):
    def set_engine_context(self, ctx: EngineContext) -> None:
        self._ctx = ctx

    async def execute(self, req: ExecuteRequest) -> ExecuteResponse:
        url   = await self._ctx.get_config("backend.url")
        await   self._ctx.cache_set("key", "value", ttl=300)
        val   = await self._ctx.cache_get("key")
        await   self._ctx.publish_result({"data": val})
        ok    = await self._ctx.request_approval("Proceed?", Permission.MODIFY)
        await   self._ctx.log_event("action_completed", {"action": "query"})

DateTime Utilities

Convert req.time_range to backend-specific formats — never parse time in a plugin:

from mirastack_sdk import datetimeutils

start = datetimeutils.format_epoch_seconds(req.time_range.start_epoch_ms)  # VictoriaMetrics
start = datetimeutils.format_epoch_micros(req.time_range.start_epoch_ms)   # VictoriaTraces
start = datetimeutils.format_rfc3339(req.time_range.start_epoch_ms)        # VictoriaLogs

SDK Components

Module Purpose
plugin.py Plugin ABC, PluginInfo, Action, IntentPattern, PromptTemplate
context.py EngineContext proxy — config, cache, publish, approval, audit log
respond.py respond_map, respond_json, respond_error, respond_raw helpers
serve.py gRPC server bootstrap — call serve(agent) from __main__
datetimeutils.py Time format converters for all MIRASTACK backends
gen/ Hand-written gRPC proto stubs (will be replaced by buf generate)

Environment Variables

Variable Default Description
MIRASTACK_ENGINE_ADDR localhost:50051 Engine gRPC address
MIRASTACK_PLUGIN_PORT 50052 Port this agent listens on

Tenant Isolation

Every plugin process serves exactly one tenant. The engine launches separate processes per tenant — plugin processes are never shared.

Required Environment Variable

Variable Description
MIRASTACK_PLUGIN_TENANT_SLUG Human-readable slug (e.g. acme). Preferred deployment input; the SDK derives the UUID5 automatically.
MIRASTACK_PLUGIN_TENANT_ID Advanced override. UUID5 of the tenant this plugin serves; wins when both variables are set.

At least one of the two must be set. If both are missing the process exits immediately with a fatal log. This is non-negotiable: a plugin without a tenant identity is unsafe to run.

Registration is lazy after the tenant binding is resolved. The plugin starts its gRPC server and keeps retrying RegisterPlugin while the engine is unavailable, still in bootstrap mode, or missing the bound tenant. Once the operator creates a tenant with the same slug, registration succeeds automatically. The SDK never auto-discovers the first tenant.

How Tenant ID Is Derived

The UUID5 is deterministically derived from the slug:

namespace = UUID("f9f3a4d4-2c64-5b9e-9e25-8a8b6f6f6f6f")
tenant_id = UUID5(namespace, "tenant:" + strings.ToLower(strings.TrimSpace(slug)))

This matches the formula used by mirastack-engine/internal/tenants/id.go so plugin processes and the engine always agree on the tenant identity.

Helper Function

// IDFromSlug derives the tenant UUID5 from a human-readable slug.
// Useful in tests and operator tooling — not needed in normal plugin code.
tenantID := mirastack.IDFromSlug("acme")

Auto-Stamping

The SDK automatically stamps tenant_id on every outbound gRPC call to the engine (config, cache, publish, approval, log, call_plugin, register). Plugin authors must never set tenant_id manually or read it from params.

No Cross-Tenant Calls

When an agent calls another agent via CallPlugin / call_plugin_with_time_range, the SDK stamps the caller's own tenant_id. The engine will reject any cross-tenant call. Federation is out of scope.

Release files for mirastack-agents-sdk 1.11.0

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

Source distribution (sdist)

Source distribution for mirastack-agents-sdk 1.11.0
File Size Uploaded
mirastack_agents_sdk-1.11.0.tar.gz 55.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mirastack-agents-sdk 1.11.0
File Interpreter ABI Platform
mirastack_agents_sdk-1.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 108.6 kB

Release files / mirastack_agents_sdk-1.11.0.tar.gz

Download URL mirastack_agents_sdk-1.11.0.tar.gz
Size 55.6 kB
Tags Source
SHA-256 checksum
How to use checksums
3ab9d60a8aea5a6fe027a73f723192ef030b64e6fb92dea3f00024a7b42d017c
BLAKE2b-256 checksum
How to use checksums
7e6e13eb83a7a31b33f1ff2a317b0d11882572a5bc882c0088f07fc06e2ecf69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 10, 2026.

Transparency log

Release files / mirastack_agents_sdk-1.11.0-py3-none-any.whl

Download URL mirastack_agents_sdk-1.11.0-py3-none-any.whl
Size 53.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8dc38323e6bd0f34618f3980b95d161555b7a5c71ceb705f0fd6e19d88f9ab0e
BLAKE2b-256 checksum
How to use checksums
16f1557e48b80f4ae857c6af4fe3a8b2f8670fbd29cc1aa4abdb58f10a2ade28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.11.0 This release

2 release files

1.10.0

2 release files

1.8.0

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.4.1

2 release files

1.3.0

2 release files

1.2.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