Skip to main content

Automate with flows, not loose prompts. Chain LLM, shell, and code in one YAML pipeline.

Project description

🚀 Telize

Build reproducible, structured AI workflows with YAML and run them from your terminal, combining LLMs, shell, Python, and more—fully under your control.

Telize is a low-code framework for building agent-style pipelines: chain shell commands, file I/O, LLM calls, Python functions, and nested flows in a single workflow file. Configuration is validated before execution, and the CLI shows live progress as each step completes.

Telize CLI demo

CI · Python 3.12+ · License


🧭 Table of contents

✨ Features

  • YAML workflows — one file defines config, named models, flows, and steps
  • Composable stepsinput, chat, llm, shell, python, flow, and yaml actions
  • Jinja templating — wire step outputs together with {{ steps.name.output }}
  • Loops and sub-flows — add loop to any step to iterate it over split lists; call nested flows with uses: flow
  • Validated upfront — Pydantic models catch schema errors before any step runs
  • Rich CLI output — progress, step panels, and errors in the terminal
  • Cron scheduling — optional config.cron reruns the entrypoint on a standard five-field schedule
  • OpenAI-compatible LLMs — official OpenAI API or local Ollama via the same client

🧩 Requirements

  • Python 3.12+
  • LLM endpoint for uses: llm steps — OpenAI or Ollama; set api_url on each model profile (default http://localhost:11434)
  • Optional: uv for fast local development

📦 Installation

pip install telize

From source:

git clone https://github.com/telize-ai/telize.git
cd telize
uv sync
uv pip install -e .

Check the install:

telize --version

⚡ Quick start

Scaffold a starter project (no LLM)

Create a minimal workflow you can run immediately — shell plus Python, no API keys or local models:

telize --init my_flow
telize -f my_flow.yaml

This writes my_flow.yaml, a project README.md, and a scripts/ directory with a sample process.py helper. Telize resolves scripts.* imports from the workflow file's directory.

LLM quick start

1. For local models, start Ollama and pull a model:

ollama pull qwen3.5:4b   # or any model id you set under models.*.model

For OpenAI Cloud, set OPENAI_API_KEY and point a model profile at the API, for example api_url: https://api.openai.com/v1.

2. Create hello.yaml:

config:
  entrypoint: main

models:
  default:
    provider: openai
    model: qwen3.5:4b
    api_url: http://localhost:11434

flows:
  main:
    steps:
      - name: greet
        uses: llm
        model: default
        prompt: Say hello in one friendly sentence.

3. Run it:

telize -f hello.yaml

Validate the file without executing steps:

telize -f hello.yaml --validate-only

Run the bundled examples:

telize -f examples/minimal_llm.yaml
telize -f examples/spec_reference.yaml --validate-only

🚀 Motivation

Telize addresses a massive pain point in the current AI engineering landscape:
unpredictability and unnecessary complexity.

Many popular frameworks force developers to write complex, nested Python code (LangChain, CrewAI, AutoGen) just to string together a few API calls, a bash script, and an LLM prompt.
This results in heavy, hard-to-maintain codebases that frequently break when APIs change.

Telize essentially acts as the “GitHub Actions or Ansible for AI.”
By treating LLMs as just another step in a standard automation pipeline, it brings sanity back to the engineering process.


🧠 Why it works

  • Deterministic Structure + Non-Deterministic AI:
    It keeps the overall architecture rigid and predictable (YAML), while allowing the AI to handle the fuzzy, creative tasks (text generation, summarization) within strict boundaries.
  • Upfront Validation:
    Running LLM pipelines can be expensive and time-consuming; catching a syntax or configuration error before wasting API credits is a huge win.
  • Low Friction:
    Local-first by default (Ollama-ready) and zero-code setup means a developer can prototype an agentic workflow in 5 minutes without dealing with dependency hell.

👥 Who may choose Telize over Classic Agents?

  • DevOps and System Administrators:
    People who already love Ansible, Docker Compose, or CI/CD pipelines may want to gravitate toward Telize or similar sollutions.
    They don't want an AI Agent guessing how to deploy code; they want a script that runs a test, summarizes the failure using an LLM, and posts it to Slack.
  • Enterprise & Production Environments:
    Companies hate unpredictability. Classic agents are too risky for production because they can behave wildly.
    Telize provides guardrails. You know exactly what the workflow is going to do because you mapped out the steps.
  • Data Pipelines:
    For ETL (Extract, Transform, Load) tasks where text needs to be scraped, cleaned by an LLM, and saved to a database, a YAML flow is infinitely better than a multi-agent swarm.

⚠️ Where Telize Might Struggle (The Limitations)

While it is great for structured automation, it isn’t a silver bullet:

  • Dynamic Decision Making:
    If a task requires an AI to dynamically look at a problem, decide it needs to create 3 new files, write code, test it, and self-correct on the fly, Telize’s static YAML structure will feel too restrictive.
  • Complex State Management:
    For highly conversational applications (like a customer support chatbot that needs to maintain a complex state over days), a linear flow runner isn't the right tool.

⚙️ How it works

  1. Telize loads your YAML and validates it against typed Pydantic models.
  2. The flow named in config.entrypoint runs first.
  3. Each step executes through a registered action (input, chat, llm, shell, …); llm steps resolve their model: profile from the top-level models map.
  4. Later steps can reference earlier outputs via Jinja templates.
  5. When config.cron is set, Telize reruns the entrypoint after each run finishes, waiting until the next scheduled time.
  6. The CLI prints progress and results as the workflow runs.

📚 Workflow reference

🧱 Top-level structure

Key Description
config Global settings: entrypoint (which flow runs first)
models Named LLM profiles; referenced by model: on each uses: llm step
flows Named flows; config.entrypoint must match one of these keys

⚙️ config

Field Description
entrypoint Name of the flow to run when the file is executed
cron Optional cron schedule (five-field syntax, e.g. 0 * * * * for hourly). Omitted or null: run once. When set, the workflow reruns on the schedule after each run finishes

Example — run every hour:

config:
  entrypoint: main
  cron: "0 * * * *"

🤖 models

Each key under models is a profile name (for example default, creative). LLM steps pick a profile with model: <name>.

Field Required Description
provider no (default openai) Registered provider id
model yes Model id passed to the provider (e.g. qwen3.5:4b, gpt-4o-mini)
temperature no Sampling temperature (0–2)
api_url no (default http://localhost:11434) OpenAI-compatible API base URL (/v1 is appended automatically)
api_key no API key; use {{ env.OPENAI_API_KEY }} or rely on the OPENAI_API_KEY env var
system_prompt no System message for steps using this profile (Jinja at runtime)

Example — multiple profiles:

models:
  factual:
    model: qwen3.5:4b
    temperature: 0.2
    api_url: http://localhost:11434
    system_prompt: Be concise and factual.

  creative:
    model: qwen3.5:4b
    temperature: 1.0
    api_url: http://localhost:11434
    system_prompt: Be witty but brief.

Load-time env in api_url (see examples/env_config.yaml):

models:
  default:
    model: qwen3.5:4b
    api_url: http://{{ env.OLLAMA_HOST }}:11434

🌊 Flow

Field Description
steps List of steps (unique name per flow), executed in order

Every step also supports:

Field Description
name Unique id within the flow; referenced as {{ steps.<name>.output }}
output_to Optional path (relative to the workflow file); raw step output is written when the step finishes
loop Optional; run the step once per item (items split by split_by, default `\n<

🪜 Steps (uses)

uses Description
input Read a file or a directory (with glob include; optional separator when joining directory files, default `\n<
chat Pause the workflow and prompt the user in the terminal; optional message (supports templates); reply is {{ steps.<name>.output }}
llm Send a prompt using a named model from models
shell Run run commands; optional envs (supports templates)
python Call call (module.function) with args
flow Run another flow via run
yaml Run an external workflow from file (own config, models, and flows); optional input map passed to the child as {{ input.key }}

🧩 Templating

Telize uses Jinja2 in step fields.

When What you can use
Load time {{ env.VAR }} — expanded when the file is parsed
Runtime {{ steps.<name>.output }}, {{ models.<name>.model }}, {{ input.<key> }}, {{ item }} (inside loops)

Workflow input is provided when invoking Telize from the shell (--input, --input-file, --input-stdin) or by a parent yaml step's input map when running a nested workflow.

With --input-stdin or --input-file, input may be a YAML/JSON mapping ({"name": "Ada"}{{ input.name }}) or plain text (echo Hello or a .txt file → {{ input.text }}).

For interactive prompts mid-workflow, use uses: chat instead of --input-stdin. The chat step shows a styled prompt in the terminal and exposes the user's reply as step output. Press Ctrl+C or Ctrl+D to exit cleanly.

Example — ask the user, then call an LLM:

- name: user_chat
  uses: chat
  message: What would you like help with today?

- name: respond
  uses: llm
  model: default
  prompt: |
    The user said:
    {{ steps.user_chat.output }}

    Reply briefly and helpfully.

Example — chain a shell step into an LLM step:

- name: fetch_data
  uses: shell
  run: cat ./data.txt

- name: summarize
  uses: llm
  model: default
  prompt: |
    Summarize this:
    {{ steps.fetch_data.output }}

🧪 Examples

File What it demonstrates
examples/spec_reference.yaml Full specification reference (all step types and fields)
examples/minimal_llm.yaml Smallest runnable LLM workflow
examples/shell_to_llm.yaml Shell → LLM with {{ steps.*.output }}
examples/read_file.yaml uses: input — single file
examples/read_directory.yaml uses: input — directory glob
examples/chat_input.yaml uses: chat — interactive user prompt → LLM
examples/llm_save_output.yaml output_to — persist step output to disk
examples/llm_loop.yaml loop — split output and iterate
examples/call_subflow.yaml uses: flow — sub-flow in the same file
examples/nested_workflow.yaml uses: yaml — external workflow + input
examples/python_step.yaml uses: python — call a Python function
examples/multi_model.yaml Multiple named models profiles
examples/shell_with_env.yaml Shell envs and load-time {{ env.* }}
examples/env_config.yaml {{ env.VAR }} in the models section at load time

💻 CLI

usage: telize [-h] [--version] [-f FILE] [--validate-only]
              [--input KEY=VALUE] [--input-file FILE] [--input-stdin]
              [--init FLOW_NAME]

options:
  -h, --help            show help
  --version             show version
  -f, --file FILE       path to workflow YAML
  --validate-only       parse and validate without running steps
  --input KEY=VALUE     workflow input (repeatable)
  --input-file FILE     workflow input from a file
  --input-stdin         read workflow input from stdin
  --init FLOW_NAME      create a starter workflow and scripts/ in the current directory

telize --init <flow_name> scaffolds <flow_name>.yaml, a project README.md, and scripts/process.py. The generated flow chains two shell steps around a Python function — useful for trying Telize before configuring LLMs.

🛠️ Development

uv sync
uv run pytest
uv run ruff check .
uv run ruff format .
uv run mypy

See CONTRIBUTING.md for pull request guidelines and CHANGELOG.md for release notes.

🤝 Contributing

Contributions are welcome — bug reports, docs, and pull requests. Please read CONTRIBUTING.md and open an issue before large changes.

📄 License

Apache License 2.0 — see LICENSE.

GitHub · Issues · Changelog

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

telize-0.3.2.tar.gz (448.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

telize-0.3.2-py3-none-any.whl (44.2 kB view details)

Uploaded Python 3

File details

Details for the file telize-0.3.2.tar.gz.

File metadata

  • Download URL: telize-0.3.2.tar.gz
  • Upload date:
  • Size: 448.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for telize-0.3.2.tar.gz
Algorithm Hash digest
SHA256 22ddee6cae4ca3318bfff6206f7ea3252a8d6d800640a33f688b9302c6a6b4b7
MD5 c207dd1248df70c26931d7400d29ad64
BLAKE2b-256 70596392a3a9414b94b5e75b56fbd6f41ebf20801c8db83df5cb8d74d48329b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for telize-0.3.2.tar.gz:

Publisher: publish.yml on telize-ai/telize

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file telize-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: telize-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 44.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for telize-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 980ea575e4978f2d3231bc65d41687adb9b41b71800f1bd82001fdef3478ca5e
MD5 3f0fad95907e7327ee88b1f420e41d6f
BLAKE2b-256 d948521675152516982bd65c605cedab8dc21b7a17f72813b41967690941b82d

See more details on using hashes here.

Provenance

The following attestation bundles were made for telize-0.3.2-py3-none-any.whl:

Publisher: publish.yml on telize-ai/telize

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page