Skip to main content

L402 Lightning payment middleware for Python — async wrap_with_l402 wrapper for agent tools (CrewAI, AutoGen, LangChain Python). Sibling of @powforge/langchain-l402-middleware on npm.

Project description

powforge

Lightning payment middleware for Python agent tools.

You wrote a CrewAI / AutoGen / LangChain tool. Someone is going to call it a thousand times an hour, burn your OpenAI credits, and walk away. You want the call to cost them 21 sats so they only run it when they actually need the answer.

from powforge.l402 import wrap_with_l402

async def query_market(symbol: str) -> dict:
    # your real tool here
    return {"symbol": symbol, "price": 100_000}

gated = wrap_with_l402(
    query_market,
    lnbits_url="https://lnbits.example",
    lnbits_api_key="invoice-or-admin-key",
    sats_amount=21,
)

# First call — no payment proof yet.
unpaid = await gated("BTC")
# {'error': 'payment_required', 'invoice': 'lnbc210n1...', 'payment_hash': '...', 'sats': 21, 'next_step': '...'}

# Pay the bolt11. Then call again with the payment_hash.
paid = await gated("BTC", "payment-hash-from-above")
# {'symbol': 'BTC', 'price': 100000}

That's it. Your tool now charges 21 sats per call.

Why

LLM agents are economic actors. They will retry, fan out, and brute-force any free tool you expose. A 21-sat Lightning gate makes runaway loops self-limiting: the bill grows linearly with calls, and the agent's wallet caps the blast radius before your wallet does.

Install

pip install powforge

Python 3.9+. The only runtime dependency is httpx for async HTTP.

API

wrap_with_l402(fn, **cfg)

Wraps an async (or sync) callable. Returns:

async def wrapped(raw_input, payment_proof: str | None = None) -> Any

Two calling conventions — agent frameworks vary in whether they let you pass two args to a tool callback. Both work:

# Two-arg form
result = await gated("BTC", "payment-hash")

# Envelope form — for single-arg frameworks (CrewAI Tool, LangChain Python)
envelope = json.dumps({
    "__payment_proof__": "payment-hash",
    "__tool_input__": "BTC",
})
result = await gated(envelope)

Config:

arg required default notes
lnbits_url yes* LNBits instance base URL
lnbits_api_key yes* Invoice key (read scope sufficient)
sats_amount no 10 Price per call
ttl_seconds no 600 Paid-cache TTL. None = forever
memo no "powforge-l402" Invoice memo
state no fresh Share a PaymentState across wrappers

* unless you inject create_invoice_fn + check_paid_fn directly (useful for tests or non-LNBits backends).

create_l402_tool(name=..., description=..., func=..., **cfg)

Returns a {"name", "description", "func"} dict shaped for direct registration as a CrewAI Tool / AutoGen function tool / LangChain DynamicTool's Python equivalents. The func is the L402-gated async callable; the calling framework awaits it.

Payment flow

  1. Caller invokes the wrapped function with no payment_proof.
  2. Wrapper mints a Lightning invoice via POST /api/v1/payments.
  3. Wrapper returns a 402-style dict:
    {
      "error": "payment_required",
      "invoice": "lnbc210n1...",
      "payment_hash": "...",
      "sats": 21,
      "next_step": "Pay the invoice, then re-call with the payment_hash as payment_proof."
    }
    
  4. Caller pays the bolt11 with any Lightning wallet.
  5. Caller re-invokes with the payment_hash as proof.
  6. Wrapper verifies via GET /api/v1/payments/<hash>, caches the result for ttl_seconds, and runs the wrapped function.

The hash is the receipt. In the canonical L402 macaroon spec the proof is the 32-byte preimage; this package accepts the simpler hash form because LNBits' read endpoint takes the hash, and the wrapper still verifies it against LNBits before unlocking the call. Callers who need cryptographic preimage proof should use the macaroon-flavored L402 gates instead.

Family

This package is the Python sibling of the npm packages:

  • @powforge/langchain-l402-middleware — LangChain.js
  • @powforge/semantic-kernel-l402 — Semantic Kernel JS
  • @powforge/mcp-tool-l402 — MCP per-tool wrapper
  • @powforge/mcp-l402-gate — full macaroon flow
  • @powforge/paymcp-l402-provider — paymcp BasePaymentProvider

Same envelope shape across all of them.

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

powforge-0.1.0.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

powforge-0.1.0-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file powforge-0.1.0.tar.gz.

File metadata

  • Download URL: powforge-0.1.0.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for powforge-0.1.0.tar.gz
Algorithm Hash digest
SHA256 45a8866a163fe344fa7f1a3ac73275e4d076b45321f21caa0d4348505a05c45e
MD5 08f1350709ba8061a1e8cca08de38b99
BLAKE2b-256 7661957c99481c69fada93982a56519b68645c5a9af9b48bf6e8a294d451b4ca

See more details on using hashes here.

File details

Details for the file powforge-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: powforge-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for powforge-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a5ccbc2f78c44be5ef017ea7552521c59a6c038674841d8acbd4256323a8376d
MD5 28be457f2e35757ac625878cf20b2dc5
BLAKE2b-256 bdf98550a90daaa941ea6b917551203714c6ee6a45691093972c2dac628067ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page