MPPI provider SDK for Python
Version 0.2.0 supports explicit Arc mainnet and testnet selection with validated configuration, discovery, exact payment
arithmetic, canonical chain evidence and native Complete/Control services.
await Mppi.from_config(...) composes these services from the native CLI's saved
configuration, the packaged official Arc profile for the selected network and
the existing Circle operator. The provider owns its inference integration and hosting.
uv pip install 'mppi-provider==0.2.0'
Start with the provider quickstart to install the native CLI, generate declarations, onboard and attach the SDK. Linux ARM64 has a native CLI release binary; Python providers use that same CLI for wallet selection, recipient binding and catalog publication. The quickstart also covers a locked Cargo source build. The shared protocol dependency installs automatically with this Python package.
The wallet reference covers custom adapters
and registry operations. Earlier 0.1.0 integrations passed live Arc testnet
registration, recipient binding, catalog publication, capture and close. See the
official release record
for that evidence's exact artifact and security scope.
from mppi_provider import CatalogRow, Rates, publish_catalog
catalog = publish_catalog([CatalogRow("example/model", Rates(input=1_000_000, output=3_000_000))])
The provider supplies counts, requirements and definitive outcomes. MPPI computes and validates their payment meaning. Catalog publication here produces bytes; it does not make a registry transaction. Pure calculation helpers return immutable results. The runtime retains live payment state and signals the provider's execution hook when further work is no longer authorized.
See SDK interface definitions and the protocol profile.
The runtime reference includes configuration, HTTP host integration and evidence requirements.
Upgrading from 0.1.2
0.2.0requiresmppi-protocol==0.1.4, which installs with it. A0.1.2integration ran on protocol0.1.1, so protocol0.1.3's non-additive changes apply too:CircleAgentWallet(chain=..., address=..., checkpoint_path=...)replaces thewalletandimplementationpins, andsupported_account_pinsis gone;OpeningEvidenceandClosingEvidencecarryobservationinstead ofblock, andChainReader.agent_wallettakes that observation. See the protocol package notes.- The
mppiCLI and this package read and write the same<config>.wallet-operations.json. Upgrade both to0.2.0together:0.1.2of either refuses a journal0.2.0has saved. The journal's lock is now held only while the journal is read or replaced, never across a Circle call, somppi provider updatecan run while the host serves. An execute or reconcile waits for that lock up to the adapter'stimeout_seconds(240 by default). Within one process an adapter runs one operation at a time, CLI commands included, so an operation may also wait behind another's command. - The
ProviderSessionsProtocol has a new member,recover_current(evidence). A host class written against it without that member no longer type-checks: a type checker reports the missing member where the class is used asProviderSessions, and refuses to instantiate a class that subclasses the Protocol without implementing it. At run time such a subclass inherits the Protocol's stub, which returnsNone. Implement the method, or forward it to the SDK'ssessions.recover_current. await Mppi.from_config(..., wallet=operator_wallet)composes the runtime with anyTransactionWallet. Setup checks its address against the saved operator and verifies the deployment and USDC domain; the wallet's own account, network and access are its own to check, so call aCircleAgentWallet'sverify_wallet()before passing it. Withoutwallet=, the Circle path is unchanged.- A wallet may have three optional members the runtime uses when present, so
the
TransactionWalletProtocol is unchanged:retire(*, operation_refs, at)receives references the runtime no longer needs, with the Unix time from which they may be forgotten, which a laterreconcileof the reference, or its record gaining a transaction hash, withdraws; anear_capacityproperty has each rise reported as anon_errorHookError; andmax_call_bytes(default 61,440, the Circle adapter's bound) sizes each batch the runtime builds. The runtime may now callexecuteandreconcilefor different operations at once, from several threads: a custom wallet serializes its own records, as both Circle adapters do, one operation at a time. The wallet requirements state everything the runtime assumes of a wallet. - A session closed on chain leaves the runtime after
closed_retentionseconds (24 hours by default, set onMppiorMppi.from_config), andHooks(on_session_retired=...)receives its id. No session count limits openings. ASessionOpenfor a closed session the runtime no longer holds, and a recovery from a record thatRecoveryEvidence.is_final()reports final once the chain shows the session closed, are refusedSESSION_NOT_READY/SESSION_CLOSED. Pass such final records torecoverat startup rather than skipping them: their refusal hands the wallet each reference only they still name, if the wallet'sreconcileof it agrees with the record: the same reference, the same transaction hash or none on both, and the same wallet operation id when the record names one. Maintenance makes the same check before it hands over a reference no wallet answer in this process has matched (one restored without a transaction hash, or kept against an answer that disagreed); every other hand-over makes no wallet call first. - Collections: a batch fits the wallet's
max_call_bytes, at most 136 sessions for Circle, and maintenance splits the rest; a host's ownsessions.settleBatchover it is refused before any intent is recorded. A close mined and reverted is prepared again under a successor of its reference (<reference>.1,.2, …), at most once per settlement interval, and sent only once the successor simulates: a failed simulation sends nothing, and aclosecall then fails with its error. A settlement or close that never began (aFAILEDresult with neither a transaction hash nor a wallet operation id) is restored from a checkpoint asFAILED, so the live rules prepare it again. - A session's waiting runs are admitted in the order they first waited, while
each voucher arrives within the runtime's turn;
0.1.2could admit a later run first. Hooksgainson_session_retiredandon_timingafter its0.1.2fields, so positional construction is unchanged.on_timingreceives anOperationTimingfor each request's admission and each settlement or close, in milliseconds: the host's coverage callback, chain reads, the wallet's call and waiting.- An exception other than
UpstreamFailurefrom the host's coverage callback reaches the agent asSTATE_UNAVAILABLE, without its text. Recovery refusals name the check that failed:SESSION_NOT_READY: <check>. An invalid run or voucher signature in the evidence still raisesValidationError(INVALID_VALUE), now with that message; a run whose model has no rates in its catalog is refusedSTATE_UNAVAILABLE, where0.1.2raisedKeyError.
Embedded provider runtime
The usual Circle composition is:
from mppi_provider import Mppi
sdk = await Mppi.from_config(
"mppi.toml",
testnet=True,
rpc_env="ARC_RPC_URL_TESTNET",
coverage=prepare_required_tokens,
execution=execute_and_report,
)
Run this on the serving event loop. The helper verifies the saved operator and
selected deployment, uses the authenticated Circle Agent Wallet CLI and the
original onboarding wallet-operation record, and constructs the wallet, chain
follower and contract calls.
rpc_env="ARC_RPC_URL_TESTNET" selects a trusted RPC environment variable;
profile=load_profile(Path("trusted-profile.json")) selects an explicit
trusted profile using mppi_protocol.deployment.load_profile. With
testnet=True, the default profile is packaged official testnet; the RPC comes
from the validated configuration unless rpc_env is supplied. It starts no
listener or inference job. The host owns runtime startup, its server and shutdown.
wallet=operator_wallet composes another TransactionWallet instead of the
Circle one, such as one whose key an HSM or KMS holds; setup checks its address
against the saved operator but cannot verify its account, network or access.
For custom integrations, the explicit constructor remains available.
Construct mppi_provider.runtime.Mppi(config, chain=..., contract=..., wallet=..., coverage=..., execution=...) on the serving event-loop thread. Supply:
ProviderConfig: validated applied declarations and provider-selected timings.ChainFollower: the shared follower of the selected verified deployment. Its freshness and collection-margin timings must equal the validated config.ContractCalls: the same MPPI domain and verified USDC funding domain.TransactionWallet: the configured provider operator's execution capability.coverage: an async callable(PreparedRequest, RunContext) -> TokenCounts. Return the prepared prefill bound and at least the configured actual output buffer; preparation performs no paid inference.execution: an async iterator callable(PreparedRequest, RunContext, ProviderRuns, asyncio.Event) -> AsyncIterator[bytes]. It yields original JSON objects after the provider removes any upstream framing.
Unauthenticated Control setup expires after 60 seconds. The optional constructor
keyword control_auth_timeout sets a positive timeout in seconds, up to 3,600.
Only successful signed session attachment removes this deadline; challenges and
opening notices do not extend it. Authenticated Control streams may remain open.
This server policy is independent of payment.authorization_wait_ms and applies
even when a client omits its own RPC deadline.
The execution integration uses report_usage(context, cumulative_counts) and
report_terminal(context, final_counts, RunStatus) to supply facts. MPPI measures
no tokens. A definitive final must follow actual provider-reported termination;
iterator EOF, a disconnect and a cancellation signal do not substitute for it.
For an upstream application error, report definitive FAILED usage when known and
raise UpstreamFailure(original_json_bytes, http_status=...).
require_coverage(context, remaining_tokens) requests a complete desired remaining
bound at the admitted run prices. It grants only when the combined session target
fits the accepted voucher and confirmed deposit. An already larger reservation
is retained. Only definitive final accounting releases unused coverage. During
ordinary decode, report usage early enough for asynchronous voucher renewal,
then request the next rolling output bound before consuming unreserved work.
A rejected grant sets the event passed to execution. The provider terminates
its actual job and reports final usage; a later voucher does not restart it.
Pass mppi_protocol.wire.GRPC_OPTIONS when creating the host's grpc.aio.server.
Call register_grpc(server) before starting that server, then await start() and
check its Readiness. Publish discovery(path) responses through the host's
HTTP stack on the same HTTPS origin. The host supplies TLS credentials, ingress
and listener lifecycle. MPPI starts no listener and does not serve keyed /v1.
An unavailable chain at startup returns not-ready while the follower retries.
Discovery and the first-use baseline become available only after fresh identity
evidence arrives; an outage does not establish empty session history.
sessions.settle(id) captures cumulative actual usage and keeps the session open.
sessions.close(id) preserves close intent, requests termination and verifies
canonical closure before returning a confirmed result. Pending/unknown calls
retain their original transaction identity; repeated calls reconcile it. The
close intent has its own reference, which a retry of a close mined and
reverted replaces with its successor; confirming an earlier capture does not
report that close as confirmed. The
background schedule groups collection requests into batches that fit the
wallet's optional max_call_bytes (61,440 bytes by default, at most 136
sessions; see the runtime reference). settleBatch(session_ids)
simulates the exact ordered call before wallet submission and reconciles each
target independently. Unknown submission outcomes preserve their original
identity; they never trigger a replacement capture.
Call shutdown(deadline) with an absolute serving-loop monotonic deadline.
It stops new grants, signals execution, processes available final reports and
returns unresolved runs/operations. The caller stops its own gRPC server.
Shutdown does not initiate escrow closure or invent final reports.
Payment-state ownership and recovery
One Mppi instance holds the authoritative live payment state for its sessions.
Its Complete and Control handlers may receive different backend connections;
socket equality grants no authority. The provider must ensure every operation
uses that same authoritative state. Independent processes do not share payment
state through this SDK. Routing, worker coordination, durability and recovery
remain provider responsibilities.
A newly observed opening after startup can create first-use state under that
ownership requirement. A historical opening after restart cannot establish zero
usage. await sessions.checkpoint(session_id) exports detached
RecoveryEvidence for provider-owned retention. await sessions.recover(evidence)
revalidates the supplied run proofs, exact prices, accounting, reservations and
canonical chain evidence before installing state. Missing private history returns
STATE_UNAVAILABLE; invalid recovery leaves existing state unchanged. Recovery
requires fresh Control authentication and never resumes old execution.
Unresolved old execution prevents a ready replacement attachment.
RecoveryEvidence.is_final() marks a closed session's record with nothing left
to recover: recovery refuses it, but pass it at startup all the same, since the
refusal hands to retirement each reference it names that the wallet's own
record agrees with. The runtime retires a closed session after
closed_retention seconds (24 hours by default) and limits no session count.
A known opening before its first authenticated attachment can be checkpointed at generation zero. This private evidence has no accepted voucher, usage, runs or reservations and remains unready. The provider must retain complete history; zero on-chain settlement alone cannot establish that it was unused. Recovery preserves any refund-only close intent and assigns no owner. Fresh authentication creates generation one; generation-zero snapshots are never valid on Control.
Wallet adapters must durably bind an operation reference to its exact intended call and retain available wallet/transaction identifiers. These requirements do not add a provider database. The shared Circle Agent Wallet adapter retains its wallet-operation record, while each application owns its payment-state retention. The native CLI and registry helpers provide onboarding and submission.
Lifecycle observers
Pass hooks=Hooks(...) to the runtime/client for typed lifecycle observations.
on_timing reports where each admission and collection spent its time. See the
hook payloads, ordering and bounds.
License
Copyright 2026 MPPI contributors. Licensed under the Apache License, Version 2.0.
Metadata
Release files for mppi-provider 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mppi_provider-0.2.0.tar.gz | 118.8 kB | Without provenance | Details for mppi_provider-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mppi_provider-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for mppi_provider-0.2.0-py3-none-any.whl |
Total release size: 182.1 kB
Release files / mppi_provider-0.2.0.tar.gz
| Download URL | mppi_provider-0.2.0.tar.gz |
|---|---|
| Size | 118.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49b5b03b8eb450d0fdffc93b96fce6f86ffe78d2786dc205c84955a3eb14283a
|
|
BLAKE2b-256 checksum How to use checksums |
56d3a0ef4fb6405bacaa7943a5d93e0018332580d082d59f99ac21efe63cda95
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mppi_provider-0.2.0-py3-none-any.whl
| Download URL | mppi_provider-0.2.0-py3-none-any.whl |
|---|---|
| Size | 63.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6eee320c73ff1008660136b1a3d4b26aee1f18bfa2eeeb60f36c4d10d7ce9e46
|
|
BLAKE2b-256 checksum How to use checksums |
adf8d28d9b4626d85a3322bc98bb3f574636cb1f53a4f1807cb36f61bf42266b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for mppi-provider 0.2.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.