Streamblocks
Real-time extraction and processing of structured blocks from text streams.
LLMs often embed structured data in their responses: file operations, code blocks, tool calls. Streamblocks extracts these blocks in real-time as the stream arrives, emitting events like BLOCK_START, BLOCK_CONTENT_DELTA, and BLOCK_END. Process a Gemini stream, detect !!save:file\npath/to/file.py\n!!end blocks, and react immediately, no need to wait for the full response.
Table of Contents
- Features
- Installation
- Quick Start
- More Examples
- Built-in Syntaxes
- Event Types
- Optional Extras
- Documentation
- Development
- Contributing
- License
Features
- Pluggable Syntax System: Define your own block syntaxes or use built-in ones
- Async Stream Processing: Process text streams line-by-line with full async support
- AI Provider Adapters: Automatic adapter detection for Gemini, OpenAI, Anthropic
- AG-UI Protocol Support: Bidirectional adapters that consume AG-UI streams and emit AG-UI events
- Type-Safe Models: Use Pydantic models for block metadata and content
- Event-Driven Architecture: React to block detection, updates, completion, and rejection
- Production Ready: Comprehensive error handling, logging, and validation
Installation
pip install streamblocks
Quick Start
import asyncio
from streamblocks import BlockRegistry, DelimiterPreambleSyntax, StreamBlockProcessor, EventType
from streamblocks.content import FileOperationsContent, FileOperationsMetadata
async def main():
registry = BlockRegistry()
syntax = DelimiterPreambleSyntax(
metadata_class=FileOperationsMetadata,
content_class=FileOperationsContent,
)
registry.register_syntax(syntax, block_types=["files_operations"])
processor = StreamBlockProcessor(registry)
async def text_stream():
yield "!!file01:files_operations\n"
yield "src/main.py:C\n"
yield "!!end\n"
async for event in processor.process_stream(text_stream()):
if event.type == EventType.BLOCK_END:
print(f"Block extracted: {event.block_id}")
asyncio.run(main())
More Examples
Processing AI Provider Streams
from google import genai
from streamblocks import StreamBlockProcessor
client = genai.Client(api_key="...")
response = await client.aio.models.generate_content_stream(
model="gemini-2.5-flash",
contents="Create a Python script",
)
# Adapter auto-detected for Gemini streams
async for event in processor.process_stream(response):
match event.type:
case EventType.BLOCK_START:
print(f"Block started: {event.block_id}")
case EventType.BLOCK_END:
print(f"Block complete: {event.block_id}")
Event Handling Pattern
async for event in processor.process_stream(stream):
match event.type:
case EventType.STREAM_STARTED:
print("Processing started")
case EventType.TEXT_DELTA:
print(event.delta, end="")
case EventType.BLOCK_START:
print(f"\n[Block {event.block_id} detected]")
case EventType.BLOCK_CONTENT_DELTA:
print(event.delta, end="")
case EventType.BLOCK_END:
print(f"\n[Block {event.block_id} complete]")
case EventType.STREAM_FINISHED:
print("\nDone")
Using Markdown Frontmatter Syntax
from streamblocks import MarkdownFrontmatterSyntax
syntax = MarkdownFrontmatterSyntax(
metadata_class=CodeBlockMetadata,
content_class=CodeBlockContent,
)
registry.register_syntax(syntax, block_types=["python", "javascript"])
# Detects blocks like:
# ```python
# ---
# name: example
# ---
# print("hello")
# ```
Built-in Syntaxes
| Syntax | Format | Use Case |
|---|---|---|
| Delimiter with Preamble | !!<id>:<type>\n...\n!!end |
Simple structured blocks |
| Markdown with Frontmatter | ```lang\n---\nkey: value\n---\n...\n``` |
Code blocks with metadata |
| Delimiter with Frontmatter | !!start\n---\nkey: value\n---\n...\n!!end |
Hybrid structured blocks |
Event Types
Lifecycle Events
STREAM_STARTED- Stream processing beganSTREAM_FINISHED- Stream processing completedSTREAM_ERROR- Stream processing failed
Text Events
TEXT_CONTENT- Complete text content outside blocksTEXT_DELTA- Incremental text chunk
Block Events
BLOCK_START- Block header detectedBLOCK_HEADER_DELTA- Block header line receivedBLOCK_METADATA_DELTA- Metadata line receivedBLOCK_CONTENT_DELTA- Content line receivedBLOCK_METADATA_END- Metadata section completeBLOCK_CONTENT_END- Content section completeBLOCK_END- Block fully extractedBLOCK_ERROR- Block extraction failed
Custom
CUSTOM- User-defined event
Optional Extras
Streamblocks provides optional extras for AI provider integrations:
| Extra | Dependencies | Purpose |
|---|---|---|
gemini |
google-genai | Google Gemini stream processing |
openai |
openai | OpenAI stream processing |
anthropic |
anthropic | Anthropic Claude stream processing |
agui |
ag-ui | AG-UI protocol adapters |
all-providers |
All above | All AI provider integrations |
# Single provider
pip install streamblocks[gemini]
# Multiple providers
pip install streamblocks[gemini,openai]
# All providers
pip install streamblocks[all-providers]
Documentation
To build and serve the documentation locally:
uv sync --group doc
brew install d2 # diagrams are rendered with d2 at build time
uv run mkdocs serve
The documentation is served at http://127.0.0.1:7227.
Development
Dependency Groups
| Group | Purpose | Key Dependencies |
|---|---|---|
dev |
Development tools | pytest, ruff, basedpyright, detect-secrets |
doc |
Documentation building | mkdocs, mkdocs-material, mike |
Installation
Basic development setup:
uv sync --group dev
source .venv/bin/activate
lefthook install
Full development setup with extras:
uv sync --group dev --all-extras
Quick Reference
Available extras: gemini, openai, anthropic, all-providers
Available groups: dev, doc
Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=hother.streamblocks --cov-report=html
# Run examples
uv run python examples/run_examples.py --skip-api
Release Process
This project uses python-semantic-release for fully automated versioning and releases. Every commit to the main branch is analyzed using conventional commits, and releases are created automatically when needed.
How It Works
- Commit with conventional format to the
mainbranch - GitHub Actions automatically analyzes commits, determines version bump, creates tag, updates changelog, publishes to PyPI, and creates GitHub release
- Documentation is automatically deployed when a release is published
Version Bumping Rules
| Commit Type | Version Bump | Example |
|---|---|---|
feat: |
Minor | 0.5.0 → 0.6.0 |
fix:, perf:, refactor: |
Patch | 0.5.0 → 0.5.1 |
feat!:, BREAKING CHANGE: |
Major | 0.5.0 → 1.0.0 |
docs:, chore:, ci:, style:, test: |
No release | - |
Documentation Deployment
Documentation is automatically built and deployed when:
- A release is published (triggered by semantic-release)
- Changes are pushed to
docs/,mkdocs.yml, or the workflow file onmain
Development Practices
Branching & Pull Requests
Each git branch should have the format <tag>/item_<id> with eventually a descriptive suffix.
We use a Squash & Merge approach.
Conventional Commits
We use Conventional Commits:
feat: New featurefix: Bug fixdocs: Documentation changesrefactor: Code refactoringtest: Test changeschore: Maintenance tasks
Contributing
Contributions are welcome! Please ensure:
- All tests pass (
uv run pytest) - Code quality checks pass (
uv run lefthook run pre-commit --all-files -- --no-stash) - Commits follow conventional commit format
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for streamblocks 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| streamblocks-0.4.0.tar.gz | 219.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| streamblocks-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 453.7 kB
Release files / streamblocks-0.4.0.tar.gz
| Download URL | streamblocks-0.4.0.tar.gz |
|---|---|
| Size | 219.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b8ff86f0712c67b86acb3e8b0e0df7a0fe76a901bf922d7c0264c671dad51197
|
|
BLAKE2b-256 checksum How to use checksums |
075c65d35fca6203aad10e8a1f6a25711cb16e18a587633ebd284d03d9366c97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jun 16, 2026.
Transparency logRelease files / streamblocks-0.4.0-py3-none-any.whl
| Download URL | streamblocks-0.4.0-py3-none-any.whl |
|---|---|
| Size | 234.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d0f081db15cc405a96b204cdf2ad9ecff7a9c50625e3ff98591cdab933501b77
|
|
BLAKE2b-256 checksum How to use checksums |
cb1178a7812671a36cb8255803f4e67d9934c8e3c2424b32c45f865e5de940ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jun 16, 2026.
Transparency logSecurity for streamblocks 0.4.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for streamblocks-0.4.0.tar.gz
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 Jun 16, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.