This release is a pre-release and may not be stable for production use.
Forge SDK for Python
forgeintel-sdk (import forgeintel) brings Forge telemetry, agent context and
feedback to x402 services running FastAPI, Starlette, or another ASGI app.
Python 3.11+. Beta source package; not yet published to PyPI.
# From this repository
python -m pip install ./packages/sdk-python
import os
from fastapi import FastAPI
from forgeintel import Forge, ForgeMiddleware
app = FastAPI()
# Install your x402 payment middleware here, FIRST.
forge = Forge(
api_key=os.environ["FORGE_API_KEY"],
backend_url="https://api.forgeintel.co/api/sdk/v2",
public_url="https://api.example.com",
)
# Starlette runs the LAST added middleware FIRST.
app.add_middleware(ForgeMiddleware, forge=forge)
See the complete runnable merchant in examples/fastapi.
Plain ASGI: app = forge.wrap(app). Use one Forge instance per application/event
loop. ASGI lifespan shutdown flushes and closes Forge automatically. When lifespan
is disabled, call await forge.shutdown() in your application's shutdown hook.
What ships
- x402 v1 JSON challenges /
X-PAYMENTand v2PAYMENT-REQUIRED/PAYMENT-SIGNATURE/PAYMENT-RESPONSE. Existing payment terms and merchant extensions, including Bazaar, remain intact. - Locally signed feedback IDs, byte-compatible with the TypeScript SDK and Forge v2 collector. IDs, response decoration and context parsing need no Forge network round trip on the merchant request path. This is not a payment processor: the existing x402 middleware still verifies and settles payments.
- Background discovery, challenge and interaction telemetry with the same header allowlist as TypeScript. AgentCash, awal and pay.sh hints reach the backend, where caller classification and generic-traffic filtering happen.
- Agent context required on paid requests when enabled and stripped before merchant validation, in JSON bodies or query parameters. Configured independently from feedback.
- Feedback ID header, optional JSON body fields and optional plain-text trailer; structured feedback in v2 challenge and successful settlement extensions.
- Public feedback form, GET rating, POST rating with note, cached summary. Only these explicit rating/summary routes await the Forge backend. The backend owns rating idempotency and the correction window.
- OpenAPI 3.0–3.2 / Swagger 2.0 JSON enrichment. Shared schema components remain untouched. Composed schemas are conservatively header-only; JSON/YAML that cannot be safely enriched is served unchanged.
- Bounded event queue (1,000), batches (100), 5-second delivery timeout, retry after failure, diagnostics and a bounded shutdown flush. Best-effort delivery, not durable storage; separate queues per worker. Requires an asyncio event loop.
Options
All option names use Python snake_case; pass keyword arguments to Forge or a
ForgeOptions dataclass. The Python beta deliberately supports the core options,
not TypeScript's custom tone/wording overrides.
| Option | Default | Behavior |
|---|---|---|
api_key, backend_url, public_url |
required | Merchant credentials, collector and public service URL. Never infer URLs from Host. Use the /api/sdk/v2 collector URL; an origin-only backend URL selects /v1. |
feedback |
True |
Feedback IDs, prompts and routes. False retains telemetry with an internal interaction UUID. |
base_path |
/feedback |
Free feedback routes; must not collide with merchant routes. |
agent_context |
True |
Require context on paid requests. AgentContextOptions(search_query=False) requires only the agent name; False disables context. Legacy required=False is ignored. |
describe_challenges, challenge_extension, receipt_extension |
True |
Feedback additions on x402 challenges/receipts. |
inject_body, rate_hint |
True |
Paid JSON object fields and rating sentence. |
inject_text |
False |
Opt-in trailer on paid text/plain responses. |
openapi |
True |
Boolean or OpenAPIOptions(paths=("/openapi.json",), document=None, is_paid_operation=None). Document can be a dict or sync/async provider. |
ttl_ms |
86400000 |
Must match backend feedback TTL. |
flush_interval_ms |
2000 |
Background event flush interval. |
strict |
False |
Raise on invalid options in CI; otherwise disable Forge and leave the API unchanged. |
on_error |
logging warning | Optional error callback; callback failures are isolated. |
Forge(..., http_client=client) accepts a caller-owned httpx.AsyncClient for
custom transports/testing. The caller closes an injected client.
from forgeintel import AgentContextOptions, OpenAPIOptions
forge = Forge(
api_key="ffk_...",
backend_url="https://api.forgeintel.co/api/sdk/v2",
public_url="https://api.example.com",
agent_context=AgentContextOptions(search_query=True),
# FastAPI doesn't infer 402 responses from payment middleware. Declare them
# on paid routes, or explicitly select the paid operations here.
openapi=OpenAPIOptions(is_paid_operation=lambda method, path, op: path == "/weather"),
)
Required context rejects payment-bearing requests with HTTP 400 before x402
processing. It requires a listed agent_type and search_query (direct when no
search was used), unless search_query=False. Initial unpaid challenges,
inspection and feedback routes remain available. This mode is opt-in.
JSON requests are read up to 1 MiB. Optional mode replays oversized, compressed or invalid bodies unchanged; use query parameters for those bodies. Required mode rejects unreadable JSON. Binary uploads are never buffered by Forge. Agent context is still stripped when collection is disabled, where the body can be inspected.
JSON responses are rewritten only when bounded to 1 MiB (5 MiB for OpenAPI).
Unknown-length multi-chunk streams, SSE, compressed bodies, partial responses and
binary files remain unchanged; successful paid responses still receive the ID
header. Forge removes stale validators when it changes bytes and preserves repeated
headers such as Set-Cookie. No feedback is injected into redirects or errors.
For strict response schemas, provide OpenAPIOptions(document=app.openapi) or a
static document and call forge.enrich_openapi(app.openapi()) before serving
traffic. Otherwise schema-aware body injection starts after the first spec fetch.
For a mounted app or reverse-proxy root_path such as /api, configure public paths: base_path="/api/feedback" and OpenAPIOptions(paths=("/api/openapi.json",), ...).
Place Forge inside response compression and outside payment middleware. Framework
exceptions propagate normally; Forge never retries a merchant handler.
Development
python -m venv packages/sdk-python/.venv
packages/sdk-python/.venv/bin/pip install -e './packages/sdk-python[test]'
packages/sdk-python/.venv/bin/python -m pytest packages/sdk-python/tests
packages/sdk-python/.venv/bin/python -m build packages/sdk-python
Tests include the real x402==2.5.0 FastAPI middleware and client, with a fake
facilitator (no funds spent), ASGI streaming/body limits and shared TypeScript ID
vectors. Live merchant rollout and PyPI publication are separate release steps.
MPP and Flask/WSGI are deferred.
Release files for forgeintel-sdk 0.1.0b1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| forgeintel_sdk-0.1.0b1.tar.gz | 31.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| forgeintel_sdk-0.1.0b1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.7 kB
Release files / forgeintel_sdk-0.1.0b1.tar.gz
| Download URL | forgeintel_sdk-0.1.0b1.tar.gz |
|---|---|
| Size | 31.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dc74f01b543319f2be44b740eb2ecec540c12e4444c856fd55a526728508670c
|
|
BLAKE2b-256 checksum How to use checksums |
356989abb1c19d4172377ab48806dd0e5b55a21e9f08770c838cc51819d5fe52
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|
Release files / forgeintel_sdk-0.1.0b1-py3-none-any.whl
| Download URL | forgeintel_sdk-0.1.0b1-py3-none-any.whl |
|---|---|
| Size | 26.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d6ed47a0b81605cdee367c5a2e34fe934b94ed9235816402ca2028f453753dfc
|
|
BLAKE2b-256 checksum How to use checksums |
3515a2fd98687bb34e426174bd7e297bc68eabca7c117188c2a26c4d9f17e877
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.0
|