Skip to content

feat: bill payments for single-shot live runner calls #3955

Description

@rickstaa

What we need

A way to bill payments for single-shot live runner calls. Single-shot mode is functional but unpaid today: a single-shot runner registers with a price and is advertised in /discovery, but ProxyLiveRunnerSingleShot serves the call for free. We want single-shot (request/response and short lived) calls to actually charge, so batch style apps on the network are paid.

Current state

  • Single-shot route /apps/{runner_id}/app/{app_path...} (server/ai_http.go:103) maps to ProxyLiveRunnerSingleShot (server/ai_http.go:568), which reserves a session, proxies, and releases, with no payment: no 402 challenge, no ProcessPayment, no metering.
  • The persistent path ReserveLiveRunnerSession (server/ai_http.go:205) is the only fully paid path. It gates on a 402, calls ProcessPayment, and runs a background LivePaymentProcessor ticker (-livePaymentInterval, 5s default) that meters wall clock time and debits a prepaid balance. The request/response examples (hello-world, vllm in https://github.com/livepeer/live-runner-example-apps) currently ride this path and are billed by held open wall clock time, which over charges short calls.
  • The price field is generic. Fee is pricePerUnit / pixelsPerUnit * quantity, so the same PriceInfo covers any unit. For live runners the quantity is elapsed nanoseconds (pixelsPerUnit = 1e9, wei per nanosecond). Single-shot can reuse this field as is; the only thing to decide is what quantity it meters. No new price field is needed.

Billing model & failed calls

Both options reuse the existing PriceInfo; they differ only in the metered quantity and the trust/failure tradeoff:

  • Per used compute (metered) — quantity = elapsed nanoseconds, consistent with the per second model (feat(ai/runner): per-second live runner pricing (remove 720p pixel scaling) #3952). Only actual compute is billed, so failed jobs are not charged fully. This matters most for single-shot, where payment is taken upfront in one shot. Cost: assumes the orchestrator is truthful and does not slow walk work to inflate billed time.
  • Flat per call — quantity = one unit per call; the runner declares a price per call. No slow walk attack angle since billing does not depend on measured compute, but you pay more upfront even when the request fails.

SDK surface

Add a paid single-shot entry point that targets /apps/{runner}/app/{path} and skips reserve_session / stop_runner_session, reusing the inline 402 loop that call_runner already implements.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions