Skip to content

Reference

Design principles

See CONSTITUTION.md for the framework's principles and non-negotiable rules — the short version:

  • Workflow as data. YAML/JSON are canonical; code is optional.
  • Async by default. Nodes, tools, and LLM calls are async.
  • Durable. Checkpoint/resume across file, SQLite, and PostgreSQL.
  • Embeddable. A library, not a platform — you import us, we never import you.
  • Zero runtime magic. No hidden registries beyond the documented plugin mechanism.

The ${ENV} interpolation

Every value in a workflow document is interpolated against the process environment. A variable that is not set stays as a literal placeholder — nothing crashes. This is the only supported way to pass secrets; never hardcode API keys in a workflow file.

Typed errors

Loading or running a broken workflow throws errors from a public hierarchy rooted at teff.TeffError; subclasses multiple-inherit from builtins for back-compat:

TeffError
├── ConfigError             (also KeyError)      — invalid config / unknown types
├── WorkflowError           (also RuntimeError)  — workflow-level failures
│   ├── NodeError                                 — a node raised (node_id/type)
│   └── LLMError                                  — a model call failed after retries
├── InterruptError                                — HITL resume misuse
├── GraphInterrupt                                — workflow paused for human input
└── StructuredOutputError   (also ValueError)    — schema validation failed

Workflow validation

from teff.yaml_schema import validate_workflow_file, format_errors

errors = validate_workflow_file("workflow.yaml")
if errors:
    print(format_errors(errors, source="workflow.yaml"))
teff validate workflow.yaml    # exits non-zero on errors

To validate an already-parsed dict (no file) use teff.yaml_schema.validate_workflow(data, node_types=..., tool_types=...) — same error list. See the API reference.

Development

uv sync                        # install deps
uv run pytest tests/ -q        # tests
uv run ruff check .            # lint
uv run ruff format --check .   # formatting
uv run mypy .                  # types

Running these docs

uv run pip install -e ".[docs]"
uv run mkdocs serve            # http://localhost:8000
uv run mkdocs build            # static site in site/