Skip to main content

YAML-first framework for building LLM pipelines with LangGraph

Project description

YamlGraph

PyPI version Python 3.11+ License: MIT

A YAML-first framework for building LLM pipelines using:

  • YAML Graph Configuration - Declarative pipeline definition with schema validation
  • YAML Prompts - Declarative prompt templates with Jinja2 support
  • Pydantic Models - Structured LLM outputs
  • Multi-Provider LLMs - Support for Anthropic, Mistral, and OpenAI
  • LangGraph - Pipeline orchestration with resume support
  • SQLite - State persistence
  • LangSmith - Observability and tracing
  • JSON Export - Result serialization

Installation

From PyPI

pip install yamlgraph

From Source

git clone https://github.com/sheikkinen/yamlgraph.git
cd yamlgraph
pip install -e ".[dev]"

Quick Start

1. Create a Prompt

Create prompts/greet.yaml:

system: |
  You are a friendly assistant.

user: |
  Say hello to {name} in a {style} way.

2. Create a Graph

Create graphs/hello.yaml:

version: "1.0"
name: hello-world

nodes:
  greet:
    type: llm
    prompt: greet
    variables:
      name: "{state.name}"
      style: "{state.style}"
    state_key: greeting

edges:
  - from: START
    to: greet
  - from: greet
    to: END

3. Set API Key

export ANTHROPIC_API_KEY=your-key-here
# Or: export MISTRAL_API_KEY=... or OPENAI_API_KEY=...

4. Run It

yamlgraph graph run graphs/hello.yaml --var name="World" --var style="enthusiastic"

Or use the Python API:

from yamlgraph.graph_loader import load_and_compile

graph = load_and_compile("graphs/hello.yaml")
app = graph.compile()
result = app.invoke({"name": "World", "style": "enthusiastic"})
print(result["greeting"])

More Examples

# Content generation pipeline
yamlgraph graph run graphs/yamlgraph.yaml --var topic="AI" --var style=casual

# Sentiment-based routing
yamlgraph graph run graphs/router-demo.yaml --var message="I love this!"

# Self-correction loop (Reflexion pattern)
yamlgraph graph run graphs/reflexion-demo.yaml --var topic="climate change"

# AI agent with shell tools
yamlgraph graph run graphs/git-report.yaml --var input="What changed recently?"

# Parallel fan-out with map nodes
yamlgraph graph run examples/storyboard/animated-character-graph.yaml \
  --var concept="A brave mouse knight" --var model=hidream

CLI Utilities

yamlgraph graph list                         # List available graphs
yamlgraph graph info graphs/router-demo.yaml # Show graph structure
yamlgraph graph validate graphs/*.yaml       # Validate graph schemas
yamlgraph list-runs                          # View recent runs
yamlgraph resume --thread-id abc123          # Resume a run
yamlgraph export --thread-id abc123          # Export run to JSON

# Observability (requires LangSmith)
yamlgraph trace --verbose                    # View execution trace
yamlgraph mermaid                            # Show pipeline as Mermaid diagram

Documentation

See the reference/ folder for comprehensive YAML configuration guides:

Architecture

Data Flow

flowchart TB
    subgraph Input["๐Ÿ“ฅ Input Layer"]
        CLI["CLI Command"]
        YAML_G["graphs/*.yaml"]
        YAML_P["prompts/*.yaml"]
    end

    subgraph Core["โš™๏ธ Core Processing"]
        GL["graph_loader.py<br/>YAML โ†’ StateGraph"]
        NF["node_factory.py<br/>Create Node Functions"]
        EH["error_handlers.py<br/>Skip/Retry/Fail/Fallback"]
        EX["executor.py<br/>Prompt Execution"]
    end

    subgraph LLM["๐Ÿค– LLM Layer"]
        LF["llm_factory.py"]
        ANT["Anthropic"]
        MIS["Mistral"]
        OAI["OpenAI"]
    end

    subgraph State["๐Ÿ’พ State Layer"]
        SB["state_builder.py<br/>Dynamic TypedDict"]
        CP["checkpointer.py<br/>SQLite Persistence"]
        DB[(SQLite DB)]
    end

    subgraph Output["๐Ÿ“ค Output Layer"]
        EXP["export.py"]
        JSON["JSON Export"]
        LS["LangSmith Traces"]
    end

    CLI --> GL
    YAML_G --> GL
    YAML_P --> EX
    GL --> NF
    NF --> EH
    EH --> EX
    EX --> LF
    LF --> ANT & MIS & OAI
    GL --> SB
    SB --> CP
    CP --> DB
    EX --> EXP
    EXP --> JSON
    EX --> LS

Directory Structure

yamlgraph/
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ pyproject.toml        # Package definition with CLI entry point and dependencies
โ”œโ”€โ”€ .env.sample           # Environment template
โ”‚
โ”œโ”€โ”€ graphs/               # YAML graph definitions
โ”‚   โ”œโ”€โ”€ yamlgraph.yaml    # Main pipeline definition
โ”‚   โ”œโ”€โ”€ router-demo.yaml  # Tone-based routing demo
โ”‚   โ”œโ”€โ”€ reflexion-demo.yaml # Self-refinement loop demo
โ”‚   โ””โ”€โ”€ git-report.yaml   # AI agent demo with shell tools
โ”‚
โ”œโ”€โ”€ yamlgraph/            # Main package
โ”‚   โ”œโ”€โ”€ __init__.py       # Package exports
โ”‚   โ”œโ”€โ”€ builder.py        # Graph builders (loads from YAML)
โ”‚   โ”œโ”€โ”€ graph_loader.py   # YAML โ†’ LangGraph compiler
โ”‚   โ”œโ”€โ”€ config.py         # Centralized configuration
โ”‚   โ”œโ”€โ”€ executor.py       # YAML prompt executor
โ”‚   โ”œโ”€โ”€ cli.py            # CLI commands
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ models/           # Pydantic models
โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”œโ”€โ”€ schemas.py    # Framework schemas (ErrorType, PipelineError, GenericReport)
โ”‚   โ”‚   โ”œโ”€โ”€ state_builder.py  # Dynamic state generation from YAML
โ”‚   โ”‚   โ””โ”€โ”€ graph_schema.py   # Pydantic schema validation
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ tools/            # Tool execution
โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”œโ”€โ”€ shell.py      # Shell command executor
โ”‚   โ”‚   โ”œโ”€โ”€ nodes.py      # Tool node factory
โ”‚   โ”‚   โ””โ”€โ”€ agent.py      # Agent node factory
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ storage/          # Persistence layer
โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”œโ”€โ”€ database.py   # SQLite wrapper
โ”‚   โ”‚   โ””โ”€โ”€ export.py     # JSON export
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ utils/            # Utilities
โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚       โ”œโ”€โ”€ llm_factory.py # Multi-provider LLM creation
โ”‚       โ””โ”€โ”€ langsmith.py  # Tracing helpers
โ”‚
โ”œโ”€โ”€ prompts/              # YAML prompt templates
โ”‚   โ”œโ”€โ”€ greet.yaml
โ”‚   โ”œโ”€โ”€ analyze.yaml
โ”‚   โ”œโ”€โ”€ analyze_list.yaml # Jinja2 example with loops/filters
โ”‚   โ”œโ”€โ”€ generate.yaml
โ”‚   โ”œโ”€โ”€ summarize.yaml
โ”‚   โ””โ”€โ”€ router-demo/      # Tone routing prompts
โ”‚       โ”œโ”€โ”€ classify_tone.yaml
โ”‚       โ”œโ”€โ”€ respond_positive.yaml
โ”‚       โ”œโ”€โ”€ respond_negative.yaml
โ”‚       โ””โ”€โ”€ respond_neutral.yaml
โ”‚
โ”œโ”€โ”€ reference/            # YAML configuration reference docs
โ”‚   โ”œโ”€โ”€ README.md         # Overview and key concepts
โ”‚   โ”œโ”€โ”€ quickstart.md     # 5-minute getting started guide
โ”‚   โ”œโ”€โ”€ graph-yaml.md     # Graph YAML reference
โ”‚   โ”œโ”€โ”€ prompt-yaml.md    # Prompt YAML reference
โ”‚   โ””โ”€โ”€ patterns.md       # Common patterns and examples
โ”‚
โ”œโ”€โ”€ tests/                # Test suite
โ”‚   โ”œโ”€โ”€ conftest.py       # Shared fixtures
โ”‚   โ”œโ”€โ”€ unit/             # Unit tests
โ”‚   โ””โ”€โ”€ integration/      # Integration tests
โ”‚
โ””โ”€โ”€ outputs/              # Generated files (gitignored)

## Pipeline Flow

```mermaid
graph TD
    A["๐Ÿ“ generate"] -->|content| B{should_continue}
    B -->|"โœ“ content exists"| C["๐Ÿ” analyze"]
    B -->|"โœ— error/empty"| F["๐Ÿ›‘ END"]
    C -->|analysis| D["๐Ÿ“Š summarize"]
    D -->|final_summary| F

    style A fill:#e1f5fe
    style C fill:#fff3e0
    style D fill:#e8f5e9
    style F fill:#fce4ec

Node Outputs

Node Output Type Description
generate Inline schema Title, content, word_count, tags
analyze Inline schema Summary, key_points, sentiment, confidence
summarize str Final combined summary

Output schemas are defined inline in YAML prompt files using the schema: block.

Resume Flow

Pipelines can be resumed from any checkpoint. The resume behavior uses skip_if_exists: nodes check if their output already exists in state and skip LLM calls if so.

graph LR
    subgraph "Resume after 'analyze' completed"
        A1["Load State"] --> B1["analyze (skipped)"] --> C1["summarize"] --> D1["END"]
    end
# Resume an interrupted run
yamlgraph resume --thread-id abc123

When resumed:

  • Nodes with existing outputs are skipped (no duplicate LLM calls)
  • Only nodes without outputs in state actually run
  • State is preserved via SQLite checkpointing

Key Patterns

1. YAML Prompt Templates

Simple Templating (Basic Substitution):

# prompts/generate.yaml
system: |
  You are a creative content writer...

user: |
  Write about: {topic}
  Target length: approximately {word_count} words

Advanced Templating (Jinja2):

# prompts/analyze_list.yaml
template: |
  Analyze the following {{ items|length }} items:

  {% for item in items %}
  ### {{ loop.index }}. {{ item.title }}
  Topic: {{ item.topic }}
  {% if item.tags %}
  Tags: {{ item.tags | join(", ") }}
  {% endif %}
  {% endfor %}

Template Features:

  • Auto-detection: Uses Jinja2 if {{ or {% present, otherwise simple formatting
  • Loops: {% for item in items %}...{% endfor %}
  • Conditionals: {% if condition %}...{% endif %}
  • Filters: {{ text[:50] }}, {{ items | join(", ") }}, {{ name | upper }}
  • Backward compatible: Existing {variable} prompts work unchanged

2. Structured Executor

from yamlgraph.executor import execute_prompt
from yamlgraph.models import GenericReport

result = execute_prompt(
    "generate",
    variables={"topic": "AI", "word_count": 300},
    output_model=GenericReport,
)
print(result.title)  # Typed access!

3. Multi-Provider LLM Support

from yamlgraph.executor import execute_prompt

# Use default provider (Anthropic)
result = execute_prompt(
    "greet",
    variables={"name": "Alice", "style": "formal"},
)

# Switch to Mistral
result = execute_prompt(
    "greet",
    variables={"name": "Bob", "style": "casual"},
    provider="mistral",
)

# Or set via environment variable
# PROVIDER=openai yamlgraph graph run ...

Supported providers:

  • Anthropic (default): Claude models
  • Mistral: Mistral Large and other models
  • OpenAI: GPT-4 and other models

Provider selection priority:

  1. Function parameter: execute_prompt(..., provider="mistral")
  2. YAML metadata: provider: mistral in prompt file
  3. Environment variable: PROVIDER=mistral
  4. Default: anthropic

4. YAML Graph Configuration

Pipelines are defined declaratively in YAML and compiled to LangGraph:

# graphs/yamlgraph.yaml
version: "1.0"
name: yamlgraph-demo
description: Content generation pipeline

defaults:
  provider: mistral
  temperature: 0.7

nodes:
  generate:
    type: llm
    prompt: generate
    output_schema:  # Inline schema - no Python model needed!
      title: str
      content: str
      word_count: int
      tags: list[str]
    temperature: 0.8
    variables:
      topic: "{state.topic}"
      word_count: "{state.word_count}"
      style: "{state.style}"
    state_key: generated

  analyze:
    type: llm
    prompt: analyze
    output_schema:  # Inline schema
      summary: str
      key_points: list[str]
      sentiment: str
      confidence: float
    temperature: 0.3
    variables:
      content: "{state.generated.content}"
    state_key: analysis
    requires: [generated]

  summarize:
    type: llm
    prompt: summarize
    temperature: 0.5
    state_key: final_summary
    requires: [generated, analysis]

edges:
  - from: START
    to: generate
  - from: generate
    to: analyze
    condition: continue
  - from: generate
    to: END
    condition: end
  - from: analyze
    to: summarize
  - from: summarize
    to: END

Load and run:

from yamlgraph.builder import build_graph

graph = build_graph().compile()  # Loads from graphs/yamlgraph.yaml
result = graph.invoke(initial_state)

5. State Persistence

from yamlgraph.storage import YamlGraphDB

db = YamlGraphDB()
db.save_state("thread-123", state)
state = db.load_state("thread-123")

6. LangSmith Tracing

from yamlgraph.utils.langsmith import print_run_tree

print_run_tree(verbose=True)
# ๐Ÿ“Š Execution Tree:
# โ””โ”€ yamlgraph_pipeline (12.3s) โœ…
#    โ”œโ”€ generate (5.2s) โœ…
#    โ”œโ”€ analyze (3.1s) โœ…
#    โ””โ”€ summarize (4.0s) โœ…

7. Shell Tools & Agent Nodes

Define shell tools and let the LLM decide when to use them:

# graphs/git-report.yaml
tools:
  recent_commits:
    type: shell
    command: git log --oneline -n {count}
    description: "List recent commits"

  changed_files:
    type: shell
    command: git diff --name-only HEAD~{n}
    description: "List files changed in last n commits"

nodes:
  analyze:
    type: agent              # LLM decides which tools to call
    prompt: git_analyst
    tools: [recent_commits, changed_files]
    max_iterations: 8
    state_key: analysis

Run the git analysis agent:

yamlgraph git-report -q "What changed recently?"
yamlgraph git-report -q "Summarize the test directory"

Node types:

  • type: llm - Standard LLM call with structured output
  • type: router - Classify and route to different paths
  • type: map - Parallel fan-out over lists with Send()
  • type: python - Execute custom Python functions
  • type: agent - LLM loop that autonomously calls tools

Environment Variables

Variable Required Description
ANTHROPIC_API_KEY Yes* Anthropic API key (* if using Anthropic)
MISTRAL_API_KEY No Mistral API key (required if using Mistral)
OPENAI_API_KEY No OpenAI API key (required if using OpenAI)
PROVIDER No Default LLM provider (anthropic/mistral/openai)
ANTHROPIC_MODEL No Anthropic model (default: claude-sonnet-4-20250514)
MISTRAL_MODEL No Mistral model (default: mistral-large-latest)
OPENAI_MODEL No OpenAI model (default: gpt-4o)
LANGCHAIN_TRACING No Enable LangSmith tracing
LANGCHAIN_API_KEY No LangSmith API key
LANGCHAIN_ENDPOINT No LangSmith endpoint URL
LANGCHAIN_PROJECT No LangSmith project name

Testing

Run the test suite:

# Run all tests
pytest tests/ -v

# Run only unit tests
pytest tests/unit/ -v

# Run only integration tests
pytest tests/integration/ -v

# Run with coverage report
pytest tests/ --cov=yamlgraph --cov-report=term-missing

# Run with HTML coverage report
pytest tests/ --cov=yamlgraph --cov-report=html
# Then open htmlcov/index.html

Current coverage: 60% overall, 98% on graph_loader, 100% on builder/llm_factory.

Extending the Pipeline

Adding a New Node (YAML-First Approach)

Let's add a "fact_check" node that verifies generated content:

Step 1: Define the output schema (yamlgraph/models/schemas.py):

class FactCheck(BaseModel):
    """Structured fact-checking output."""

    claims: list[str] = Field(description="Claims identified in content")
    verified: bool = Field(description="Whether claims are verifiable")
    confidence: float = Field(ge=0.0, le=1.0, description="Verification confidence")
    notes: str = Field(description="Additional context")

Step 2: Create the prompt (prompts/fact_check.yaml):

system: |
  You are a fact-checker. Analyze the given content and identify
  claims that can be verified. Assess the overall verifiability.

user: |
  Content to fact-check:
  {content}

  Identify key claims and assess their verifiability.

Step 3: State is auto-generated

State fields are now generated automatically from your YAML graph config. The state_key in your node config determines where output is stored:

# Node output stored in state.fact_check automatically
fact_check:
  type: llm
  prompt: fact_check
  state_key: fact_check  # This creates the state field

Step 4: Add the node to your graph (graphs/yamlgraph.yaml):

nodes:
  generate:
    type: prompt
    prompt: generate
    output_schema:  # Inline schema - no Python model needed!
      title: str
      content: str
    variables:
      topic: topic
    state_key: generated

  fact_check:  # โœจ New node - just YAML!
    type: prompt
    prompt: fact_check
    output_schema:  # Define schema inline
      is_accurate: bool
      issues: list[str]
    requires: [generated]
    variables:
      content: generated.content
    state_key: fact_check

  analyze:
    # ... existing config ...

edges:
  - from: START
    to: generate
  - from: generate
    to: fact_check
    condition:
      type: has_value
      field: generated
  - from: fact_check
    to: analyze
  # ... rest of edges ...

That's it! No Python node code needed. The graph loader dynamically generates the node function.

Resulting pipeline:

graph TD
    A[generate] --> B{has generated?}
    B -->|yes| C[fact_check]
    C --> D[analyze]
    D --> E[summarize]
    E --> F[END]
    B -->|no| F

Adding Conditional Branching

Route to different nodes based on analysis results (all in YAML):

edges:
  - from: analyze
    to: rewrite_node
    condition:
      type: field_equals
      field: analysis.sentiment
      value: negative

  - from: analyze
    to: enhance_node
    condition:
      type: field_equals
      field: analysis.sentiment
      value: positive

  - from: analyze
    to: summarize  # Default fallback

Add a New Prompt

  1. Create prompts/new_prompt.yaml:
system: Your system prompt...
user: Your user prompt with {variables}...
  1. Call it:
result = execute_prompt("new_prompt", variables={"var": "value"})

Add Structured Output

  1. Define model in yamlgraph/models/schemas.py:
class MyOutput(BaseModel):
    field: str = Field(description="...")
  1. Use with executor:
result = execute_prompt("prompt", output_model=MyOutput)

Known Issues & Future Improvements

This project demonstrates solid production patterns with declarative YAML-based configuration.

Completed Features

Feature Status Notes
YAML Graph Configuration โœ… Declarative pipeline definition in graphs/yamlgraph.yaml
Jinja2 Templating โœ… Hybrid auto-detection (simple {var} + advanced Jinja2)
Multi-Provider LLMs โœ… Factory pattern supporting Anthropic/Mistral/OpenAI
Dynamic Node Generation โœ… Nodes compiled from YAML at runtime

Implemented Patterns

Feature Status Notes
Branching/Routing โœ… type: router for LLM-based conditional routing
Self-Correction Loops โœ… Reflexion pattern with critique โ†’ refine cycles
Tool/Agent Patterns โœ… Shell tools + agent nodes with LangChain tool binding
Per-Node Error Handling โœ… on_error: skip/retry/fail/fallback
Conversation Memory โœ… Message accumulation via AgentState.messages
Native Checkpointing โœ… SqliteSaver from langgraph-checkpoint-sqlite
State Export โœ… JSON/Markdown export with export_result()
LangSmith Share Links โœ… Auto-generate public trace URLs after runs

Missing LangGraph Features

Feature Status Notes
Fan-out/Fan-in โœ… type: map with Send() for item-level parallelism
Human-in-the-Loop โŒ No interrupt_before / interrupt_after demonstration
Streaming โŒ No streaming output support
Sub-graphs โŒ No nested graph composition

Potential Enhancements

Short-term (Quick Wins)

  1. Add in operator to conditions - Support status in ["done", "complete"] expressions
  2. Document agent max_iterations - Expose in YAML schema for agent nodes
  3. Add --dry-run flag - Validate graph without execution

Medium-term (Feature Improvements)

  1. Async map node execution - Use asyncio.gather() for parallel branches
  2. State field collision warnings - Log when YAML fields override base fields
  3. Map node error aggregation - Summary with success/failure counts per branch
  4. Add streaming - --stream CLI flag for real-time output

Long-term (Architecture)

  1. Plugin system - Custom node types via entry points
  2. Hot-reload for development - File watcher for prompt/graph YAML changes
  3. OpenTelemetry integration - Complement LangSmith with standard observability
  4. Sub-graphs - Nested graph composition for complex workflows
  5. Human-in-the-loop - interrupt_before / interrupt_after demonstration

Security

Shell Command Injection Protection

Shell tools (defined in graphs/*.yaml with type: tool) execute commands with variable substitution. All user-provided variable values are sanitized using shlex.quote() to prevent shell injection attacks.

# In graph YAML - command template is trusted
tools:
  git_log:
    type: shell
    command: "git log --author={author} -n {count}"

Security model:

  • โœ… Command templates (from YAML) are trusted configuration
  • โœ… Variable values (from user input/LLM) are escaped with shlex.quote()
  • โœ… Complex types (lists, dicts) are JSON-serialized then quoted
  • โœ… No eval() - condition expressions parsed with regex, not evaluated

Example protection:

# Malicious input is safely escaped
variables = {"author": "$(rm -rf /)"}
# Executed as: git log --author='$(rm -rf /)'  (quoted, harmless)

See yamlgraph/tools/shell.py for implementation details.

โš ๏ธ Security Considerations

Shell tools execute real commands on your system. While variables are sanitized:

  1. Command templates are trusted - Only use shell tools from trusted YAML configs
  2. No sandboxing - Commands run with your user permissions
  3. Agent autonomy - Agent nodes may call tools unpredictably
  4. Review tool definitions - Audit tools: section in graph YAML before running

For production deployments, consider:

  • Running in a container with limited permissions
  • Restricting available tools to read-only operations
  • Implementing approval workflows for sensitive operations

License

MIT

Remember

Prompts in yaml templates, graphs in yaml, shared executor, pydantic, data stored in sqlite, langgraph, langsmith, venv, tdd red-green-refactor, modules < 400 lines, kiss

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yamlgraph-0.1.1.tar.gz (139.1 kB view details)

Uploaded Source

Built Distribution

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

yamlgraph-0.1.1-py3-none-any.whl (172.9 kB view details)

Uploaded Python 3

File details

Details for the file yamlgraph-0.1.1.tar.gz.

File metadata

  • Download URL: yamlgraph-0.1.1.tar.gz
  • Upload date:
  • Size: 139.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for yamlgraph-0.1.1.tar.gz
Algorithm Hash digest
SHA256 0930578d459ee587f794f683a90364e8f7bd798c6106752946cd59ca87ffbe41
MD5 b0f2f755ab5951abc3dbad56e73c60d2
BLAKE2b-256 1f5059a4cc8e9620e263df407c09443adea0483eb801f4fa6b69f79c9453ca58

See more details on using hashes here.

Provenance

The following attestation bundles were made for yamlgraph-0.1.1.tar.gz:

Publisher: workflow.yml on sheikkinen/yamlgraph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yamlgraph-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: yamlgraph-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 172.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for yamlgraph-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fe6eb9fe427fe405f5eb0745ab2a7bc4dec08962c8d3a5042609e835bb86bded
MD5 e803a0ebc5e65cd4a44aac3a73ddb15f
BLAKE2b-256 de09bbcb96fb9e59e52ac5bc5235909e80a2ff747099ac70c1465312ac215025

See more details on using hashes here.

Provenance

The following attestation bundles were made for yamlgraph-0.1.1-py3-none-any.whl:

Publisher: workflow.yml on sheikkinen/yamlgraph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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