← FlyteCONTENT HISTORY

Update to Flyte

Snapshot Sep 30, 2026 · 22:59 UTC · version 1.0.1

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Migrates Flyte 1 tasks and workflows to Flyte 2, where the @task, @workflow, and @dynamic decorators collapse into a single @env.task on a flyte.TaskEnvironment and a workflow becomes a task that calls other tasks. Use when the user is migrating Flyte 1 tasks/workflows to Flyte 2. Trigger words: migrate task, migrate workflow, @task, @workflow, @dynamic, TaskEnvironment, env.task.",
  "included_files": [],
  "name": "flyte-migrate-tasks-workflows",
  "skill_md_contents": "---\nname: flyte-migrate-tasks-workflows\ndescription: >-\n  Migrates Flyte 1 tasks and workflows to Flyte 2, where the @task, @workflow,\n  and @dynamic decorators collapse into a single @env.task on a\n  flyte.TaskEnvironment and a workflow becomes a task that calls other tasks.\n  Use when the user is migrating Flyte 1 tasks/workflows to Flyte 2. Trigger\n  words: migrate task, migrate workflow, @task, @workflow, @dynamic,\n  TaskEnvironment, env.task.\n---\n\n# Flyte 1 to 2 Migration: Tasks and Workflows\n\nThe biggest structural change in Flyte 2 is that everything is a task. The Flyte 1 `@task`, `@workflow`, and `@dynamic` decorators all collapse into a single `@env.task` on a `flyte.TaskEnvironment`, and a \"workflow\" is now just a task that calls other tasks. This skill covers the structural shift, sequential ordering without the `>>` operator, nested subworkflows, TaskEnvironment configuration basics, and the full `@task` parameter mapping.\n\n## Grounding References\n\n| Resource | URL |\n|---|---|\n| Migration guide | https://www.union.ai/docs/v2/flyte/user-guide/migration/flyte-2/tasks-and-workflows/ |\n| Official docs | https://www.union.ai/docs/v2/flyte |\n| Docs index (LLMs) | https://www.union.ai/docs/v2/flyte/llms.txt |\n| SDK API reference | https://www.union.ai/docs/v2/union/api-reference/flyte-sdk/ |\n| Example code | https://github.com/unionai/unionai-examples |\n| Flyte MCP tools | Available via `flyte-mcp` server |\n\n## The Structural Shift\n\nIn Flyte 1 you decorated units of work with `@task`, composed them with `@workflow`, and used `@dynamic` for runtime-generated graphs. In Flyte 2 you create one `flyte.TaskEnvironment` that carries the configuration, then decorate every function — leaf tasks and orchestrating \"workflows\" alike — with `@env.task`. There is no separate `@workflow` decorator: the entrypoint is just a task that calls other tasks.\n\n## Hello World: Tasks and Workflows\n\nA `@task` plus `@workflow` becomes two `@env.task`s, where the entrypoint task calls the others. Sequential calls are naturally ordered — no `>>` operator required.\n\n### Flyte 1\n\n```python\nimport flytekit\n\n@flytekit.task\ndef say_hello(name: str) -> str:\n    return f\"Hello, {name}!\"\n\n@flytekit.task\ndef to_upper(greeting: str) -> str:\n    return greeting.upper()\n\n@flytekit.workflow\ndef main(name: str) -> str:\n    greeting = say_hello(name=name)\n    return to_upper(greeting=greeting)\n```\n\n### Flyte 2\n\n```python\nimport flyte\n\nenv = flyte.TaskEnvironment(name=\"hello_world\")\n\n@env.task\ndef say_hello(name: str) -> str:\n    return f\"Hello, {name}!\"\n\n@env.task\ndef to_upper(greeting: str) -> str:\n    return greeting.upper()\n\n# The \"workflow\" is now just a task that calls other tasks.\n@env.task\ndef main(name: str) -> str:\n    greeting = say_hello(name)\n    return to_upper(greeting)\n```\n\nNote that Flyte 2 task calls pass arguments positionally (`say_hello(name)`) rather than requiring keyword arguments as in Flyte 1 (`say_hello(name=name)`).\n\n## Chaining and Ordering\n\nIn Flyte 1 you sometimes used `>>` to force ordering between tasks with no data dependency. In Flyte 2, sequential (synchronous) calls run in the order they are written, and `await`ing async tasks in sequence does the same. The `>>` operator is gone.\n\n### Flyte 1\n\n```python\nfrom flytekit import task, workflow\n\n@task\ndef clear_staging_table() -> None:\n    # Side effect only: truncate the staging table.\n    print(\"cleared staging table\")\n\n@task\ndef load_into_staging() -> None:\n    # Side effect only: load fresh rows into staging.\n    print(\"loaded staging table\")\n\n@task\ndef publish_to_prod() -> None:\n    # Side effect only: swap staging into the production table.\n    print(\"published to prod\")\n\n@workflow\ndef main() -> None:\n    clear = clear_staging_table()\n    load = load_into_staging()\n    publish = publish_to_prod()\n\n    # These tasks pass no data between them, so use the >> operator to force\n    # ordering: clear must finish before load, which must finish before publish.\n    clear >> load >> publish\n```\n\n### Flyte 2\n\n```python\nimport flyte\n\nenv = flyte.TaskEnvironment(name=\"staging_publish\")\n\n@env.task\ndef clear_staging_table() -> None:\n    print(\"cleared staging table\")\n\n@env.task\ndef load_into_staging() -> None:\n    print(\"loaded staging table\")\n\n@env.task\ndef publish_to_prod() -> None:\n    print(\"published to prod\")\n\n# Sequential (synchronous) calls run in the order they're written, even when no\n# data flows between them. The Flyte 1 `>>` ordering operator is gone.\n@env.task\ndef main() -> None:\n    clear_staging_table()\n    load_into_staging()\n    publish_to_prod()\n```\n\n## Subworkflows\n\nA `@workflow` invoked by another `@workflow` (for example, a reusable preprocessing pipeline) becomes a task that calls other tasks — nest them as deeply as you like.\n\n### Flyte 1\n\n```python\nfrom flytekit import task, workflow\n\n@task\ndef impute(value: float) -> float:\n    # Replace missing/negative sentinel values with 0.\n    return value if value >= 0 else 0.0\n\n@task\ndef scale(value: float) -> float:\n    return value / 100.0\n\n@workflow\ndef preprocess(value: float) -> float:\n    imputed = impute(value=value)\n    return scale(value=imputed)\n\n@workflow\ndef main(raw_value: float) -> float:\n    return preprocess(value=raw_value)\n```\n\n### Flyte 2\n\n```python\nimport flyte\n\nenv = flyte.TaskEnvironment(name=\"subworkflow\")\n\n@env.task\ndef impute(value: float) -> float:\n    # Replace missing/negative sentinel values with 0.\n    return value if value >= 0 else 0.0\n\n@env.task\ndef scale(value: float) -> float:\n    return value / 100.0\n\n# A preprocessing \"subworkflow\" is just a task that calls other tasks.\n@env.task\ndef preprocess(value: float) -> float:\n    imputed = impute(value)\n    return scale(imputed)\n\n@env.task\ndef main(raw_value: float) -> float:\n    return preprocess(raw_value)\n```\n\n## TaskEnvironment Configuration\n\nThe `TaskEnvironment` holds the configuration that Flyte 1 spread across the `@task` decorator. The task decorator can still override a few settings per-task.\n\n```python\nimport flyte\n\nenv = flyte.TaskEnvironment(\n    name=\"my_env\",                           # Required: unique name\n    image=flyte.Image.from_debian_base(),    # Or a string, or \"auto\"\n    resources=flyte.Resources(\n        cpu=\"2\",\n        memory=\"4Gi\",\n        gpu=\"A100:1\",\n        disk=\"10Gi\",\n    ),\n    env_vars={\"LOG_LEVEL\": \"INFO\"},\n    secrets=[flyte.Secret(key=\"api-key\", as_env_var=\"API_KEY\")],\n    cache=\"auto\",                            # \"auto\", \"override\", \"disable\", or a Cache object\n    reusable=flyte.ReusePolicy(replicas=5, idle_ttl=60),\n    interruptible=True,\n)\n\n# The task decorator can override some settings:\n@env.task(\n    short_name=\"my_task\",   # Display name\n    cache=\"disable\",        # Override cache\n    retries=3,              # Retry count\n    timeout=3600,           # Seconds or a timedelta\n    report=True,            # Generate an HTML report\n)\ndef my_task(x: int) -> int:\n    return x\n```\n\n## Parameter Mapping: `@task` to `TaskEnvironment` + `@env.task`\n\n| Flyte 1 `@task` parameter | Flyte 2 location | Notes |\n|---|---|---|\n| `container_image` | `TaskEnvironment(image=...)` | Env-level only |\n| `requests` | `TaskEnvironment(resources=...)` | Env-level only |\n| `limits` | `TaskEnvironment(resources=...)` | Combined with requests (single value) |\n| `environment` | `TaskEnvironment(env_vars=...)` | Env-level only |\n| `secret_requests` | `TaskEnvironment(secrets=...)` | Env-level only |\n| `cache` | Both | Can override at task level |\n| `cache_version` | `flyte.Cache(version_override=...)` | In a `Cache` object |\n| `retries` | `@env.task(retries=...)` | Task-level only |\n| `timeout` | `@env.task(timeout=...)` | Task-level only |\n| `interruptible` | Both | Can override at task level |\n| `pod_template` | Both | Can override at task level |\n| `deprecated` | N/A | Not in Flyte 2 |\n| `docs` | `@env.task(docs=...)` | Task-level only |\n\nFor image, resource, secret, and caching detail, see the Task configuration migration page.\n\n## Anti-Patterns\n\n1. **Don't reach for `>>`** — the ordering operator is gone. Sequential synchronous calls already run in written order; `await` async tasks in sequence for the same effect.\n2. **Don't look for a `@workflow` decorator** — there isn't one. The orchestrating entrypoint is just another `@env.task` that calls other tasks.\n3. **Don't look for a `@dynamic` decorator** — dynamic graphs also collapse into ordinary `@env.task` functions that call other tasks at runtime.\n4. **Don't put heavy compute in the orchestrating task** — keep the entrypoint task focused on calling other tasks; push CPU/GPU/memory-intensive work into leaf tasks whose resources you can tune per environment.\n5. **Don't set image, resources, or secrets on the `@env.task` decorator** — those are env-level and belong on `TaskEnvironment`. Only per-task overrides like `retries`, `timeout`, `cache`, and `short_name` go on `@env.task`.\n6. **Don't keep passing every argument by keyword** — Flyte 2 task calls accept positional arguments (`say_hello(name)`).\n"
}

SHA-256 of public snapshot: 1ef08b319d5b3c659436175744131d13a6c7a81931a3948d799c528d09f9ce00