Turn anything
into a live stream.

Wire cameras, models and your own code into a stream. Expose an output, and apps, agents and your other machines read it by URL.

brew install --cask tatolab/tap/tatolabopen -a Tatolab

Apple silicon, macOS 15 or laterx86_64 Linux with a Vulkan GPU

Then connect your agent
claude mcp add tatolab -- tatolab mcp

Every exposed output has a URL. Open it in a browser, pull it into another stream, or hand it to an agent.

studio/pitch/overlay/video_to_downstream
The overlay node's output, open in a browser.

An agent connected over MCP samples the output and looks at a frame.

YouWhat's happening on the pitch?
Tooltap("pitch/overlay/video_to_downstream")3 bags
Toolexchange(surface_id)a frame, as an image
AgentFive players are in view, and the ball is near the center circle.

A stream is a function. A node is a class. Wrap a model, an SDK or a driver in a node. Each one runs in its own process.

@stream
def pitch(stream_builder: StreamBuilder) -> None:
    camera = stream_builder.remote_output("pitch-cam/sideline/camera/video")
    detector = stream_builder.add(
        HuggingFaceDetector, config={"model": "facebook/detr-resnet-50"}
    )
    overlay = stream_builder.add(Overlay)
    stream_builder.connect(camera, detector.input("video_from_upstream"))
    stream_builder.connect(camera, overlay.input("video_from_upstream"))
    stream_builder.connect(
        detector.output("detections_to_downstream"),
        overlay.input("detections_from_upstream"),
    )
    stream_builder.expose(
        overlay.output("video_to_downstream"), Exposure.PUBLIC
    )
The pitch stream: the camera on pitch-cam feeds the detector and the overlay, the detector feeds the overlay, and the overlay's output has a URL.camerapitch-cam/sidelinedetectordetr-resnet-50overlaystudio/pitch/overlay/video_to_downstream
stream.py, as a graph.

Run one in five minutesWrite a node

Works with your agents. Over MCP, an agent sees the live graph, samples outputs, looks at frames, reads logs, and rewires nodes.

Over MCP
  • Claude Code
  • Claude Desktop
  • Cline
  • Codex
  • Cursor
  • Devin Desktop
  • Gemini CLI
  • GitHub Copilot
  • Grok Build
  • Zed
Computer use
  • Grok Bot
  • Muse

They open a stream by its URL.

Set up
claude mcp add tatolab -- tatolab mcp

One command or a few lines of config for each agent. Connect an agent

Nothing leaves until you expose it. Set each output's level in code, and change it while the stream runs.

Internal

Only links inside the stream read it. Every output starts here.

Private

Streams and agents on this machine read it.

stream_builder.expose(output)
Public

Your other machines read it by URL, over your tailnet or a relay.

stream_builder.expose(output, Exposure.PUBLIC)
Live

Raise or remove a level without a restart.

$ tatolab expose pitch overlay video_to_downstream --remove

Outputs travel over MoQ on QUIC, which is always encrypted: across your tailnet, or through a relay you run or join.

Install it. The quickstart has a stream running in about five minutes.

brew install --cask tatolab/tap/tatolabopen -a Tatolab

Apple silicon, macOS 15 or laterx86_64 Linux with a Vulkan GPU

Questions? Email hello@tatolab.com. Agents can read this page as Markdown at /index.md, and /llms.txt lists the rest of the site.