Quickstart
Create a stream, run it, see the output it shares with other streams and agents, and change it while it runs. About five minutes once Tatolab is installed.
You’ll create a project with tatolab new, run its stream, see the output it shares, and change the stream while it runs.
Before you start
Section titled “Before you start”You need three things:
-
Tatolab installed, with its runtime running. Check with:
Terminal window tatolab streamsIf it prints
No streams in this runtime., you’re ready. If it saysno runtime is running on this machine, see Install Tatolab. If you built from source, the runtime istatolabdrunning in a terminal of its own: keep it running, and use another terminal for the steps below. -
uv, the Python package manager.
uv --versionshould print a version. If it doesn’t, see Install uv. -
A camera. No camera on this machine? Add
--test-patternin step 1 and the stream uses color bars instead.
1. Create a project
Section titled “1. Create a project”tatolab new my-streamCreated a Tatolab stream project in `my-stream`.
Next: cd my-stream uv sync tatolab devIt wrote a small stream: your camera, through an effect that inverts its colors, exposed so other programs can read it. It also opens a window, so you can see the result while you test, and logs the picture’s brightness once a second:
my-stream/├── stream.py the stream: which nodes, and how they connect├── nodes/│ ├── __init__.py│ ├── inverting_effect.py inverts the picture's colors│ └── brightness_meter.py logs the picture's brightness├── pyproject.toml depends on tatolab-stream and numpy├── .python-version 3.12└── .gitignoretatolab new refuses to write into a directory that already has these files, so it never overwrites your work.
2. Install the project’s dependencies
Section titled “2. Install the project’s dependencies”cd my-streamuv syncThis creates .venv/ inside the project, with Python 3.12, tatolab-stream and numpy. The runtime runs your nodes with this environment’s Python, so a package you add with uv add is available to every node in the project.
3. Run it
Section titled “3. Run it”tatolab devA test window opens with the effect’s output: your camera, colors inverted. The terminal says the stream loaded, then shows its log records, one per line, timed in UTC. Once a second, one reports the picture’s brightness:
tatolab dev: main loaded (4 nodes, project /home/you/my-stream); Ctrl-C stops it14:03:22.511 [ INFO] [Rk3x9q2m…/main/python] streamlib::polyglot::python — brightness processor_id=P… height=720 mean=118.4 width=1280The first load can take a few seconds. tatolab dev keeps running and watches your files; leave it running.
4. See what it shares
Section titled “4. See what it shares”Open a second terminal. The stream runs in the machine’s runtime, not inside your first terminal:
tatolab streamsNAME STATE NODES PROJECTmain attached 4 /home/you/my-streamThe stream is called main, after its function in stream.py. Open stream.py and look at its last line:
stream_builder.expose(effect.output("video_to_downstream"))That exposes the effect’s output, your camera with its colors inverted, at the address main/invertingeffect/video_to_downstream: the stream, the node and the port. Exposing is how a stream shares what it makes:
- Other streams use it. A stream in any project on this machine reads it with
stream_builder.remote_output("main/invertingeffect/video_to_downstream"), and can record it, run a model on it or send it on.maindoesn’t change, and doesn’t need to know who’s reading. The tutorial builds a stream that reads another. - Agents see it. An agent connected to the runtime can look at what the output carries. Agents and MCP shows how to connect one.
- Browsers and your other machines get a URL. The runtime’s MoQ relay serves each exposed output at one. See Across machines.
5. Change it while it runs
Section titled “5. Change it while it runs”With tatolab dev still running, open nodes/inverting_effect.py. The effect is one small function that runs for every pixel of every frame:
vec4 effect(vec4 source, ivec2 at) { // Color channels only — inverting alpha would erase the picture. return vec4(1.0 - source.rgb, source.a);}Replace it with a grayscale:
vec4 effect(vec4 source, ivec2 at) { float gray = dot(source.rgb, vec3(0.299, 0.587, 0.114)); return vec4(vec3(gray), source.a);}Save the file. tatolab dev notices and loads the stream again. Each load replaces the whole stream, so the window closes and opens again, now in gray.
If your GLSL doesn’t compile, the effect can’t start: the terminal shows the error, naming the line of your GLSL that failed, and no picture reaches the window until you fix it and save again. An edit that stops the stream loading at all, such as a Python syntax error in stream.py, is different: dev keeps the last working version running until you save one that loads.
6. Stop it
Section titled “6. Stop it”Press Ctrl-C in the first terminal. The stream stops and the window closes. The runtime keeps running, ready for the next stream.
What just happened
Section titled “What just happened”tatolab devasked the runtime to loadstream.py. The runtime ran your@streamfunction with the project’s.venvto learn which nodes to create and how to connect them, then started them.- The camera and the window are built-in nodes, native code inside the runtime. Your two nodes each ran in their own Python process, started from your
.venv, so neither could stall the other or the window. - The stream exposed its output by an address. Other streams read it by that address, agents can look at it, and the MoQ relay serves it at a URL.
devwatched your files and reloaded the stream when one changed.tatolab rundoes the same without the watching, andtatolab run -dhands the stream to the runtime to keep running after you close the terminal.
Next steps
Section titled “Next steps”- How Tatolab works: streams, nodes, exposure and the runtime, in plain terms.
- Tutorial: write a node of your own, and share its output with a second stream.
- Write a node: everything a node can declare and do.