Runtimes

Python Runtime

The Python runtime is an independent implementation of the AppTheory contract — not a port of the Go runtime. It executes the 271 generic runner fixtures in the 273-vector corpus, including the SP09 MCP tier, SP12 OAuth tier, and SP13 objectstore tier; the two Go/CDK-TS MCP route/facade tables are explicitly 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.

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 271 generic fixtures in the 273-vector corpus on every commit. It includes the SP09 MCP tier, SP12 OAuth tier, and SP13 objectstore tier; the nested route-algebra and facade-inventory tables are consumed only by Go and CDK-TS. Tests live under py/tests/ and are exercised by ./scripts/verify-python-tests.sh and make rubric.

Next reads