Python SDK
Package maeyr on PyPI — the agent runtime, API client, and dev tooling. Preinstalled on platform workers.
Install
pip install maeyr
# optional: validation CLI + pytest helpers
pip install "maeyr[dev]"Source and changelog: github.com/maeyr/maeyr-sdk. Monorepo copy: maeyr-workspace/maeyr-sdk.
Platform feature coverage
Typed sub-clients cover the main product workflows. For a newly added public endpoint that does not yet have a convenience method, client.request() keeps the same authentication, tenant headers, retries, timeouts, and typed error handling.
| Product surface | SDK entry point | Coverage |
|---|---|---|
| Auth and tenancy | client.auth | Login, refresh, profile, usage, sessions, API/worker keys, organizations, and projects |
| Agents and Vault | client.builder | Agent CRUD, revisions, builds, deploys, reconciliation, secrets, mappings, and MCP servers |
| Chat and triggers | client.chat | Conversations, streaming, execution control/debug, generation, triggers, and approvals |
| Endpoint execution | client.pulse | Typed synchronous execution and fire-and-forget agent invocation |
| Workflows | client.workflow | Workflow CRUD, clone, rerun, execute, and full execution lifecycle |
| Schedules | client.scheduler | Create, list, update, pause, resume, delete, and run-now |
| Marketplace | client.marketplace | Agent/workforce listings, publishing, search, installation, and publisher profiles |
| Webhooks and MCP | WebhookClient / McpClient | Public webhook invoke/stream plus hosted MCP tool discovery and calls |
Exact routes and payloads are available in the REST API reference.
Agents, builds, and deployments
Manage the complete agent lifecycle. Build and deploy start asynchronous platform work; read the agent status until it reaches a terminal state. Deletion is also reconciled — only a result with complete=true is finished.
# Inspect, build, deploy, and reconcile an agent
agent = await client.builder.agents.get("AI-...")
await client.builder.deploy.build(agent["agent_id"])
await client.builder.deploy.deploy(agent["agent_id"])
await client.builder.deploy.reconcile(agent["agent_id"])
# Paginate without writing skip/limit loops
async for agent in client.builder.agents.iter_all(search="weather"):
print(agent["agent_name"], agent.get("deploy_status"))Endpoint execution and streaming
Pulse runs typed agent endpoints. Chat helpers route natural-language requests and expose incremental SSE events. Endpoint paths use agent_alias.module.function.
from maeyr.models.executor import AgentType, EndpointExecutionRequest
result = await client.pulse.execute(
EndpointExecutionRequest(
agent_id="AI-...",
agent_type=AgentType.CLOUD,
endpoint="weather.main.forecast",
inputs={"city": "Bengaluru"},
)
)
# Streaming helpers yield decoded SSE JSON objects
async for event in client.chat.stream_indent_finder(
"Run the weather forecast for Bengaluru",
conversation_id="CI-...",
):
print(event)Triggers, schedules, approvals, and webhooks
Create event-driven and scheduled automation, run tests, inspect histories, and resolve human approval tasks. Public webhook helpers intentionally use a webhook token instead of a user JWT.
# Triggers
trigger = await client.chat.triggers.create({
"name": "Order created",
"event_type": "webhook",
"workflow_id": "WI-...",
})
async for event in await client.chat.triggers.test(trigger["trigger_id"]):
print(event)
# Reuse schedule_id when retrying an ambiguous create
schedule = await client.scheduler.create(
{"name": "Daily report", "cron": "0 9 * * *", "workflow_id": "WI-..."},
schedule_id="daily-report-v1",
)
await client.scheduler.run_now(schedule["schedule_id"])
# Human approvals
pending = await client.chat.approvals.list(status="pending")
await client.chat.approvals.decide("AP-...", {"decision": "approved"})# Public webhooks do not use a user JWT
webhook = MaeyrClient.webhook("TR-...", webhook_token="wh_...")
await webhook.invoke({"event": "order.created", "order_id": "123"})
async for event in webhook.stream({"event": "order.created"}):
print(event)Retries, idempotency, and custom endpoints
Transient connection failures and HTTP 429, 502, 503, and 504 use exponential backoff. Reuse the same idempotency key, schedule ID, or request object when a timeout leaves the outcome unknown; a new key can create duplicate work.
from maeyr import MaeyrClient
from maeyr.client import ClientConfig, RetryConfig
client = MaeyrClient(
access_token="eyJ...",
config=ClientConfig(
timeout=30,
retry=RetryConfig(max_retries=5, backoff_factor=0.5),
idempotency_key="create-agent-weather-v1",
),
)
# Use the hardened transport for a public route not wrapped yet
status = await client.request("GET", "/worker", "/cloud-worker/status")Hosted MCP and stdio bridge
Prefer a direct remote MCP connection with an mcp_ token. Use the bridge only for clients that support stdio but cannot connect to a remote MCP server. Python integrations can use McpClient.from_env() to list and call tools.
python -m pip install "maeyr[mcp]"
export MAEYR_MCP_TOKEN="mcp_..."
# Stdio-only clients; remote MCP clients should connect to the gateway directly
maeyr-mcp-bridge \
--base-url "https://api.maeyr.com" \
--agent-alias weather_agentAgent runtime (maeyr.runtime)
The same import works everywhere — the dashboard editor, local development, and CI. The SDK is preinstalled on platform workers; never vendor a Maeyr.py file.
from typing import Any, Dict
from maeyr.runtime import mcp_endpoint, MaeyrAuth, MaeyrAuthError
@mcp_endpoint(description="Look up a record by id")
async def get_record(payload: Dict[str, Any]) -> Dict[str, Any]:
record_id = payload.get("record_id")
try:
token = MaeyrAuth.require_param("api_bearer", "token")
except MaeyrAuthError as exc:
return {"ok": False, "error": str(exc)}
# use token in httpx/aiohttp — never log secrets
return {"ok": True, "id": record_id}# One import everywhere — platform editor and local dev:
from maeyr.runtime import mcp_endpoint, MaeyrAuth, MaeyrAuthError
# The maeyr SDK is preinstalled on platform workers.
# For local development: pip install maeyr
# (Nothing is injected anymore — never vendor a Maeyr.py in your repo.)- @mcp_endpoint — marks an async tool; description is shown to planners and validators.
- MaeyrAuth — reads vault-backed secrets as
method_id.param_nameenv vars. See Auth & credentials. - MaeyrAuthError — raised when a required auth method or param is missing; return structured errors from endpoints instead of bare tracebacks when possible.
- context() — read A2A correlation metadata on agent-to-agent calls (optional).
Step-by-step agent authoring: Creating agents, Endpoints.
Development tooling (maeyr.devtools)
Run the same manifest checks the platform uses before build/deploy: required main.py, endpoint names, @mcp_endpoint on each declared function, async + single payload argument, and input/output references.
# Validate agent.json + embedded main.py before deploy
maeyr-agent-validate ./my-agent/
# Or from Python
from maeyr.devtools import validate_agent_manifest, AgentValidationError
validate_agent_manifest(manifest_dict) # raises AgentValidationErrorPlatform HTTP client (MaeyrClient)
Call Maeyr REST APIs from scripts, automation, or backends. Distinct from MaeyrAuth inside agents (external API keys). Supports JWT, project API keys, and login; base_url is configurable for staging and self-hosted gateways.
from maeyr import MaeyrClient
# JWT (console or prior login)
async with MaeyrClient(
access_token="eyJ...",
org_id="org-id",
project_id="project-id",
base_url="https://api.maeyr.com",
) as client:
me = await client.auth.me()
# Project API key
client = MaeyrClient.from_api_key("vk_...", validate=True)
# Email / password
client = await MaeyrClient.from_login("[email protected]", "password")
# Environment: MAEYR_API_KEY | MAEYR_ACCESS_TOKEN | MAEYR_EMAIL+MAEYR_PASSWORD
client = MaeyrClient.from_env()REST surface: API reference. Platform sign-in (SSO): Authentication.
Typed API errors
HTTP failures map to exceptions such as MaeyrNotFoundError, MaeyrValidationError, and MaeyrRateLimitError, with parsed FastAPI detail and optional request_id. Retries and JWT refresh are configurable.
from maeyr import MaeyrClient, MaeyrNotFoundError, MaeyrValidationError
try:
await client.builder.agents.get("missing")
except MaeyrNotFoundError as e:
print(e.status_code, e.detail_message, e.request_id)
except MaeyrValidationError as e:
print(e.details)Example agent in the SDK repo
examples/aviation_agent/main.py — multiple @mcp_endpoint handlers with MaeyrAuth.require_param for an external API key.