wizardflow 0.6.7__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wizardflow-0.6.7 → wizardflow-0.7.0}/.gitignore +1 -0
- wizardflow-0.7.0/PKG-INFO +230 -0
- wizardflow-0.7.0/README.md +183 -0
- wizardflow-0.7.0/docs/cli.md +118 -0
- wizardflow-0.7.0/docs/jsonl-file-format.md +184 -0
- wizardflow-0.7.0/docs/opentelemetry.md +302 -0
- wizardflow-0.7.0/docs/recording.md +258 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/pyproject.toml +1 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/__init__.py +77 -3
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/404.html +3 -3
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/__next.__PAGE__.txt +3 -3
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/__next._full.txt +6 -6
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/__next._head.txt +1 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/__next._index.txt +3 -3
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/__next._tree.txt +2 -2
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/0h4fa6bya_8s_.js → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/0d1yav018wi6n.js +1 -1
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/0fizjutis9uvx.js +120 -0
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/14a18doinx71t.css +1 -0
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/1diz-5jfxjm5x.js +1 -0
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/1por0fhggxwcm.js +19 -0
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/3lt2ss7dftc2n.css → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/24c18qa28ilul.css +1 -1
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/2dclsx_n3obic.js +1 -0
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/3kdn4z1bubx6o.js → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/2l6srvxdnb-io.js +1 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/18s31mhvm3v37.js → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/32c7h_m2amh5m.js +1 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/17lpwh4vr7yy-.js → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/352yh6c3r6-0k.js +1 -1
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/3fxdmyfsnxue6.js +131 -0
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/3q-c23s8gv3du.js +1 -0
- wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/3rdqn8rx95pw7.js +1 -0
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/35s_hwnpcd3sa.js → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/414c1-tn-1aef.js +4 -4
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/38u-dtit1x5gj.js → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/chunks/43x_68q2b6gcs.js +2 -2
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found/__next._full.txt +4 -4
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found/__next._head.txt +1 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found/__next._index.txt +3 -3
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found/__next._not-found/__PAGE__.txt +1 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found/__next._not-found.txt +1 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found/__next._tree.txt +1 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found.html +3 -3
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_not-found.txt +4 -4
- wizardflow-0.7.0/src/wizardflow/_ui/index.html +7 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/index.txt +6 -6
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/sitemap.xml +1 -1
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow/__next._full.txt +37 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow/__next._head.txt +6 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow/__next._index.txt +7 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow/__next._tree.txt +5 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow/__next.why-wizardflow/__PAGE__.txt +20 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow/__next.why-wizardflow.txt +5 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow.html +7 -0
- wizardflow-0.7.0/src/wizardflow/_ui/why-wizardflow.txt +37 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/cli.py +108 -2
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/client.py +597 -36
- wizardflow-0.7.0/src/wizardflow/otel.py +339 -0
- wizardflow-0.7.0/src/wizardflow/otel_file_exporter.py +141 -0
- wizardflow-0.7.0/src/wizardflow/otel_mapping.py +382 -0
- wizardflow-0.7.0/src/wizardflow/reader.py +272 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/tests/test_cli.py +38 -0
- wizardflow-0.7.0/tests/test_otel.py +415 -0
- wizardflow-0.7.0/tests/test_otel_file_exporter.py +78 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/tests/test_reader.py +92 -1
- {wizardflow-0.6.7 → wizardflow-0.7.0}/tests/test_trace.py +435 -0
- wizardflow-0.6.7/PKG-INFO +0 -552
- wizardflow-0.6.7/README.md +0 -505
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/04v6b5cii8amb.js +0 -121
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/07ut259iis1nt.js +0 -19
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/0rcl5uhziw0rb.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/0xty7ppkvnn_9.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/1p2cfk2pfta65.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/2bn76zw72neic.js +0 -122
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/2ovr9w8tatmai.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/3-4_ix1hbk5bi.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/33lom4053xb3g.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/_next/static/chunks/43u-gbx_f5fl7.js +0 -1
- wizardflow-0.6.7/src/wizardflow/_ui/index.html +0 -7
- wizardflow-0.6.7/src/wizardflow/reader.py +0 -134
- {wizardflow-0.6.7 → wizardflow-0.7.0}/CONTRIBUTING.md +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/LICENSE +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/assets/demo.gif +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/data_types.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/multibranch.html +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/multibranch.md +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/multibranch.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/quickstart.html +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/quickstart.md +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/examples/quickstart.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/scripts/build_ui.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/scripts/live_trace_demo.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_render.py +0 -0
- {wizardflow-0.6.7/src/wizardflow/_ui/_next/static/Turmu90w9F5mwvKyfszeR → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/H81QsKAgLXQMK2H6vyBjb}/_buildManifest.js +0 -0
- {wizardflow-0.6.7/src/wizardflow/_ui/_next/static/Turmu90w9F5mwvKyfszeR → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/H81QsKAgLXQMK2H6vyBjb}/_clientMiddlewareManifest.js +0 -0
- {wizardflow-0.6.7/src/wizardflow/_ui/_next/static/Turmu90w9F5mwvKyfszeR → wizardflow-0.7.0/src/wizardflow/_ui/_next/static/H81QsKAgLXQMK2H6vyBjb}/_ssgManifest.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/05-c3ty_6dwfk.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/09s72r58ijxwx.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/0cz1d0mv5g_q7.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/14mrh2-p_w84d.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/18clj6xsyhc_j.css +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/1_way7swvumpv.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/2-j1b74l3lxxu.css +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/27jktro2p5rq9.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/2gj5bmeov-r8f.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/310vm2bl3xxpt.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/3n7dm2ojtyzwn.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/chunks/turbopack-2fblmukzx7kws.js +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/4fa387ec64143e14-s.2tuy5pz7dlieh.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/53b9e256198e5412-s.390ncx5urfkfu.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/5ce348bf30bf5439-s.31988l_ccedte.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/6306c77e7c8268e4-s.2dbetqa9o8jxf.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/7178b3e590c64307-s.21jp631_3pja2.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/797e433ab948586e-s.p.0r6juujl39pe6.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/7d817b4c03b0c5f1-s.1uyisp29ctx0d.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/8a480f0b521d4e75-s.1qq4vpdcun5oj.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/bbc41e54d2fcbd21-s.1rgnod-3esatf.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/caa3a2e1cccd8315-s.p.0wgildi0cnwt9.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/fef07dbb0973bf53-s.3p2_lha1f2xer.woff2 +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/_next/static/media/icon.09qublg69ek7b.svg +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/icon.svg +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/opengraph-image +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/_ui/robots.txt +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/constants.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/html.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/markdown.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/src/wizardflow/py.typed +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/tests/conftest.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/tests/test_html.py +0 -0
- {wizardflow-0.6.7 → wizardflow-0.7.0}/tests/test_markdown.py +0 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: wizardflow
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Python SDK for recording agent flows into the WizardFlow / AgentTrace file format.
|
|
5
|
+
Project-URL: Homepage, https://getwizardflow.com
|
|
6
|
+
Project-URL: Documentation, https://getwizardflow.com
|
|
7
|
+
Author: Leon Koch
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Leon Koch
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Keywords: agents,langgraph,llm,observability,tracing
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Operating System :: OS Independent
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
42
|
+
Classifier: Typing :: Typed
|
|
43
|
+
Requires-Python: >=3.9
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# WizardFlow Python SDK
|
|
49
|
+
|
|
50
|
+
**A lightweight recorder for Python agents.** WizardFlow turns an agent run
|
|
51
|
+
into a portable WizardFlow JSONL file that you can replay as an interactive
|
|
52
|
+
graph, inspect with ordinary tools, or attach to a bug report.
|
|
53
|
+
|
|
54
|
+
Drop the file into [getwizardflow.com](https://getwizardflow.com) and it is
|
|
55
|
+
processed entirely in the browser—nothing is uploaded. You can also replay it
|
|
56
|
+
locally with `wizardflow ui`.
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
â–¶ **[Watch this run replay](https://getwizardflow.com/?example=doctor-consultation)**
|
|
61
|
+
|
|
62
|
+
## Why WizardFlow?
|
|
63
|
+
|
|
64
|
+
- **The trace is a file.** Commit, diff, grep, archive, or share it without an
|
|
65
|
+
observability account.
|
|
66
|
+
- **Replay it anywhere.** Use the bundled local viewer or the fully client-side
|
|
67
|
+
hosted viewer.
|
|
68
|
+
- **Zero runtime dependencies.** The base SDK is pure Python and requires no
|
|
69
|
+
daemon or framework.
|
|
70
|
+
- **Explicit by design.** Your code chooses which node executions and values
|
|
71
|
+
enter the trace.
|
|
72
|
+
- **OpenTelemetry is optional.** The same node executions can also be projected
|
|
73
|
+
to OTLP-compatible observability backends.
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install wizardflow
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quickstart
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
import uuid
|
|
85
|
+
|
|
86
|
+
import wizardflow
|
|
87
|
+
|
|
88
|
+
trace = wizardflow.init(
|
|
89
|
+
output_dir="traces",
|
|
90
|
+
file_prefix="run",
|
|
91
|
+
nodes=["generator"],
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
message_id = str(uuid.uuid4())
|
|
95
|
+
input_value = ...
|
|
96
|
+
|
|
97
|
+
with trace.node(message_id, "generator") as node:
|
|
98
|
+
node.log_input(input_value)
|
|
99
|
+
output_value = ...
|
|
100
|
+
node.log_output(output_value)
|
|
101
|
+
|
|
102
|
+
trace_path = trace.end_message(message_id)
|
|
103
|
+
print(trace_path)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`trace.node(...)` records the node's execution interval. `log_input()` and
|
|
107
|
+
`log_output()` preserve their JSON-compatible values in the trace, and
|
|
108
|
+
`end_message()` appends the completed message to JSONL. There is no separate
|
|
109
|
+
`save()` call.
|
|
110
|
+
|
|
111
|
+
Drop `trace_path` into [getwizardflow.com](https://getwizardflow.com), or open
|
|
112
|
+
it locally:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
wizardflow ui traces/run__<timestamp>.jsonl
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The module-level style remains available for applications that use one default
|
|
119
|
+
trace:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
wizardflow.init(nodes=["generator"])
|
|
123
|
+
|
|
124
|
+
with wizardflow.node("msg-1", "generator") as node:
|
|
125
|
+
node.log_input(input_value)
|
|
126
|
+
node.log_output(output_value)
|
|
127
|
+
|
|
128
|
+
wizardflow.end_message("msg-1")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Optional OpenTelemetry export
|
|
132
|
+
|
|
133
|
+
Install the optional OTel packages directly:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Then enable OTLP trace export while retaining JSONL as the portable source of
|
|
140
|
+
truth:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
trace = wizardflow.init(
|
|
144
|
+
nodes=["generator"],
|
|
145
|
+
name="my-agent",
|
|
146
|
+
otel=True,
|
|
147
|
+
otel_endpoint="http://localhost:4318/v1/traces",
|
|
148
|
+
otel_trace_scope="message",
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
with trace.node("msg-1", "generator", kind="llm") as node:
|
|
152
|
+
node.log_input(input_value)
|
|
153
|
+
node.log_output(output_value)
|
|
154
|
+
|
|
155
|
+
trace.end_message("msg-1")
|
|
156
|
+
trace.close_otel()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Generic logs can optionally choose an exact application-owned span attribute
|
|
160
|
+
without changing their JSONL/UI label:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
node.log("quality", 0.92, otel_attribute="app.response.quality")
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Content export is privacy-conscious and disabled by default. See the
|
|
167
|
+
[OpenTelemetry guide](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/opentelemetry.md)
|
|
168
|
+
for provider ownership, GenAI mappings, content controls, graph events, and
|
|
169
|
+
independent JSONL/OTel lifecycles. Existing artifacts can be exported later:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
wizardflow otel export run.jsonl --endpoint http://localhost:4318/v1/traces
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## LangGraph topology
|
|
176
|
+
|
|
177
|
+
WizardFlow can read nodes and edges from a compiled LangGraph application
|
|
178
|
+
without importing LangGraph itself:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
trace = wizardflow.init_from_langgraph(
|
|
182
|
+
compiled_app,
|
|
183
|
+
output_dir="traces",
|
|
184
|
+
file_prefix="run",
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Runtime recording then uses the same `trace.node(...)` API. Extraction is
|
|
189
|
+
duck-typed through `app.get_graph()`.
|
|
190
|
+
|
|
191
|
+
## Documentation
|
|
192
|
+
|
|
193
|
+
- **[Recording agent runs](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/recording.md)**
|
|
194
|
+
— messages, node scopes, semantic records, generic logs, kinds, output
|
|
195
|
+
selection, multiple clients, and reinitialization.
|
|
196
|
+
- **[OpenTelemetry export](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/opentelemetry.md)**
|
|
197
|
+
— OTLP setup, provider ownership, GenAI mappings, privacy controls, graph
|
|
198
|
+
events, offline JSONL export, and cleanup.
|
|
199
|
+
- **[WizardFlow JSONL format](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/jsonl-file-format.md)**
|
|
200
|
+
— record shapes, semantic fields, compatibility, and rotation.
|
|
201
|
+
- **[CLI and local viewer](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/cli.md)**
|
|
202
|
+
— live local replay and Markdown, HTML, and JSON export.
|
|
203
|
+
|
|
204
|
+
## CLI at a glance
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
wizardflow ui run.jsonl # interactive local replay
|
|
208
|
+
wizardflow ui --latest traces/ # newest trace in a directory
|
|
209
|
+
wizardflow md run.jsonl -o run.md # Markdown export
|
|
210
|
+
wizardflow html run.jsonl -o run.html
|
|
211
|
+
wizardflow json run.jsonl -o run.json
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
All commands read both WizardFlow JSONL and the single-document JSON form. See
|
|
215
|
+
the [CLI guide](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/cli.md)
|
|
216
|
+
for flags, live-trace behavior, and rotated-part navigation.
|
|
217
|
+
|
|
218
|
+
## Examples
|
|
219
|
+
|
|
220
|
+
Runnable examples live in
|
|
221
|
+
[`examples/`](https://github.com/lkleonk/wizardflow/tree/main/sdk/python/examples):
|
|
222
|
+
|
|
223
|
+
- `quickstart.py` records a small linear flow.
|
|
224
|
+
- `multibranch.py` records two messages that take different graph branches.
|
|
225
|
+
|
|
226
|
+
## Development
|
|
227
|
+
|
|
228
|
+
See
|
|
229
|
+
[CONTRIBUTING.md](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/CONTRIBUTING.md)
|
|
230
|
+
for local tests and maintainer workflows.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# WizardFlow Python SDK
|
|
2
|
+
|
|
3
|
+
**A lightweight recorder for Python agents.** WizardFlow turns an agent run
|
|
4
|
+
into a portable WizardFlow JSONL file that you can replay as an interactive
|
|
5
|
+
graph, inspect with ordinary tools, or attach to a bug report.
|
|
6
|
+
|
|
7
|
+
Drop the file into [getwizardflow.com](https://getwizardflow.com) and it is
|
|
8
|
+
processed entirely in the browser—nothing is uploaded. You can also replay it
|
|
9
|
+
locally with `wizardflow ui`.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
â–¶ **[Watch this run replay](https://getwizardflow.com/?example=doctor-consultation)**
|
|
14
|
+
|
|
15
|
+
## Why WizardFlow?
|
|
16
|
+
|
|
17
|
+
- **The trace is a file.** Commit, diff, grep, archive, or share it without an
|
|
18
|
+
observability account.
|
|
19
|
+
- **Replay it anywhere.** Use the bundled local viewer or the fully client-side
|
|
20
|
+
hosted viewer.
|
|
21
|
+
- **Zero runtime dependencies.** The base SDK is pure Python and requires no
|
|
22
|
+
daemon or framework.
|
|
23
|
+
- **Explicit by design.** Your code chooses which node executions and values
|
|
24
|
+
enter the trace.
|
|
25
|
+
- **OpenTelemetry is optional.** The same node executions can also be projected
|
|
26
|
+
to OTLP-compatible observability backends.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install wizardflow
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quickstart
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import uuid
|
|
38
|
+
|
|
39
|
+
import wizardflow
|
|
40
|
+
|
|
41
|
+
trace = wizardflow.init(
|
|
42
|
+
output_dir="traces",
|
|
43
|
+
file_prefix="run",
|
|
44
|
+
nodes=["generator"],
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
message_id = str(uuid.uuid4())
|
|
48
|
+
input_value = ...
|
|
49
|
+
|
|
50
|
+
with trace.node(message_id, "generator") as node:
|
|
51
|
+
node.log_input(input_value)
|
|
52
|
+
output_value = ...
|
|
53
|
+
node.log_output(output_value)
|
|
54
|
+
|
|
55
|
+
trace_path = trace.end_message(message_id)
|
|
56
|
+
print(trace_path)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`trace.node(...)` records the node's execution interval. `log_input()` and
|
|
60
|
+
`log_output()` preserve their JSON-compatible values in the trace, and
|
|
61
|
+
`end_message()` appends the completed message to JSONL. There is no separate
|
|
62
|
+
`save()` call.
|
|
63
|
+
|
|
64
|
+
Drop `trace_path` into [getwizardflow.com](https://getwizardflow.com), or open
|
|
65
|
+
it locally:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
wizardflow ui traces/run__<timestamp>.jsonl
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The module-level style remains available for applications that use one default
|
|
72
|
+
trace:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
wizardflow.init(nodes=["generator"])
|
|
76
|
+
|
|
77
|
+
with wizardflow.node("msg-1", "generator") as node:
|
|
78
|
+
node.log_input(input_value)
|
|
79
|
+
node.log_output(output_value)
|
|
80
|
+
|
|
81
|
+
wizardflow.end_message("msg-1")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Optional OpenTelemetry export
|
|
85
|
+
|
|
86
|
+
Install the optional OTel packages directly:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Then enable OTLP trace export while retaining JSONL as the portable source of
|
|
93
|
+
truth:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
trace = wizardflow.init(
|
|
97
|
+
nodes=["generator"],
|
|
98
|
+
name="my-agent",
|
|
99
|
+
otel=True,
|
|
100
|
+
otel_endpoint="http://localhost:4318/v1/traces",
|
|
101
|
+
otel_trace_scope="message",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
with trace.node("msg-1", "generator", kind="llm") as node:
|
|
105
|
+
node.log_input(input_value)
|
|
106
|
+
node.log_output(output_value)
|
|
107
|
+
|
|
108
|
+
trace.end_message("msg-1")
|
|
109
|
+
trace.close_otel()
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Generic logs can optionally choose an exact application-owned span attribute
|
|
113
|
+
without changing their JSONL/UI label:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
node.log("quality", 0.92, otel_attribute="app.response.quality")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Content export is privacy-conscious and disabled by default. See the
|
|
120
|
+
[OpenTelemetry guide](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/opentelemetry.md)
|
|
121
|
+
for provider ownership, GenAI mappings, content controls, graph events, and
|
|
122
|
+
independent JSONL/OTel lifecycles. Existing artifacts can be exported later:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
wizardflow otel export run.jsonl --endpoint http://localhost:4318/v1/traces
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## LangGraph topology
|
|
129
|
+
|
|
130
|
+
WizardFlow can read nodes and edges from a compiled LangGraph application
|
|
131
|
+
without importing LangGraph itself:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
trace = wizardflow.init_from_langgraph(
|
|
135
|
+
compiled_app,
|
|
136
|
+
output_dir="traces",
|
|
137
|
+
file_prefix="run",
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Runtime recording then uses the same `trace.node(...)` API. Extraction is
|
|
142
|
+
duck-typed through `app.get_graph()`.
|
|
143
|
+
|
|
144
|
+
## Documentation
|
|
145
|
+
|
|
146
|
+
- **[Recording agent runs](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/recording.md)**
|
|
147
|
+
— messages, node scopes, semantic records, generic logs, kinds, output
|
|
148
|
+
selection, multiple clients, and reinitialization.
|
|
149
|
+
- **[OpenTelemetry export](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/opentelemetry.md)**
|
|
150
|
+
— OTLP setup, provider ownership, GenAI mappings, privacy controls, graph
|
|
151
|
+
events, offline JSONL export, and cleanup.
|
|
152
|
+
- **[WizardFlow JSONL format](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/jsonl-file-format.md)**
|
|
153
|
+
— record shapes, semantic fields, compatibility, and rotation.
|
|
154
|
+
- **[CLI and local viewer](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/cli.md)**
|
|
155
|
+
— live local replay and Markdown, HTML, and JSON export.
|
|
156
|
+
|
|
157
|
+
## CLI at a glance
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
wizardflow ui run.jsonl # interactive local replay
|
|
161
|
+
wizardflow ui --latest traces/ # newest trace in a directory
|
|
162
|
+
wizardflow md run.jsonl -o run.md # Markdown export
|
|
163
|
+
wizardflow html run.jsonl -o run.html
|
|
164
|
+
wizardflow json run.jsonl -o run.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
All commands read both WizardFlow JSONL and the single-document JSON form. See
|
|
168
|
+
the [CLI guide](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/docs/cli.md)
|
|
169
|
+
for flags, live-trace behavior, and rotated-part navigation.
|
|
170
|
+
|
|
171
|
+
## Examples
|
|
172
|
+
|
|
173
|
+
Runnable examples live in
|
|
174
|
+
[`examples/`](https://github.com/lkleonk/wizardflow/tree/main/sdk/python/examples):
|
|
175
|
+
|
|
176
|
+
- `quickstart.py` records a small linear flow.
|
|
177
|
+
- `multibranch.py` records two messages that take different graph branches.
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
See
|
|
182
|
+
[CONTRIBUTING.md](https://github.com/lkleonk/wizardflow/blob/main/sdk/python/CONTRIBUTING.md)
|
|
183
|
+
for local tests and maintainer workflows.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# CLI and local viewer
|
|
2
|
+
|
|
3
|
+
The `wizardflow` command reads both WizardFlow JSONL parts and the legacy
|
|
4
|
+
single-document JSON representation.
|
|
5
|
+
|
|
6
|
+
## Selecting a trace
|
|
7
|
+
|
|
8
|
+
Every subcommand accepts a trace as a positional argument or through `--path`:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
wizardflow ui run.jsonl
|
|
12
|
+
wizardflow ui --path run.jsonl
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Use `--latest` to select the most recently modified `.jsonl` or `.json` file in
|
|
16
|
+
a directory:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
wizardflow ui --latest
|
|
20
|
+
wizardflow ui --latest traces/
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Local interactive viewer
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
wizardflow ui run.jsonl [--host 127.0.0.1] [--port 0] [--no-open]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This starts a standard-library HTTP server and serves the static WizardFlow UI
|
|
30
|
+
bundled in the package.
|
|
31
|
+
|
|
32
|
+
| Option | Default | Meaning |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `--latest` | off | Treat the path as a directory and choose its newest trace |
|
|
35
|
+
| `--host` | `127.0.0.1` | Interface to bind |
|
|
36
|
+
| `--port` | `0` | Port to bind; zero asks the OS for a free port |
|
|
37
|
+
| `--no-open` | off | Print the URL instead of opening a browser |
|
|
38
|
+
|
|
39
|
+
The viewer follows a growing active part using ETag revalidation. Polling pauses
|
|
40
|
+
while the tab is hidden and stops when the part gains `nextPart`, because a
|
|
41
|
+
sealed part no longer grows. Part navigation loads neighboring files rather
|
|
42
|
+
than stitching the entire rotation chain into one timeline.
|
|
43
|
+
|
|
44
|
+
## Markdown export
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
wizardflow md run.jsonl
|
|
48
|
+
wizardflow md run.jsonl -o run.md
|
|
49
|
+
wizardflow md run.jsonl --no-mermaid
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Markdown output includes metadata, an optional Mermaid graph, messages, steps,
|
|
53
|
+
and payloads.
|
|
54
|
+
|
|
55
|
+
| Option | Meaning |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `-o`, `--output` | Write to a file instead of stdout |
|
|
58
|
+
| `--mermaid` | Include the graph diagram; enabled by default |
|
|
59
|
+
| `--no-mermaid` | Omit the graph diagram |
|
|
60
|
+
|
|
61
|
+
## HTML export
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
wizardflow html run.jsonl
|
|
65
|
+
wizardflow html run.jsonl -o run.html
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This produces one self-contained document with inline CSS, no JavaScript, and
|
|
69
|
+
no external assets. It renders messages and payloads; use Markdown when a graph
|
|
70
|
+
diagram is required.
|
|
71
|
+
|
|
72
|
+
## Assemble JSONL into JSON
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
wizardflow json run.jsonl
|
|
76
|
+
wizardflow json run.jsonl -o run.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This assembles the selected part's header and message records into one
|
|
80
|
+
pretty-printed WizardFlow trace. A seal's `nextPart` is folded into metadata. It
|
|
81
|
+
does not combine an entire rotation chain.
|
|
82
|
+
|
|
83
|
+
## Export JSONL to OpenTelemetry
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
wizardflow otel export run.jsonl --endpoint http://localhost:4318/v1/traces
|
|
87
|
+
wizardflow otel export run.jsonl --trace-scope message
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This projects an existing artifact through OTLP/HTTP using the same semantic
|
|
91
|
+
mapping as live export. It creates fresh OTel trace IDs and never modifies the
|
|
92
|
+
source file. By default it discovers and exports the complete rotated
|
|
93
|
+
part-chain and creates one `wizardflow.run` trace; `--trace-scope message`
|
|
94
|
+
creates one `wizardflow.message` trace per message.
|
|
95
|
+
|
|
96
|
+
| Option | Default | Meaning |
|
|
97
|
+
| --- | --- | --- |
|
|
98
|
+
| `--endpoint` | OTel environment | OTLP/HTTP traces endpoint |
|
|
99
|
+
| `--trace-scope` | `recording` | `recording` or `message` trace boundaries |
|
|
100
|
+
| `--include-content` | off | Export bounded input, output, and structured log content |
|
|
101
|
+
| `--content-max-bytes` | `16_384` | Maximum bytes for each exported content value |
|
|
102
|
+
| `--export-graph` | off | Add the WizardFlow graph event to each root |
|
|
103
|
+
| `--graph-max-bytes` | `65_536` | Maximum full graph-event content size |
|
|
104
|
+
| `--current-part-only` | off | Export only the named rotation part |
|
|
105
|
+
|
|
106
|
+
When `--endpoint` is omitted, the command reads
|
|
107
|
+
`OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`, then `OTEL_EXPORTER_OTLP_ENDPOINT`.
|
|
108
|
+
See [opentelemetry.md](opentelemetry.md) for installation, privacy, and mapping
|
|
109
|
+
details.
|
|
110
|
+
|
|
111
|
+
## Live traces and rotated parts
|
|
112
|
+
|
|
113
|
+
`end_message()` appends one durable line, so `wizardflow ui` can show messages
|
|
114
|
+
while the process is still recording. When the active part rotates, its seal
|
|
115
|
+
points to the next filename. The local server resolves only plain sibling part
|
|
116
|
+
names from the trace directory; UI assets always take precedence.
|
|
117
|
+
|
|
118
|
+
See [jsonl-file-format.md](jsonl-file-format.md) for the record and rotation schema.
|