MCP Mastery
About
lab-01-first-runnable

First Runnable

README

# lab-01-first-runnable — foundations arc

Before you touch LangChain proper, internalize what a **Runnable** is supposed to do: same method names, predictable shapes, batching that is not "a for-loop that forgot it has a job," and streaming that actually yields lazily.

You build a toy `RunnableLambda`-style object: `invoke`, `batch`, and `stream`. No cloud. No vendor SDK. Just the contract the ecosystem assumes you respect.

## Run

```bash
cd labs/langchain/lab-01-first-runnable
uv run python src/main.py
```

## Test

```bash
uv run pytest tests/
```

## Stretch goals

- Add `ainvoke` as a thin async wrapper if you want to rehearse later async graphs.
- Log per-call timing in `stream` and prove chunks cross a time boundary (sleep 0 in tests only).

pyproject.toml

[project]
name = "lab-01-first-runnable"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = []

[project.optional-dependencies]
dev = ["pytest>=8.0"]

[tool.uv]
dev-dependencies = []

Starter Python

"""Demo CLI for lab-01-first-runnable."""

from __future__ import annotations

import sys
from pathlib import Path

_SRC = Path(__file__).resolve().parent
if str(_SRC) not in sys.path:
    sys.path.insert(0, str(_SRC))

from runnable_toy import RunnableToy


def main() -> None:
    r = RunnableToy()
    print("invoke:", r.invoke({"n": 7}))
    print("batch:", r.batch([{"n": 1}, {"n": 2}, {"n": 3}]))
    print("stream:", "".join(r.stream({"n": 21})))


if __name__ == "__main__":
    main()