State¶
State is a flat, JSON-serializable dict. Nodes transform state — nothing else.
Sharing keys across step configs¶
Initial state¶
Declare a seed in state.initial:
state:
initial:
title: " hello world "
Parallel branches¶
Flow.parallel() runs independent branch chains concurrently, each branch
getting an isolated copy of the state. Per-key reducers merge updates back so
append branches accumulate instead of overwriting:
from teff.flow import Flow
from teff.node import Transform
flow = (
Flow("p")
.parallel(
[Transform(action="uppercase", input_key="title", output_key="title")],
[Transform(action="uppercase", input_key="body", output_key="body")],
)
.converge(Transform(action="value", value="done", output_key="status"))
)
result = await flow.compile().run(state={"title": "hi", "body": "world"})
# -> title/body uppercased in parallel, then status="done"
Branches can be single nodes, lists of nodes (run sequentially inside the
branch), or embedded Flow subgraphs. The node also works directly:
Parallel([[node1], [node2]]).
Dynamic fan-out (Map)¶
Flow.map() fans a state list into parallel branches at runtime — the
branch count comes from the data, not the declaration:
flow = Flow(
"repair-plans",
providers=ProviderRegistry.from_presets("ollama"),
default_provider="ollama",
default_model="llama3.1:8b",
).map(
LLM(
prompt="Составь план для ремонта {type} на сумму {summ} рублей.",
output_key="plan",
),
input_keys=["type", "summ"], # lists zipped per index
output_key="plans", # list of per-item results
max_concurrency=2,
)
result = await flow.compile().run(
state={
"type": ["кухни", "санузел"],
"summ": [150000, 80000],
}
)
chunk_size batches items per branch, max_concurrency caps simultaneous
branches, result_key overrides the per-item key to collect.
Reducers¶
Pass reducers to merges multi-writer keys deterministically. String reducers
(append, replace, …) round-trip to YAML via reducers_to_yaml_schema().
Prompt templates¶
LLM nodes read multiple state keys into one prompt with {key} templates
(also supported in system):
node = LLM(
model="llama3.1:8b",
system="Ты инженер по ремонту.",
prompt="Составь план для ремонта {type} на сумму {summ} рублей.",
output_key="plan",
)
# state {"type": "кухни", "summ": 150000} -> user message:
# "Составь план для ремонта кухни на сумму 150000 рублей."
Values are stringified; a placeholder referencing a missing state key raises
KeyError. The underlying helper is teff.prompt.render_template.