Grouped runs, apps (beta), custom context, and a secrets UI.

November 2025

⏩ Grouped Runs

The redesigned Runs page groups runs by their root task. Large projects produce so many runs that a flat listing is hard to navigate, but while a project may have millions of runs, it typically has only dozens or hundreds of deployed tasks.

The grouped view, together with filtering by status, owner, and duration, makes it faster to find the runs you’re looking for, even in the largest deployments.

Grouped Runs View

🌐 Apps (beta)

You can now deploy apps in Union 2.0. Apps host ML models, Streamlit dashboards, FastAPI services, and other interactive applications alongside your workflows.

You define and deploy your app, and Union handles the infrastructure, routing, and lifecycle management. You can also call apps from your tasks to build end-to-end workflows that combine batch processing with real-time serving.

To create an app, import flyte and use one of these environments:

  • FastAPIAppEnvironment for FastAPI applications.
  • The generic AppEnvironment for other frameworks.

Here’s a FastAPI example:

from fastapi import FastAPI
import flyte
from flyte.app.extras import FastAPIAppEnvironment

app = FastAPI()
env = FastAPIAppEnvironment(
    name="my-api",
    app=app,
    image=flyte.Image.from_debian_base(python_version=(3, 12))
        .with_pip_packages("fastapi", "uvicorn"),
    resources=flyte.Resources(cpu=1, memory="512Mi"),
    requires_auth=False,
)

@env.app.get("/greeting/{name}")
async def greeting(name: str) -> str:
    return f"Hello, {name}!"

if __name__ == "__main__":
    flyte.init_from_config()
    flyte.deploy(env) # Deploy and serve your app

For Streamlit apps, use the generic AppEnvironment with a command:

app_env = flyte.app.AppEnvironment(
    name="streamlit-hello-v2",
    image=flyte.Image.from_debian_base(python_version=(3, 12)).with_pip_packages("streamlit==1.41.1"),
    command="streamlit hello --server.port 8080",
    resources=flyte.Resources(cpu="1", memory="1Gi"),
)

To call an app from a task, use depends_on and make HTTP requests to the app’s endpoint. See the example in the SDK repo.

You can also call apps from other apps. See this example.

🏷️ Custom Context

You can now use custom context to pass configuration and metadata implicitly through your entire task execution hierarchy.

Use it for cross-cutting concerns such as tracing IDs, experiment metadata, environment information, or logging correlation keys: data that needs to be available everywhere but isn’t logically part of your task’s computation.

Custom context is a string key-value map that flows automatically from parent to child tasks, so you don’t add parameters to every function signature.

  • Set it once at the run level with with_runcontext().
  • Override values within tasks with the flyte.custom_context() context manager.

For example:

import flyte

env = flyte.TaskEnvironment("custom-context-example")

@env.task
async def leaf_task() -> str:
    # Reads run-level context
    print("leaf sees:", flyte.ctx().custom_context)
    return flyte.ctx().custom_context.get("trace_id")

@env.task
async def root() -> str:
    return await leaf_task()

if __name__ == "__main__":
    flyte.init_from_config()
    # Base context for the entire run
    run = flyte.with_runcontext(custom_context={"trace_id": "root-abc", "experiment": "v1"}).run(root)
    print(run.url)

🔒 Secrets UI

You can now view and create secrets directly in the UI. Secrets are stored securely in your configured secrets manager and injected into your task environments at runtime.

Secrets Creation Flow

🔨 Image Builds Now Run in the Same Project-Domain

The image build task now runs in the same project and domain as your task, rather than in system-production. This improves isolation.

🔒 Support for Secret Mounts in Poetry and uv Projects

You can now mount secrets into both Poetry and uv-based projects. This gives you secure access to private dependencies or credentials during image builds.

import pathlib

import flyte

env = flyte.TaskEnvironment(
    name="uv_project_lib",
    resources=flyte.Resources(memory="1000Mi"),
    image=(
        flyte.Image.from_debian_base().with_uv_project(
            pyproject_file=pathlib.Path(__file__).parent / "pyproject.toml",
            pre=True,
            secret_mounts="my_secret",
        )
    ),
)