llmflow-core
Deterministic LLM workflow engine for file-defined, schema-validated pipelines.
Overview
llmflow-core executes explicit workflow DAGs from YAML and prompt files.
It is designed for predictable execution, strict output contracts, and replayable
artifacts.
Core guarantees:
- Stable topological execution order
- Fail-fast behavior on first step error
- JSON-schema validation for LLM outputs
- Run artifacts for audit and replay
Why this exists
Production LLM pipelines often fail on three basics:
- Step order is implicit and hard to reason about
- Outputs drift from expected structure
- Runs are difficult to reproduce and debug
llmflow-core addresses this with file-defined workflows, strict validation,
and deterministic run traces.
Installation
python -m pip install -e .
Install with test dependencies:
python -m pip install -e .[dev]
Quickstart
1) Run with Python API
from llmflow import MockProvider, RunConfig, Runner, Workflow
workflow = Workflow.load("examples/blog_pipeline/workflow.yaml")
runner = Runner(
provider=MockProvider(default_output="{}", strict=False),
config=RunConfig(artifacts_dir=".runs", provider_name="mock"),
)
result = runner.run(
workflow,
inputs={"topic": "Deterministic AI", "audience": "Engineering managers"},
)
print(result.outputs)
print(result.run_dir)
Note:
MockProvider(default_output=...)returns the same JSON for every LLM step.- If your workflow has different per-step schemas, use per-prompt mock responses (see Example Workflow below).
2) Run with CLI
llmflow run examples/blog_pipeline/workflow.yaml \
--input topic="Deterministic AI" \
--input audience="Engineering managers" \
--mock-output '{"title":"Draft","summary":"S","body":"B"}'
3) Inspect and replay
llmflow graph examples/blog_pipeline/workflow.yaml
llmflow replay .runs/run_YYYYMMDD_HHMMSS_<shortid>
CLI
The CLI is a thin wrapper over the library API.
Commands:
llmflow run <workflow.yaml> --input key=value ...llmflow graph <workflow.yaml>llmflow replay <run_dir>
Example:
llmflow run examples/blog_pipeline/workflow.yaml \
--input topic="Deterministic AI" \
--input audience="Engineering managers" \
--mock-output '{"title":"Draft","summary":"S","body":"B"}'
llmflow graph examples/blog_pipeline/workflow.yaml
llmflow replay .runs/run_YYYYMMDD_HHMMSS_<shortid>
CLI mock behavior:
--mock-outputand--mock-output-fileare applied to all LLM steps in the run.- For workflows with heterogeneous per-step schemas, prefer Python API tests with prompt-specific mock responses.
Example workflow
Repository example: examples/blog_pipeline
Contents:
examples/blog_pipeline/workflow.yamlexamples/blog_pipeline/prompts/outline.mdexamples/blog_pipeline/prompts/critique.mdexamples/blog_pipeline/prompts/revise.mdexamples/blog_pipeline/schemas/outline.jsonexamples/blog_pipeline/schemas/critique.jsonexamples/blog_pipeline/schemas/final_article.jsonexamples/blog_pipeline/tools.py
The end-to-end deterministic example run is validated by:
tests/test_examples_blog_pipeline.py
Workflow YAML format
Minimal shape:
workflow:
name: blog_post_pipeline
version: "1.0"
inputs:
topic:
type: string
audience:
type: string
steps:
- id: outline
type: llm
prompt: prompts/outline.md
output_schema: schemas/outline.json
llm:
model: mock-model
temperature: 0
- id: critique
type: llm
depends_on: [outline]
prompt: prompts/critique.md
output_schema: schemas/critique.json
llm:
model: mock-model
temperature: 0
outputs:
article: critique
Rules:
workflow.nameandworkflow.versionare required.inputsis a mapping of input names to type declarations.- Each step needs a unique
idandtype. depends_onmust reference existing step ids.outputsmaps final output names to step ids.- For
llmsteps,prompt,output_schema, andllm.modelare required.
Replay
Replay reconstructs outputs from recorded artifacts and verifies they match the
recorded outputs.json exactly.
from llmflow import replay
result = replay(".runs/run_YYYYMMDD_HHMMSS_<shortid>")
print(result.outputs)
Optional workflow override:
result = replay(
".runs/run_YYYYMMDD_HHMMSS_<shortid>",
workflow_path="examples/blog_pipeline/workflow.yaml",
)
Artifacts
Each run writes a folder under .runs/:
.runs/
run_YYYYMMDD_HHMMSS_<shortid>/
metadata.json
inputs.json
outputs.json
steps/
<step_id>/
output.json
rendered_prompt.md
llm_call.json
logs.txt
metadata.json includes:
artifacts_version- engine version
- workflow name, version, and hash
- provider name
- execution order
- prompt hashes and step output hashes
- timestamps
Typical step artifacts:
steps/<step_id>/output.json: Validated step output payloadsteps/<step_id>/rendered_prompt.md: Rendered prompt text for LLM stepssteps/<step_id>/llm_call.json: Provider request/response metadata for LLM steps
Extending the engine
Providers
Implement Provider.call(request) -> ProviderResponse and pass the provider to
Runner.
from llmflow.providers import Provider, ProviderRequest, ProviderResponse
class StaticProvider(Provider):
def call(self, request: ProviderRequest) -> ProviderResponse:
return ProviderResponse(
model=request.model,
output_text='{"title":"Draft","summary":"S","body":"B"}',
raw={"provider": "static"},
)
Tools
Register Python functions in ToolRegistry. Tool functions accept merged step
inputs and must return a dict.
from llmflow.registry import ToolRegistry
tools = ToolRegistry()
tools.register("summarize_topic", lambda inputs: {"topic_slug": inputs["topic"].lower()})
Validators
Register custom validators in ValidatorRegistry. Validator functions accept
merged step inputs and should return True/None on success, or False on
failure.
from llmflow.registry import ValidatorRegistry
validators = ValidatorRegistry()
validators.register("has_summary", lambda inputs: bool(inputs.get("summary")))
Custom steps
Register custom step classes in StepRegistry when you need a new execution
primitive beyond llm, tool, and validate.
Testing
Run all tests:
pytest
Run tests with coverage for core modules:
pytest --cov=llmflow --cov-report=term-missing
Determinism and replay checks:
pytest tests/test_replay.py tests/test_examples_blog_pipeline.py
Run a local command equivalent to CI:
python -m pip install -e .[dev]
pytest --cov=llmflow --cov-report=term-missing
Current status
Implemented through Phase 11:
- Core workflow loading and validation
- Graph ordering and cycle detection
- LLM/tool/validate steps
- Artifacts and metadata
- Runner and replay
- CLI (
run,graph,replay) - Example workflow (
examples/blog_pipeline) - CI workflow and coverage command (
pytest --cov=llmflow)
Metadata
Release files for llmflow-core 0.0.2
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 | |
|---|---|---|---|---|
| llmflow_core-0.0.2.tar.gz | 20.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llmflow_core-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.2 kB
Release files / llmflow_core-0.0.2.tar.gz
| Download URL | llmflow_core-0.0.2.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
65f1010616c54b12e5ce09dff4b2c2a0111ce62629d4ec0be6c98858c3e927c9
|
|
BLAKE2b-256 checksum How to use checksums |
ee431cbd8321255399d2077fc1ee583cf624b5ca241e257e1193acbcf6cd353a
|
| 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 Feb 16, 2026.
Transparency logRelease files / llmflow_core-0.0.2-py3-none-any.whl
| Download URL | llmflow_core-0.0.2-py3-none-any.whl |
|---|---|
| Size | 21.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6f48e24bb5bfbb84bbfbfa0f9fccb5bd8aebd143bc447518a35e2a1c9af81453
|
|
BLAKE2b-256 checksum How to use checksums |
e5f5e99a3ec559a006b95188eb31be05ea05b05c737351c924f7d2a7110024b5
|
| 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 Feb 16, 2026.
Transparency logSecurity for llmflow-core 0.0.2
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 llmflow_core-0.0.2.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 Feb 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.