Skip to main content

Declarative LangGraph Builder powered by YAML

Project description

Yagra: Declarative LangGraph Builder

Yagra は、YAML 定義から LangGraph の StateGraph を構築・実行する Python ライブラリです。 フロー制御(分岐・ループ)とノード設定(prompt/model など)をコードから分離し、 workflow.yaml の差し替えで挙動を切り替えられます。

公開運用ポリシー

  • パッケージ配布: Public(PyPI)
  • ソースリポジトリ: Private(GitHub)
  • 利用者向け導線は PyPI を正とし、リポジトリ参照は必須としません。

主な特徴

  • Schema-Driven: Pydantic で YAML 構造を検証
  • Registry Pattern: handler 文字列と Python callable を疎結合に接続
  • Typed State: state_schema に TypedDict/Pydantic などの状態スキーマを指定可能
  • Zero-Boilerplate: Yagra.from_workflow(...) で構築コードを最小化

インストール(利用者向け)

  • Python 3.12+
pip install yagra

開発セットアップ(メンテナー向け)

この手順は private リポジトリへのアクセス権があるメンテナー向けです。

git clone https://github.com/shogo-hs/Yagra.git
cd Yagra
uv sync --dev

クイックスタート(条件分岐あり)

1. State とノード関数を定義

from typing import TypedDict

from yagra import Yagra


class AgentState(TypedDict, total=False):
    query: str
    intent: str
    answer: str
    __next__: str


def classify_intent(state: AgentState, params: dict) -> dict:
    _ = params
    intent = "faq" if "料金" in state.get("query", "") else "general"
    return {"intent": intent, "__next__": intent}


def answer_faq(state: AgentState, params: dict) -> dict:
    prompt = params.get("prompt", {})
    return {"answer": f"FAQ: {prompt.get('system', '')}"}


def answer_general(state: AgentState, params: dict) -> dict:
    model = params.get("model", {})
    return {"answer": f"GENERAL via {model.get('name', 'unknown')}"}


def finish(state: AgentState, params: dict) -> dict:
    _ = params
    return {"answer": state.get("answer", "")}

2. Workflow YAML を定義

workflows/support.yaml

version: "1.0"
start_at: "classifier"
end_at:
  - "finish"

nodes:
  - id: "classifier"
    handler: "classify_intent"
  - id: "faq_bot"
    handler: "answer_faq"
    params:
      prompt:
        system: "pricing response"
  - id: "general_bot"
    handler: "answer_general"
    params:
      model:
        provider: "openai"
        name: "gpt-4.1-mini"
  - id: "finish"
    handler: "finish"

edges:
  - source: "classifier"
    target: "faq_bot"
    condition: "faq"
  - source: "classifier"
    target: "general_bot"
    condition: "general"
  - source: "faq_bot"
    target: "finish"
  - source: "general_bot"
    target: "finish"

3. Registry と実行

registrydict[str, callable] を直接渡せます(InMemoryNodeRegistry は内部で自動利用)。

registry = {
    "classify_intent": classify_intent,
    "answer_faq": answer_faq,
    "answer_general": answer_general,
    "finish": finish,
}

app = Yagra.from_workflow(
    workflow_path="workflows/support.yaml",
    registry=registry,
    state_schema=AgentState,
)

result = app.invoke({"query": "料金を教えて"})
print(result["answer"])

API

Yagra.from_workflow(...)

Yagra.from_workflow(
    workflow_path: str | PathLike,
    registry: NodeRegistryPort | Mapping[str, NodeHandler],
    bundle_root: str | PathLike | None = None,
    state_schema: Any = dict,
) -> Yagra
  • workflow_path: 入口となる workflow YAML
  • registry: NodeRegistryPort 実装、または dict[str, callable]
  • bundle_root: 分割参照解決の基準ディレクトリ(省略時は workflow の親)
  • state_schema: LangGraph の状態スキーマ(既定 dict

Yagra.invoke(...)

Yagra.invoke(state: Mapping[str, Any]) -> dict[str, Any]

yagra visualize(Read Only 可視化)

Workflow YAML を Read Only の可視化 HTML に変換します。

yagra visualize \
  --workflow examples/workflows/loop-split.yaml \
  --output /tmp/yagra-view.html \
  --title "Yagra Workflow Viewer"

オプション:

  • --workflow: 可視化対象 workflow ファイル(必須)
  • --bundle-root: 分割参照解決の基準ディレクトリ(任意)
  • --output: 生成 HTML の出力先(既定: workflow-visualization.html
  • --title: ページタイトル(任意)

検証エラーがある場合は HTML は生成せず、エラー一覧を標準エラーへ出力します。

yagra studio(フォーム + DnD 編集 + 保存)

Workflow の prompt / model / condition 編集に加え、DnD でノード追加・接続変更を行い、diff 確認・保存・rollback を実行するローカル WebUI/API を起動します。

# ランチャー起動(UI で workflow を選択/新規作成)
yagra studio --port 8787

# 従来どおり直接指定で起動
yagra studio \
  --workflow examples/workflows/loop-split.yaml \
  --bundle-root examples \
  --port 8787

起動後はブラウザで http://127.0.0.1:8787/ を開きます。

主な編集フロー:

  1. 必要に応じて Add Node でノードを追加し、Node/Edge フォームで値を編集して Apply ...
    • Add Node は選択中ノードの近傍(未選択時は自動レイアウト位置)へ自動配置されます。
  2. Node Properties の prompt yaml で参照先 YAML を選択すると、system prompt / user prompt が自動で読み込まれます。
  3. prompt yaml 未選択のまま Apply Node Edit した場合、workflow YAML と同階層の prompts/<node-id>.yaml(重複時は連番)が自動作成され、prompt_ref が自動設定されます。
    • prompt key を指定した場合は path#key 形式になり、生成 YAML は { key: { system, user } } 形式になります。
  4. Graph Canvas 上でノードをドラッグして位置調整し、右側ポート(output)から左側ポート(input)へドラッグしてエッジ追加(戻りループは下側 output → 上側 input で接続)
  5. 再接続時はエッジ端点をドラッグして接続先を変更(ドラッグ起点が新 source、ドロップ先が新 target)
  6. Node Properties で node id(リネーム), prompt_ref, Model Settingsprovider / name / temperature など)を設定
    • node id を変更して Apply Node Edit すると、関連する edges[].source/targetstart_at/end_at も自動で同期されます。
  7. Preview Diff で変更差分と validation を確認
  8. Save で workflow を保存(backup 作成)
  9. 必要なら Rollbackbackup_id から復元

補足:

  • Studio 画面は操作性優先のため Workflow/UI State の生JSONは常時表示しません。必要時は GET /api/workflow / GET /api/workflow/form で確認してください。

オプション:

  • --workflow: 編集対象 workflow ファイル(任意、未指定時はランチャーで選択/作成)
  • --bundle-root: 分割参照解決の基準ディレクトリ(任意)
  • --ui-state: UI サイドカー JSON の保存先(既定: <workflow>.workflow-ui.json
  • --workspace-root: ランチャーが探索/作成可能なワークスペースルート(既定: <workflow> の親 またはカレント)
  • --backup-dir: バックアップ保存先(既定: .yagra/backups
  • --host: バインドホスト(既定: 127.0.0.1
  • --port: バインドポート(既定: 8787

保存時は以下を実施します。

  • 保存前 validation(M-05 契約)
  • atomic write(中途半端な書き込み防止)
  • backup 作成(<backup-dir>/<workflow-stem>/<backup_id>.*
  • 失敗時の自動復旧

フォーム向け API:

  • GET /api/workflow/form
  • POST /api/workflow/form/preview
    • M-09 の入力契約として、下記フィールドはすべて必須
    • base_revision, ui_state
    • node_creates[] / node_edits[]
    • edge_creates[] / edge_rewires[] / edge_edits[]

仕様上の契約(Implicit Contracts)

1. 条件分岐の契約

  • edges[].condition は分岐ラベルです。
  • 分岐元ノードは {"__next__": "<condition-label>"} を state update として返します。
  • 例: condition: "faq" がある場合、__next__"faq" を返す必要があります。

2. prompt 参照解決の契約

  • prompt_ref は実行前に解決されます。
  • handler が受け取る params には解決済み値が入ります。
    • params["prompt"]
    • params["model"]
  • prompt_refprompt を同時指定した場合、prompt_ref 解決結果に prompt が上書きマージされます(ノード側優先)。
  • 実行時に handler へ渡る params からは prompt_ref は除去されます(prompt/model を利用)。
  • model_ref は廃止です。モデル設定は nodes[].params.model にインライン定義します。
  • prompt_ref の参照形式:
    • <path>(YAML ルートが prompt mapping の場合)
    • <path>#<key.path>(YAML 内キーを指定)

例:

nodes:
  - id: planner
    handler: planner_loop_handler
    params:
      prompt_ref: "../prompts/support_prompts.yaml#planner"
      model:
        provider: openai
        name: gpt-4.1-mini
        kwargs:
          temperature: 0.1

3. end_at の挙動

  • end_at は「終了ノードIDのリスト」です(複数可)。
  • Yagra は各ノードを LangGraph の finish point として登録します。
  • YAML 上で END という特別ノードを直接書く仕様ではありません。

4. ノード関数シグネチャ

Yagra は次の順で呼び出しを試みます。

  1. handler(state, params)
  2. handler(state)

YAML 仕様(要点)

トップレベル:

  • version: str
  • start_at: str
  • end_at: list[str]
  • nodes: list[NodeSpec]
  • edges: list[EdgeSpec]
  • params: dict[str, Any](任意)

NodeSpec:

  • id: str
  • handler: str
  • params: dict[str, Any](任意)

EdgeSpec:

  • source: str
  • target: str
  • condition: str | null(任意)

補足:

  • edges は 0 件でも有効です(例: start_atend_at が同一の単一ノード workflow)。

同梱サンプル

  • examples/workflows/branch-inline.yaml
    • 条件分岐の最小例
  • examples/workflows/loop-split.yaml
    • ループ + 条件分岐 + prompt_ref 分割参照 + model インライン定義
  • examples/prompts/support_prompts.yaml
  • examples/models/openai_models.yaml

開発コマンド

uv run ruff check .
uv run mypy .
uv run pytest -q
uv run pre-commit run --all-files

ドキュメント(Sphinx)

ローカルで HTML を生成:

uv run sphinx-build -b html docs/sphinx/source docs/sphinx/_build/html

生成先:

  • docs/sphinx/_build/html/index.html

公開先(GitHub Pages):

  • https://shogo-hs.github.io/Yagra/

公開の前提:

  • GitHub の Settings > Pages で Source を GitHub Actions に設定する
  • .github/workflows/docs.ymlmain への push または手動実行で成功する

PyPI 公開

公開ワークフローは v* タグ push をトリガーに実行されます。

  • workflow: .github/workflows/publish.yml
  • build: uv build
  • 検証: uvx twine check dist/*
  • publish: pypa/gh-action-pypi-publish(OIDC)

前提:

  • PyPI 側で private repository shogo-hs/Yagra を Trusted Publisher として登録しておく
  • GitHub Actions の pypi environment が利用可能である
  • Git タグ(vX.Y.Z)と pyproject.tomlversion を一致させる

リリース実行例:

git tag v0.1.3
git push origin v0.1.3

ライセンスと変更履歴

  • ライセンス: LICENSE(MIT)
  • 変更履歴: CHANGELOG.md

エージェント実行規約

エージェント運用ルールは AGENTS.md を参照してください。

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

yagra-0.1.4.tar.gz (208.0 kB view details)

Uploaded Source

Built Distribution

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

yagra-0.1.4-py3-none-any.whl (76.3 kB view details)

Uploaded Python 3

File details

Details for the file yagra-0.1.4.tar.gz.

File metadata

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

File hashes

Hashes for yagra-0.1.4.tar.gz
Algorithm Hash digest
SHA256 6ff039230ccb8c02638f0f7a8ebe875d9527257204c4ee11300d362f1c5f40a1
MD5 60836ef88c22d1937e362ba97458bfa9
BLAKE2b-256 33371b02e4ce0b7f0a3155eef0ab72c7352261c7219bcfb5b255a05984415330

See more details on using hashes here.

Provenance

The following attestation bundles were made for yagra-0.1.4.tar.gz:

Publisher: publish.yml on shogo-hs/Yagra

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

File details

Details for the file yagra-0.1.4-py3-none-any.whl.

File metadata

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

File hashes

Hashes for yagra-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 0d89e5401228a48dce5a7c555fe1df576035efa3a63d16eb40dd70f3536e5ce8
MD5 2b0140a916dae7a61593b91dc470e5b7
BLAKE2b-256 0191199aaa1f6bac1de33b2105dabd930abcf2947c28e60a83b34c15bb59ded2

See more details on using hashes here.

Provenance

The following attestation bundles were made for yagra-0.1.4-py3-none-any.whl:

Publisher: publish.yml on shogo-hs/Yagra

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