Typed WebSocket action and event dispatch with optional framework adapters.
Project description
Beeflow WebSocket
Beeflow WebSocket is a small Python library for action-driven WebSocket communication. It keeps reusable protocol code in beeflow_websocket.core and optional framework adapters under their own packages.
Name
The proposed name is Beeflow WebSocket:
- package distribution:
beeflow-websocket - Python import:
beeflow_websocket - repository directory:
beeflow-websocket
The name is direct because the package owns WebSocket action dispatch, event envelopes, recipient resolution, and optional transport adapters.
Requirements
- Python 3.12 or newer
- uv for all project commands
- no pip workflow
Installation
Core-only usage:
uv add beeflow-websocket
Django Channels usage after publishing the package:
uv add "beeflow-websocket[django]"
FastAPI projects can install the matching optional runtime extra:
uv add "beeflow-websocket[fastapi]"
Flask projects can install the matching optional runtime extra:
uv add "beeflow-websocket[flask]"
Local development from this repository:
uv sync --extra dev
make test-core
make mypy-core
Django adapter development:
uv sync --extra dev --extra django --extra django-dev
make test-django
make mypy-django
FastAPI adapter development:
uv sync --extra dev --extra fastapi --extra fastapi-dev
make test-fastapi
make mypy-fastapi
Flask adapter development:
uv sync --extra dev --extra flask --extra flask-dev
make test-flask
make mypy-flask
Protocol Flow
- A client sends a
WebSocketActionPayloadenvelope. - The framework adapter validates the transport-level shape.
ActionRegistryMetaresolves the action class.- The action yields zero, one, or many event objects.
- The adapter emitter serialises each event to
WebSocketEventPayload. RecipientRegistryMetaresolves logical recipients into concrete WebSocket identifiers.- The framework adapter sends JSON to each resolved WebSocket target.
Minimal Action
from collections.abc import AsyncIterator
from beeflow_websocket.core.action_registry import ActionContext, ActionRegistryMeta
from beeflow_websocket.core.events.health import HealthEvent
from beeflow_websocket.core.payloads import WebSocketActionPayload
class Health(metaclass=ActionRegistryMeta, name="health"):
"""Handle a health-check WebSocket action."""
async def execute(
self,
message: WebSocketActionPayload,
context: ActionContext,
) -> AsyncIterator[HealthEvent]:
"""Yield a response event for the current WebSocket connection."""
yield HealthEvent(
recipient="websocket",
recipient_id=context.websocket_id,
req_id=message.req_id,
)
Django Channels Setup
Add the package to Django settings when using the adapter:
INSTALLED_APPS = [
"channels",
"beeflow_websocket.django",
]
BEEFLOW_WEBSOCKET_PROBLEM_TYPE_BASE_URL = "https://example.com/problems/websocket"
If BEEFLOW_WEBSOCKET_PROBLEM_TYPE_BASE_URL is not configured, error payloads use about:blank as their Problem
Details type.
Include the bundled WebSocket route in your ASGI routing:
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from beeflow_websocket.django.routing import websocket_urlpatterns
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": URLRouter(websocket_urlpatterns),
}
)
The bundled route is ws/. The default consumer accepts only authenticated users.
FastAPI Setup
Install the optional FastAPI extra:
uv add "beeflow-websocket[fastapi]"
Add a WebSocket route and pass the authenticated user id from your own FastAPI dependency:
from fastapi import FastAPI, WebSocket
from beeflow_websocket.fastapi import configure_beeflow_websocket, handle_beeflow_websocket
app = FastAPI()
configure_beeflow_websocket(app, problem_type_base_url="https://example.com/problems/websocket")
@app.websocket("/ws/")
async def websocket_endpoint(websocket: WebSocket) -> None:
await handle_beeflow_websocket(websocket, user_id=1)
The FastAPI adapter handles the current WebSocket connection directly. Cross-connection broadcast or external pub/sub belongs in a separate connection manager.
If the FastAPI app is not configured with a problem type base URL, error payloads use about:blank as their Problem
Details type.
Flask Setup
Install the optional Flask extra:
uv add "beeflow-websocket[flask]"
Add a Flask-Sock WebSocket route and pass the authenticated user id from your own Flask auth layer:
from flask import Flask
from flask_sock import Sock
from beeflow_websocket.flask import configure_beeflow_websocket, handle_beeflow_websocket
app = Flask(__name__)
sock = Sock(app)
configure_beeflow_websocket(app, problem_type_base_url="https://example.com/problems/websocket")
@sock.route("/ws/")
def websocket_endpoint(websocket) -> None:
handle_beeflow_websocket(websocket, user_id=1)
The Flask adapter handles the current WebSocket connection directly. Cross-connection broadcast or external pub/sub
belongs in a separate connection manager. If the Flask app is not configured with a problem type base URL, error
payloads use about:blank as their Problem Details type.
Documentation
English documentation starts at docs/en/README.md.
Polish documentation starts at docs/pl/README.md.
Development
Use uv only:
uv sync --extra dev --extra django --extra django-dev --extra fastapi --extra fastapi-dev --extra flask --extra flask-dev
make test
make mypy
uv build
Release Automation
Every push to master runs .github/workflows/publish.yml. The workflow tests all adapters, runs mypy, builds the
source distribution and wheel, then publishes the built distributions to PyPI through Trusted Publishing.
Pull requests targeting master run .github/workflows/ci.yml, which checks the lockfile, runs tests, runs mypy, and
verifies that distributions build. The workflow also runs pre-commit hooks.
Configure PyPI Trusted Publishing for:
- owner:
beeflow - repository:
beeflow-websocket - workflow:
publish.yml - environment:
pypi
PyPI package versions are immutable. Bump project.version in pyproject.toml before merging changes that should be
published.
The master branch is protected on GitHub. Code changes must go through a pull request and review before they can be
merged. Required pull request checks are Pre-commit, Test, Mypy, and Build.
Manual patch release bump example:
[project]
version = "0.1.1"
Move the relevant changelog entries from [Unreleased] into a dated release section:
## [0.1.1] - 2026-05-03
### Added
- Added FastAPI and Flask adapters.
Verify before merging:
make test
make mypy
uv build
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file beeflow_websocket-0.1.0.tar.gz.
File metadata
- Download URL: beeflow_websocket-0.1.0.tar.gz
- Upload date:
- Size: 92.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
362f6b4b3296dfd7e9795a9b2769bd8eba7ed68ac2175fe9fbf2d4b3aed5f97e
|
|
| MD5 |
f777415863811d6eafe99e3f4b8d36fc
|
|
| BLAKE2b-256 |
c283e8c47c3aebb2fdc309070776f71bfeff081b008aece7c85c8150884a6bb9
|
Provenance
The following attestation bundles were made for beeflow_websocket-0.1.0.tar.gz:
Publisher:
publish.yml on beeflow/beeflow-websocket
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beeflow_websocket-0.1.0.tar.gz -
Subject digest:
362f6b4b3296dfd7e9795a9b2769bd8eba7ed68ac2175fe9fbf2d4b3aed5f97e - Sigstore transparency entry: 1435025329
- Sigstore integration time:
-
Permalink:
beeflow/beeflow-websocket@828cf5ae4b7b11f2625230fda37369a56690a812 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/beeflow
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@828cf5ae4b7b11f2625230fda37369a56690a812 -
Trigger Event:
push
-
Statement type:
File details
Details for the file beeflow_websocket-0.1.0-py3-none-any.whl.
File metadata
- Download URL: beeflow_websocket-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abb8189a0710489b002869b96d8f3eee3e1a84dcd838afbbff1a9e1c015e311f
|
|
| MD5 |
6a5f6c0af47f40412663cf7599c9663e
|
|
| BLAKE2b-256 |
0e8a47517e27aef0cbaa2b02843ce8a188a8ab50f155c908eb0cf6a1d37cc020
|
Provenance
The following attestation bundles were made for beeflow_websocket-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on beeflow/beeflow-websocket
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beeflow_websocket-0.1.0-py3-none-any.whl -
Subject digest:
abb8189a0710489b002869b96d8f3eee3e1a84dcd838afbbff1a9e1c015e311f - Sigstore transparency entry: 1435025440
- Sigstore integration time:
-
Permalink:
beeflow/beeflow-websocket@828cf5ae4b7b11f2625230fda37369a56690a812 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/beeflow
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@828cf5ae4b7b11f2625230fda37369a56690a812 -
Trigger Event:
push
-
Statement type: