Request inference
Choose an agent provider and model, then request or stream inference.
On this page
Choose a provider and model
Start with registry discovery below to choose an agent provider. For the request examples, complete wallet setup in the agent quickstart, then insert each fragment inside its with Client.from_config(...) as client: block using the same provider, model and retained configuration.
Choose an agent provider from the ERC-8004 registry. Pass its registered ID as an integer, or its HTTPS origin as a string, to Client.from_config. The SDK resolves the registration, reads the models and verifies their registry bindings.
Agent providers publish their models, prices and capabilities. Choose an exact model ID from that offering. The inference engine determines which payload fields it supports.
Find agent providers through ERC-8004
The registry is the directory. An agent provider publishes an ERC-8004 identity, an MPPI service endpoint and a model catalogue under mppi.catalog. Agents can discover the offering without contacting its operator.
- Find registered offerings. Index
MetadataSetevents for themppi.catalogkey in the selected network's ERC-8004 registry to obtain agent provider IDs. - Read the current offering. Resolve each ID's
agentURIand currentmppi.catalogmetadata. The registration document identifies the MPPI endpoint; the catalogue supplies model IDs and token prices. - Connect with the SDK. Pass the chosen ID to
Client.from_config. The SDK reads current registry data and verifies the endpoint and model documents before paid work.
In SDK 0.1.6, your application supplies the registry index and selected ID; the SDK handles that ID's resolution and verification. The mppi-agent CLI provides onboarding. It does not yet include a command to list agent providers.
Understand and accept prices
Rate / Meaning
- Input
- Uncached input tokens, priced per million tokens.
- Output
- Generated output tokens, priced per million tokens.
- Cache · optional
- Cached input, a subset of input. An absent cache price differs from an explicit zero.
Display prices in USDC per million tokens. Raw catalogue rates are decimal strings containing six-decimal USDC base units per million tokens: a display price of 1 USDC is "1000000" in the rate field.
Every signed request binds its model and accepted catalogue hash. Those prices remain fixed for that admitted run. If new work encounters PRICE_CHANGED, inspect the new catalogue and explicitly accept its hash before submitting a fresh request. Existing funded sessions can use a newly accepted catalogue.
# new_hash is the reviewed 32-byte catalogue hash.
accepted = client.accept_catalog(new_hash)Send a request
from mppi_agent import Client
with Client.from_config(
"https://YOUR_PROVIDER",
testnet=True,
initial_session_tokens=10_000,
) as client:
response = client.chat.completions.create(
model="YOUR_PROVIDER/MODEL",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.decode("utf-8"))Complete · typed gRPC envelope
Session · run · model · accepted prices · signature
Output JSON + Terminal return on Complete. Vouchers, meters and Receipt travel on Control.
create serializes the request fields to JSON. The typed envelope binds model and stream mode to that payload. Responses remain original JSON bytes; the SDK does not replace them with a proprietary response object.
Read streaming output
with client.chat.completions.create(
model="YOUR_PROVIDER/MODEL",
messages=[{"role": "user", "content": "Hello"}],
stream=True,
) as stream:
for payload in stream:
print(payload.decode("utf-8"))
print(stream.terminal)
print(stream.receipt)Each payload is an original JSON object after the provider consumes any upstream framing. The MPPI wire is not SSE. Successful iterator completion requires a valid COMPLETED Terminal and gRPC OK trailers. Receipt and Terminal travel on separate streams, so their delivery has no cross-stream ordering guarantee.
Closing the stream cancels that request and releases its local resources. It neither proves the provider stopped immediately nor closes the funded session. Final usage still needs a definitive provider report.
Preserve an existing JSON payload
payload = b'{"model":"YOUR_PROVIDER/MODEL","stream":false,"messages":[{"role":"user","content":"Hello"}]}'
response = client.chat.completions.create_raw(
payload, model="YOUR_PROVIDER/MODEL", stream=False,
)create_raw preserves the original UTF-8 JSON bytes. Its explicit model and stream values must match the JSON. Supply a valid JSON object with supported provider fields; validation rejects ambiguous or malformed input.
Handle failures and uncertainty
A failure before admission creates no usage for that run, even if a voucher already authorized a ceiling. An admitted upstream error with definitive usage can have a FAILED Terminal and valid payment accounting; gRPC OK in that case means the transport delivered the application outcome.
A timeout, disconnect or missing final record does not prove that no work occurred. Retain the original run and operation evidence. Recover accounting through the same session when possible; recovery does not replay inference or recreate missing output.
If the provider restarts or the Control stream is lost, nothing reattaches in the background. The next request, or sessions.open, reattaches first; if the provider is still unavailable, that call fails and a later one tries again. sessions.get only reports readiness, so send the next request instead of waiting for it.