Skip to main content

runtime-narrative — model execution as human-readable stories

Project description

runtime_narrative

Model your application's execution as human-readable stories instead of scattered log lines.

When something fails, instead of a raw traceback you get:

❌ Failure detected
Story:    Create Customer
Stage:    Validate Input
Error:    ValueError - invalid email
Location: handlers.py:24 (validate_customer)
Code:     if "@" not in payload.email:
Progress: 33% (1 / 3 stages completed)
Recent stages: Validate Input=failed (0.001s)

Installation

# Core only (zero dependencies)
pip install runtime-narrative

# With colored console output
pip install "runtime-narrative[console]"

# With FastAPI middleware
pip install "runtime-narrative[fastapi]"

# Everything
pip install "runtime-narrative[all]"

Quick start

from runtime_narrative import story, stage

with story("Import Customers"):
    with stage("Load CSV"):
        load_file()

    with stage("Validate Data"):
        validate()

    with stage("Insert Records"):
        insert()

FastAPI — middleware (recommended)

Add middleware once and every request gets a story automatically. Route handlers only need to declare stages:

from runtime_narrative import RuntimeNarrativeMiddleware, stage

app.add_middleware(RuntimeNarrativeMiddleware)

@app.post("/customers")
async def create_customer(payload: CustomerIn):
    with stage("Validate Input"):
        ...
    with stage("Insert Into Database"):
        ...
    with stage("Build Response"):
        return {"ok": True}

FastAPI — decorator style

from runtime_narrative import runtime_narrative_story, runtime_narrative_stage

@app.post("/customers")
@runtime_narrative_story("Create Customer")
async def create_customer(payload: CustomerIn):
    return await _save(payload)

@runtime_narrative_stage("Save to Database")
async def _save(payload):
    ...

Structured JSON output

Pipe one JSON object per lifecycle event to stdout, a file, or any stream:

from runtime_narrative import RuntimeNarrativeMiddleware, JsonRenderer

app.add_middleware(RuntimeNarrativeMiddleware, renderers=[JsonRenderer()])

Output (one line per event):

{"event": "StoryStarted", "story_id": "...", "story_name": "POST /customers", "timestamp": "..."}
{"event": "StageStarted", "story_id": "...", "stage_name": "Validate Input", "timestamp": "..."}
{"event": "StageCompleted", "story_id": "...", "stage_name": "Validate Input", "duration_seconds": 0.001, "timestamp": "..."}
{"event": "StoryCompleted", "story_id": "...", "success": true, "progress": {"percent": 100, ...}, "timestamp": "..."}

Write to a file instead of stdout:

JsonRenderer(output=open("runtime_narrative.log", "a"))

LLM failure analysis

Plug in any LLM backend — model name and endpoint are always required (no defaults).

OpenAI-compatible backends (vLLM, llama.cpp --server, LM Studio, Ollama OpenAI mode):

from runtime_narrative import LLMFailureAnalyzer, story

analyzer = LLMFailureAnalyzer(
    model="llama3",
    endpoint="http://localhost:8000/v1/chat/completions",
)

with story("Process Orders", failure_analyzer=analyzer):
    ...

Ollama native API:

from runtime_narrative import OllamaFailureAnalyzer, story

analyzer = OllamaFailureAnalyzer(
    model="llama3",
    endpoint="http://localhost:11434/api/generate",
)

with story("Process Orders", failure_analyzer=analyzer):
    ...

Falls back silently if the endpoint is unavailable.

Custom renderer

Implement a single handle method to receive all lifecycle events:

class MyRenderer:
    def handle(self, event):
        print(event.__class__.__name__, event.__dict__)

with story("My Story", renderers=[MyRenderer()]):
    ...

Events: StoryStarted, StageStarted, StageCompleted, FailureOccurred, StoryCompleted.

License

MIT

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

runtime_narrative-0.1.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

runtime_narrative-0.1.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file runtime_narrative-0.1.0.tar.gz.

File metadata

  • Download URL: runtime_narrative-0.1.0.tar.gz
  • Upload date:
  • Size: 13.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for runtime_narrative-0.1.0.tar.gz
Algorithm Hash digest
SHA256 30766660c6177df2eda862f0d29d6146c45930d1c5cd4215bf877e19645624b9
MD5 33fd7ba3552cc19ea8b4ae844bf45561
BLAKE2b-256 7f1f8db8040a213c29ab52b1a5075831dc888ed9328ac3c440b55fdc5d36bddd

See more details on using hashes here.

File details

Details for the file runtime_narrative-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for runtime_narrative-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9501aa8e0176086f842cce455dca2a46df126319f3a541d20ec109231a25e6d
MD5 55b87fe47b8c1f200e00a0c3edd97bc0
BLAKE2b-256 bf181d7d32f82c9d3ae7ee9102edd07899ffe753e604620761e51d44e38582d5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page