Skip to main content

asgion

CI Coverage PyPI Python License

ASGI protocol inspector and trace engine. Catch subtle protocol violations your tests miss — before they hit production.

Why asgion?

ASGI apps can pass all tests while still violating the protocol:

  • Sending response body before http.response.start
  • Writing to a closed WebSocket connection
  • Exiting without completing a streaming response
  • Returning malformed event payloads

Frameworks catch some of this. asgion validates the full ASGI contract — state machines, event schemas, scope fields, and semantic constraints across HTTP, WebSocket, and Lifespan.

Highlights

  • Full ASGI contract validation — 163 rules across HTTP, WebSocket, and Lifespan
  • Trace engine — record every receive()/send() with nanosecond timestamps and inline violation markers
  • CI-ready — deterministic exit codes and JSON output
  • CLI, Python API, pytest plugin — fits any workflow
  • Zero runtime dependencies — pure Python 3.12+
  • O(1) per message — safe for hot paths, no overhead when tracing is off

Works with any ASGI app: FastAPI, Starlette, Litestar, Django (ASGI), or bare ASGI handlers.

Quickstart

Get started in under a minute:

pip install asgion[cli]

Given a buggy app that sends body before http.response.start:

# myapp.py
async def app(scope, receive, send):
    if scope["type"] == "http":
        await send({"type": "http.response.body", "body": b"oops"})       # wrong order
        await send({"type": "http.response.start", "status": 200, "headers": []})
        await send({"type": "http.response.body", "body": b"hello"})

Check finds protocol violations:

asgion check myapp:app
CHECK  myapp:app

── GET / ─────────────────────────────────────────────────────────
  [HF-002] error: http.response.body sent without preceding http.response.start
    hint: Send http.response.start before any http.response.body
  [SEM-002] info: No Content-Type header on 2xx response
    hint: Responses with a body should include a Content-Type header

2 violations (1 error, 1 info)  |  709µs

What is HF-002? Look up any rule directly:

asgion rules HF-002
RULE  [HF-002] error
  http.response.body sent without preceding http.response.start
    hint: Send http.response.start before any http.response.body

  layer: http.fsm
  applies to: http

Trace shows the full event timeline for the same app:

asgion trace myapp:app
TRACE  GET / (88µs, TTFB 54µs)

        26µs  send     http.response.body  4 bytes  ← HF-002 (error)
        54µs  send     http.response.start  200  (+28µs)  ← SEM-002 (info)
        75µs  send     http.response.body  5 bytes  (+21µs)

  Events: 3  |  Violations: 2 (1 error, 1 info)
asgion trace myapp:app --min-severity error   # only error-level markers
asgion trace myapp:app --out ./traces/        # save as JSON files

Filter, export, target specific endpoints:

asgion check myapp:app --select "HF-*" --min-severity warning
asgion check myapp:app --path /api/users --path "POST:/api/users" -H "Content-Type: application/json"
asgion check myapp:app --format sarif --out report.sarif   # GitHub Code Scanning
asgion check myapp:app --format junit --out report.xml     # Jenkins / GitLab CI

Bootstrap a config file:

asgion init              # creates .asgion.toml with commented-out defaults
asgion init --pyproject  # prints [tool.asgion] block to stdout

Exit codes: 0 = clean, 1 = violations (--strict), 2 = runtime error. See asgion check --help. App exceptions and timeouts are reported but do not affect exit codes — only protocol violations do.

Note: asgion check myapp:app imports your module and drives the ASGI app. All application dependencies (FastAPI, SQLAlchemy, etc.) must be installed in the same environment as asgion.

See the full rule list for all 163 rules and their descriptions.

Python API

from asgion import Inspector

inspector = Inspector(app)
# ... drive the app via httpx, TestClient, etc. ...
assert inspector.violations == []  # fails if any protocol violation occurred

With tracing:

inspector = Inspector(app, trace=True)
async with httpx.AsyncClient(transport=ASGITransport(inspector)) as client:
    await client.get("/api/users")

record = inspector.traces[0]
record.scope.method      # "GET"
record.scope.path        # "/api/users"
record.summary.ttfb_ns   # time to first byte (ns)

As middleware:

from asgion import inspect

uvicorn.run(inspect(app))

Pytest Plugin

Integrate protocol validation directly into your test suite:

pip install asgion[pytest]
async def test_my_app(asgi_inspect):
    inspector = asgi_inspect(my_app)
    async with httpx.AsyncClient(transport=ASGITransport(inspector)) as client:
        await client.get("/users")
    assert inspector.violations == []
pytest --asgi-strict   # auto-check all tests

CI Integration

GitHub Action

# .github/workflows/asgion.yml
name: ASGI Check
on: [push, pull_request]
jobs:
  asgion:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ack1d/asgion@v0
        with:
          app: myapp:app
          strict: true
          format: sarif

pre-commit

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/ack1d/asgion
    rev: v0.6.0  # update with: pre-commit autoupdate
    hooks:
      - id: asgion
        args: [myapp:app, --strict]  # args is required — specify your app target

pre-commit runs in an isolated virtualenv — asgion can only validate raw ASGI apps that have no external imports. For apps with dependencies, use the CLI or GitHub Action instead.

Configuration

Via pyproject.toml, .asgion.toml, or Python API. See configuration docs and full rule list.

[tool.asgion]
profile = "recommended"
exclude_rules = ["SEM-006"]

Contributing

git clone https://github.com/ack1d/asgion.git
cd asgion
uv sync --group dev
uv run pytest

If you have Task installed: task check runs lint, typecheck, and tests.

License

MIT

Metadata

Release files for asgion 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for asgion 0.6.1
File Size Uploaded
asgion-0.6.1.tar.gz 49.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for asgion 0.6.1
File Interpreter ABI Platform
asgion-0.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 116.2 kB

Release files / asgion-0.6.1.tar.gz

Download URL asgion-0.6.1.tar.gz
Size 49.0 kB
Tags Source
SHA-256 checksum
How to use checksums
58f9538a3d610b1da22f1bd2dc3e36ddb2da8e25d98777d0c676cf408a53fdd1
BLAKE2b-256 checksum
How to use checksums
4ffaecc954e18f03208331e0711334ef2d4f218c72439759380544cb367b721a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 16, 2026.

Transparency log

Release files / asgion-0.6.1-py3-none-any.whl

Download URL asgion-0.6.1-py3-none-any.whl
Size 67.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b697477cdf3599a7c02753177834df0da3f8dd1a0fcd2c502ca9299665f07750
BLAKE2b-256 checksum
How to use checksums
c93c70123d20806d559c6ca117a5a1459284aaa994e62942caba9b868e1909b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page