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.
🌐 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:
FastAPIAppEnvironmentfor FastAPI applications.- The generic
AppEnvironmentfor 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 appFor 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.
🔨 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",
)
),
)