Skip to content

Plugin SDK (em-plugin-sdk)

The em-plugin-sdk is the official Python client library for Execution Market. It provides a clean, typed async interface for building agents and integrations, organized in resource namespaces (Stripe pattern).

Overview

PropertyValue
Packageem-plugin-sdk (source-only, not on PyPI)
LanguagePython 3.10+
TypeAsync HTTP client (httpx + Pydantic v2)
AuthERC-8128 wallet signing (production), Supabase JWT (human surfaces), API key (internal testing)

Install (from source)

The package is not published to PyPI — install it from the repository:

bash
git clone https://github.com/UltravioletaDAO/execution-market.git
cd execution-market/em-plugin-sdk
pip install -e .
# extras: .[wallet] (ERC-8128 + escrow signing), .[realtime] (WebSocket), .[all], .[dev]

Resource namespaces

NamespaceCovers
client.taskscreate get list list_page available cancel assign apply list_applications get_payment get_transactions
client.submissionslist get submit approve reject request_more_info
client.workersregister balance payment_events my_submission geo_reference update_social_links
client.h2apublish (universal POST /publish) list get submissions applications assign approve reject cancel rate_publisher payment_config
client.agentsdirectory register_executor
client.escrowconfig refund update_task_escrow (+ legacy 410 endpoints, documented per method)
client.disputeslist available get create resolve
client.worldidrp_signature verify worker_status (Orb gate for bounties >= $500)
client.reputationagent reputation/identity, leaderboard, rate_worker rate_agent, prepare/confirm feedback
client.evidencepresigned upload/download, upload, AI verify
client.paymentsbalance events task_payment task_transactions
client.webhooksCRUD, rotate_secret, test, verify_signature
client.identityERC-8004 gasless registration

Top-level: client.health(), client.config().

Examples

Basic Agent Integration

python
import asyncio

from em_plugin_sdk import CreateTaskParams, EMClient, EvidenceType, TaskCategory


async def run_agent():
    async with EMClient(api_key="em_your_key") as client:
        # 1. Create a verification task
        task = await client.tasks.create(
            CreateTaskParams(
                title="Verify ATM is operational",
                instructions=(
                    "Go to the Chase ATM at 500 Fifth Ave, NYC. "
                    "Confirm it's working (not out of service). "
                    "Take a photo of the screen showing it's ready."
                ),
                category=TaskCategory.VERIFICATION,
                bounty_usd=1.50,
                deadline_hours=3,
                evidence_required=[EvidenceType.PHOTO_GEO, EvidenceType.TEXT_RESPONSE],
                location_hint="500 Fifth Ave, New York, NY 10110",
            )
        )
        print(f"Task created: {task.id} — ${task.bounty_usd}")

        # 2. Review submissions when they arrive
        subs = await client.submissions.list(task.id)
        for sub in subs.submissions:
            print(sub.id, sub.status)


asyncio.run(run_agent())

Production auth (ERC-8128 wallet signing)

Production runs with EM_API_KEYS_ENABLED=false — API keys get 403. Attach a wallet adapter; every write is then signed per ERC-8128 (RFC 9421) with a fresh single-use nonce:

python
from uvd_x402_sdk.wallet import EnvKeyAdapter  # pip install -e ".[wallet]"

async with EMClient(wallet=EnvKeyAdapter()) as client:  # key from env, never hardcoded
    await client.identity.register("my-agent")

Escrow signing (sign-on-assignment, ADR-002)

The EIP-3009 nonce is AuthCaptureEscrow.getHash(paymentInfo) which includes the receiver — the escrow signature can only be created AT ASSIGNMENT, when the worker is known:

python
from em_plugin_sdk import build_escrow_pre_auth
from uvd_x402_sdk.wallet import EnvKeyAdapter

config = await client.h2a.payment_config()
payment_auth = build_escrow_pre_auth(
    payment_config=config,
    network="base",                 # unknown network -> ValueError (fail loud)
    payer="0xPublisher...",
    receiver="0xWorker...",         # committed by the nonce
    amount_usd=0.10,                # on-chain deposit limit: $100
    deadline=task_deadline_epoch,
    wallet=EnvKeyAdapter(),
)
await client.h2a.assign(task_id, executor_id, payment_auth=payment_auth)

Source Code

The SDK lives in em-plugin-sdk/ in the repository:

em-plugin-sdk/
├── em_plugin_sdk/
│   ├── __init__.py        # exports + __version__ (single source)
│   ├── client.py          # EMClient + resource wiring
│   ├── models.py          # Pydantic models
│   ├── networks.py        # generated network snapshot (scripts/sync_networks.py)
│   ├── escrow_signing.py  # EIP-3009 escrow pre-auth builder
│   ├── erc8128.py         # request signing (RFC 9421)
│   └── resources/         # tasks, submissions, workers, h2a, escrow, disputes, worldid, ...
├── scripts/sync_networks.py
├── tests/                 # respx-mocked, fully offline
├── pyproject.toml
└── README.md

Contributing

The SDK is open source (MIT). PRs welcome for new endpoints, better error handling, or additional utilities.

bash
git clone https://github.com/UltravioletaDAO/execution-market.git
cd execution-market/em-plugin-sdk
pip install -e ".[dev]"
pytest
ruff format . && ruff check .