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 と実行
registry は dict[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 YAMLregistry:NodeRegistryPort実装、またはdict[str, callable]bundle_root: 分割参照解決の基準ディレクトリ(省略時は workflow の親)state_schema: LangGraph の状態スキーマ(既定dict)
Yagra.invoke(...)
Yagra.invoke(state: Mapping[str, Any]) -> dict[str, Any]
仕様上の契約(Implicit Contracts)
1. 条件分岐の契約
edges[].conditionは分岐ラベルです。- 分岐元ノードは
{"__next__": "<condition-label>"}を state update として返します。 - 例:
condition: "faq"がある場合、__next__は"faq"を返す必要があります。
2. catalog 参照解決の契約
prompt_ref/model_refは実行前に解決されます。- handler が受け取る
paramsには解決済み値が入ります。params["prompt"]params["model"]
- 参照形式:
<key>(workflow.params.prompt_catalog/model_catalogを使用)<path>#<key.path>(明示参照)
例:
params:
prompt_catalog: "../prompts/support_prompts.yaml"
model_catalog: "../models/openai_models.yaml"
nodes:
- id: planner
handler: planner_loop_handler
params:
prompt_ref: planner
model_ref: default
3. end_at の挙動
end_atは「終了ノードIDのリスト」です(複数可)。- Yagra は各ノードを LangGraph の finish point として登録します。
- YAML 上で
ENDという特別ノードを直接書く仕様ではありません。
4. ノード関数シグネチャ
Yagra は次の順で呼び出しを試みます。
handler(state, params)handler(state)
YAML 仕様(要点)
トップレベル:
version: strstart_at: strend_at: list[str]nodes: list[NodeSpec]edges: list[EdgeSpec]params: dict[str, Any](任意)
NodeSpec:
id: strhandler: strparams: dict[str, Any](任意)
EdgeSpec:
source: strtarget: strcondition: str | null(任意)
同梱サンプル
examples/workflows/branch-inline.yaml- 条件分岐の最小例
examples/workflows/loop-split.yaml- ループ + 条件分岐 +
prompt_ref/model_ref分割参照
- ループ + 条件分岐 +
examples/prompts/support_prompts.yamlexamples/models/openai_models.yaml
開発コマンド
uv run ruff check .
uv run mypy .
uv run pytest -q
uv run pre-commit run --all-files
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 の
pypienvironment が利用可能である - Git タグ(
vX.Y.Z)とpyproject.tomlのversionを一致させる
リリース実行例:
git tag v0.1.1
git push origin v0.1.1
ライセンスと変更履歴
- ライセンス:
LICENSE(MIT) - 変更履歴:
CHANGELOG.md
エージェント実行規約
エージェント運用ルールは AGENTS.md を参照してください。
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yagra-0.1.0.tar.gz.
File metadata
- Download URL: yagra-0.1.0.tar.gz
- Upload date:
- Size: 157.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d3355ed059cf4b71429fd0c33d26cbf006d5298e5df4c36d63bd49f609a200e
|
|
| MD5 |
5c549c77588a014c757dcc17ec3dd3ae
|
|
| BLAKE2b-256 |
9458f1890453417bb0792f9fbaa4d530ba3b960989bf9569b48988997e3af9bf
|
Provenance
The following attestation bundles were made for yagra-0.1.0.tar.gz:
Publisher:
publish.yml on shogo-hs/Yagra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
yagra-0.1.0.tar.gz -
Subject digest:
1d3355ed059cf4b71429fd0c33d26cbf006d5298e5df4c36d63bd49f609a200e - Sigstore transparency entry: 948210996
- Sigstore integration time:
-
Permalink:
shogo-hs/Yagra@26f147fc85a0ab2bc3c0c9517ce82d960fd66be8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/shogo-hs
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@26f147fc85a0ab2bc3c0c9517ce82d960fd66be8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file yagra-0.1.0-py3-none-any.whl.
File metadata
- Download URL: yagra-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df6d4b1807193678cfe1aa5f596010354be11b2fa2684848523e40b6e4d1f08e
|
|
| MD5 |
b8950755c8afdea4ecafc06b9011f23a
|
|
| BLAKE2b-256 |
a9e359850aea3ae6409009bed3d97dfa6774db5db20f35bd773f535808d7202c
|
Provenance
The following attestation bundles were made for yagra-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on shogo-hs/Yagra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
yagra-0.1.0-py3-none-any.whl -
Subject digest:
df6d4b1807193678cfe1aa5f596010354be11b2fa2684848523e40b6e4d1f08e - Sigstore transparency entry: 948211046
- Sigstore integration time:
-
Permalink:
shogo-hs/Yagra@26f147fc85a0ab2bc3c0c9517ce82d960fd66be8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/shogo-hs
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@26f147fc85a0ab2bc3c0c9517ce82d960fd66be8 -
Trigger Event:
push
-
Statement type: