A structured graph runtime for Python and TypeScript.
Sley is a fork of Caskada. It keeps that history visible while taking the graph runtime forward under its own package and project identity.
Sley runs ordinary functions as nodes in nested directed graphs. It provides explicit branching, structured fan-out and joining, retries, recovery, local concurrency, and typed execution results without depending on an LLM provider or application framework.
Why Sley
A sley is the moving loom frame that carries the reed, keeps warp threads separated, and advances the fabric. To sley also means threading the warp in a prescribed pattern. The analogy is direct: the graph defines the pattern, branches and state are the threads, Sley executes their arrangement, and a completed run is the woven result.
Install
pip install sley
npm install @jigging/sley
Python 3.13 or newer is required. The TypeScript package ships ESM and CommonJS builds.
Python
import asyncio
from sley import Flow, node
@node
def normalize(context):
context.state["question"] = context.state["question"].strip()
@node
def answer(context):
context.state["answer"] = f"You asked: {context.state['question']}"
normalize.link(answer)
async def main() -> None:
state = await Flow(normalize).run({"question": " Why? "})
print(state["answer"])
asyncio.run(main())
TypeScript
import { Flow, node } from '@jigging/sley'
interface State {
question: string
answer?: string
}
const normalize = node<State>((context) => {
context.state.question = context.state.question.trim()
})
const answer = node<State>((context) => {
context.state.answer = `You asked: ${context.state.question}`
})
normalize.link(answer)
const state = await new Flow(normalize).run({ question: ' Why? ' })
console.log(state.answer)
Both programs print You asked: Why?.
Core Model
Nodes
node(handler) turns a function into one graph occurrence. A handler receives
one Context and returns no application value.
@node
def decide(context):
if needs_review(context.state):
context.emit("review")
Nodes connect target first:
decide.link(review, "review")
decide.link(publish) # unlabelled link
The equivalent TypeScript spelling is identical:
decide.link(review, 'review')
decide.link(publish)
Control
context.emit()selects the unlabelled link.context.emit("review")selects a named link.context.emit("work", item)also supplies the next branch'scontext.input.- A successful normal handler with no control call behaves like one implicit
emit(). context.end(value)creates a hard terminal for the current branch and bypasses links. It does not stop the handler function, so use a normalreturnwhen later statements should not run.
Several control calls create a buffered fan-out. Sley commits that buffer only after the handler returns normally; state writes and external effects are not rolled back.
Data
context.state is the one mutable top-level map shared by every branch in one
run. Sley shallow-copies the caller's initial mapping once, so run() returns
the authoritative final state and does not mutate the caller's top-level map.
Nested values remain shared references.
context.input is the value carried by one branch. Omitted input forwards the
current input. Sley preserves application values but does not validate their
schema or prove payload compatibility between links.
Flows And Combine
A Flow is a structured scope. It waits until all of its branches settle, then
optionally invokes one combine callback.
def combine(context, result):
context.state["total"] = sum(result.outputs)
batch = Flow(dispatch, combine=combine, concurrency=8)
Worker branches publish values with context.end(value). The combiner reads
those values through result.outputs. Zero combiner emissions preserve the
original terminals; one or more emissions replace them with new outward
continuations.
Results
await flow.run(initial_state) is the simple API. It returns the final state for
every completed run and raises RunError on failure. The error retains the
failed result and exposes a controlling application error through standard
native exception chaining.
flow.start(initial_state) returns a RunHandle whose result() method exposes
the completed or failed result, including state and settled terminals.
Learn
License
Sley is licensed under the Mozilla Public License 2.0.
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 sley-0.0.2.tar.gz.
File metadata
- Download URL: sley-0.0.2.tar.gz
- Upload date:
- Size: 15.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a527fdea29988bb7f71a5c52132109891212c57851867dcd5eaa766a5504b73
|
|
| MD5 |
bd37be31f9c9b64e5ebc58224b122cd1
|
|
| BLAKE2b-256 |
0c5ae03c74973b72e7d9bdb25a4c306d3e44ee949d372da0cd56095606344cbe
|
Provenance
The following attestation bundles were made for sley-0.0.2.tar.gz:
Publisher:
python-publish.yml on jigmd/sley
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sley-0.0.2.tar.gz -
Subject digest:
6a527fdea29988bb7f71a5c52132109891212c57851867dcd5eaa766a5504b73 - Sigstore transparency entry: 2581963632
- Sigstore integration time:
-
Permalink:
jigmd/sley@5fe2735e2d78fba27e4fc966cd6ba17883927655 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jigmd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5fe2735e2d78fba27e4fc966cd6ba17883927655 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sley-0.0.2-py3-none-any.whl.
File metadata
- Download URL: sley-0.0.2-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a3618ba254a848f580580e58b1d04e71e1ed31ac8ec31cc7fc66174b01b5846
|
|
| MD5 |
aa52707201c2469f6ac1a279f5778b4e
|
|
| BLAKE2b-256 |
16f1f0f5975108f7f967e84b45e92a8fbeb535e3256738b301cf7f7469a9b102
|
Provenance
The following attestation bundles were made for sley-0.0.2-py3-none-any.whl:
Publisher:
python-publish.yml on jigmd/sley
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sley-0.0.2-py3-none-any.whl -
Subject digest:
6a3618ba254a848f580580e58b1d04e71e1ed31ac8ec31cc7fc66174b01b5846 - Sigstore transparency entry: 2581963638
- Sigstore integration time:
-
Permalink:
jigmd/sley@5fe2735e2d78fba27e4fc966cd6ba17883927655 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jigmd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@5fe2735e2d78fba27e4fc966cd6ba17883927655 -
Trigger Event:
push
-
Statement type: