KWIP
Technology /

Traversal 0.2.0 · MIT

Python functions.
Connected.

A small graph engine for work that branches, waits, and joins. Write the functions. Traversal handles their dependencies and concurrent execution.

Free and open source. Rust core. No service to run.

A dependency graph branches from fetch into parse and inspect. Report joins both branches before save can run.
Independent work moves together.Dependent work waits.

Ordinary PythonFunctions and existing tools

Rust schedulingReady queues and dependency state

Local historyOpt-in SQLite on your machine

Explicit reuseYour keys. Inspectable decisions.

A graph, without a framework

Keep your functions.
Connect the work.

A node is a function call. Pass one node’s result into another to define a dependency. Request an output, and Traversal runs the work needed to produce it.

The two branches below can run together. The total waits for both.

Read the complete API →
report.pyPython + Traversal
from traversal import Graph

graph = Graph("report")
source = graph.add("source", lambda: 5)
left = graph.add("left", lambda n: n * 2, source)
right = graph.add("right", lambda n: n + 3, source)
total = graph.add("total", sum, [left, right])

plan = graph.compile(total)
report = plan.run(max_concurrency=2)
report.raise_for_status()
print(report.outputs["total"])  # 18
4 nodes succeeded total → 18

Execution you can inspect

Know what can run.
Know what happened.

01

Start when the inputs are ready

Independent branches overlap up to your concurrency limit. Completion releases dependents immediately. Async functions use the event loop; blocking calls use threads.

02

Find the last attempt, or the last success

Opt into a local history store for run IDs, node outcomes, and timestamps. Inspect failures by node. Incomplete work stays visible; a read never silently declares a run abandoned.

03

Reuse with a reason

Declare repeat-safe computations with explicit cache keys. Preview which results can be reused. Resume creates a linked run and asks for a decision before repeating previously started, undeclared work.

New in 0.2.0

More cores.
The same graph.

Independent Python computations can now run across CPU cores with free-threaded Python 3.14t. Keep your functions and concurrency limit. The skill walks your agent through setup and checks that the GIL stays disabled.

Rust handles bulk graph work outside the interpreter. Regular Python remains supported for everyday tool calls and I/O.

Read the measurements and limits →
Four independent chunks execute on four CPU worker lanes, then join into one result. Free-threaded Python enables the CPU branches to overlap.
Independent CPU branches.One joined result.

A little memory. On your machine.

The next run starts
with context.

Keep durable run metadata in SQLite. Persist JSON results only for tasks that opt into caching. No account, hosted collector, or automatic telemetry.

History and recovery details ↗
plan.explain_run(previous=run_id)Illustrative output
sourcereuseCompatible persisted result
normalizereuseCompatible persisted result
publishdecisionPreviously started; repeat safety undeclared

Unknown external effects are never silently replayed.

Get started

One install.
Your next graph.

Install in your project’s Python environment. Supported wheels include the native engine, so you don’t need Rust installed.

python -m pip install 'traversal==0.2.0'

CPython 3.11–3.14 + free-threaded 3.14t · Linux x86_64 (glibc 2.28+) · macOS Apple Silicon · Windows x86_64. Other platforms require a source build and are not part of the tested wheel matrix.

A focused component.

Traversal owns graph structure, node readiness, execution state, local history, and explicit reuse. Your Python handles APIs, files, and business logic. Your scheduler decides when a run starts.

Regular Python retains its GIL for Python CPU tasks. Free-threaded 3.14t can execute independent synchronous branches on multiple cores. Shared mutable values need caller coordination; blocking calls need their own I/O timeouts. Cache keys are caller-maintained; results must be finite JSON values to persist. Cancellation cannot undo an external action. There are no distributed workers or exactly-once guarantees.

Read the supported behavior and limits →