Python Runtime
The Python runtime is an independent implementation of the AppTheory contract — not a port of the Go runtime. It executes the 275 generic runner fixtures in the 287-vector corpus, including the SP09 MCP tier, SP12 OAuth tier, and SP13 objectstore tier; the Python suite also loads the shared MCP route-algebra expectations table and the M2 auth-facade acceptance tables and the two M3a provider/store conformance tables (JWKS validator, OIDC discovery bootstrap, route challenge, provider conformance, and store conformance). The remaining three CDK-facing facade tables (facade route-inventory, route-model, and transport-posture) are outside Python’s scope.
Install
Distribution is GitHub Releases only. PyPI is not used; AppTheory does not publish to it. Pin the release wheel and verify its checksum before installing it:
VERSION=1.14.0
TAG="v${VERSION}"
REPO="theory-cloud/AppTheory"
gh release download "${TAG}" --repo "${REPO}" \
--pattern "apptheory-${VERSION}-py3-none-any.whl" \
--pattern "SHA256SUMS.txt" \
--clobber
grep " apptheory-${VERSION}-py3-none-any.whl$" SHA256SUMS.txt | sha256sum -c -
python -m pip install "./apptheory-${VERSION}-py3-none-any.whl"
Python 3.12+ is required. The floor is pinned by py/pyproject.toml, Ruff, Pyright, the pinned TableTheory GitHub
Release wheel metadata, and CI. Do not document a different Python floor unless scripts/verify-runtime-floor-claims.sh
passes with a CI matrix that includes both the floor and Python 3.14.
Module layout
| Module | Purpose |
|---|---|
apptheory |
Core Python runtime exports: create_app, Context, request/response helpers, event builders, testkit helpers, MCP/OAuth helpers, jobs-ledger primitives, logging profiles, object-store helpers, and sanitization helpers. Rate-limiter classes are not root exports. |
apptheory.mcp |
Streamable HTTP MCP server, registries, session/stream/task stores, SSE parsing, and deterministic test harness helpers. |
apptheory.oauth |
Protected-resource metadata, bearer-token validation, DCR, PKCE, and Remote MCP OAuth helper surfaces. |
apptheory.limited |
DynamoDB-backed rate limiter exports (DynamoRateLimiter, FixedWindowStrategy, SlidingWindowStrategy, MultiWindowStrategy). |
See api-snapshots/py.txt for the exact exported surface — that file is the release gate.
Minimal app
from apptheory import create_app, text
app = create_app()
@app.get("/ping")
def ping(ctx):
return text(200, "pong")
def handler(event, ctx):
return app.handle_lambda(event, ctx)
handle_lambda is the single Lambda entrypoint for every AWS event shape. See Event Shape Dispatch for the dispatch table.
Tier selection
from apptheory import create_app
app = create_app(tier="p0")
Python tiers are string literals: "p0", "p1", or "p2".
See HTTP Runtime for what each tier includes.
Deterministic tests
from datetime import datetime, timezone
from apptheory import build_apigw_v2_request, create_test_env, text
def test_ping():
env = create_test_env(now=datetime(2026, 1, 1, tzinfo=timezone.utc))
env.ids.push("req-1")
app = env.app()
app.get("/ping", lambda ctx: text(200, "pong"))
event = build_apigw_v2_request("GET", "/ping")
resp = env.invoke_apigw_v2(app, event)
assert resp["statusCode"] == 200
Route registration
app.handle("GET", "/users/{id}", handler)
app.get("/users/{id}", handler)
Normal fluent registration fails closed on invalid patterns, duplicates, and None handlers. handle_strict remains as
a deprecated compatibility wrapper for callers that still need the old helper shape; it now raises AppTheoryError
rather than ValueError for registration failures.
Object-store dependency posture
The Python package intentionally keeps boto3 optional and lazy for create_s3_object_store. Importing apptheory or
using the fake object store does not require boto3; constructing the S3-backed store fails closed with a stable
ObjectStoreError if boto3 or the required S3 methods are unavailable. This differs from TypeScript’s hard S3 SDK
dependency by design and does not widen the object-store contract.
The S3-backed store also exposes the bounded upload grant (ObjectStoreUploadGranter#presign_put). Because botocore’s
bundled S3 service model defaults to signature version s3, AppTheory constructs the boto3 client with
Config(signature_version="s3v4"): a SigV2 presigned URL does not sign content-length at all and hoists
content-type and x-amz-checksum-sha256 into the query string. The store additionally re-verifies every presigned URL
and fails closed with ObjectStoreError(objectstore.invalid_store_config) if the constraints are not signed headers.
HTTP error format
from apptheory import create_app, HTTP_ERROR_FORMAT_FLAT_LEGACY
app = create_app(http_error_format=HTTP_ERROR_FORMAT_FLAT_LEGACY)
Applies to HTTP error serialization only.
What’s verified
The Python runner passes all 275 generic fixtures in the 287-vector corpus on every commit. It includes the SP09 MCP tier, SP12 OAuth tier, and SP13 objectstore tier; the Python suite also loads the shared MCP route-algebra expectations table and the M2 auth-facade acceptance tables and the two M3a provider/store conformance tables (JWKS validator, OIDC discovery bootstrap, route challenge, provider conformance, and store conformance), while the facade route-inventory, route-model, and transport-posture tables are consumed by Go and CDK-TS. Tests live under py/tests/ and are exercised by ./scripts/verify-python-tests.sh and make rubric.
Next reads
- API Reference
- HTTP Runtime tiers
- MCP Method Surface — transport and JSON-RPC method contract
- Contract Fixtures