# Getting started
> This bundle contains all pages in the Getting started section.
> Source: https://www.union.ai/docs/v1/flyte/user-guide/getting-started/

=== PAGE: https://www.union.ai/docs/v1/flyte/user-guide/getting-started ===

# Getting started

> **📝 Note**
>
> An LLM-optimized bundle of this entire section is available at [`section.md`](section.md).
> This single file contains all pages in this section, optimized for AI coding agent context.

This section gives you a quick introduction to writing and running Flyte workflows.

## Try Flyte on your local machine

You can also install Flyte's SDK (called `flytekit`) and a local Flyte cluster to run workflows on your local machine.

To get started, follow the instructions on the next page, **Getting started > Local setup**.

=== PAGE: https://www.union.ai/docs/v1/flyte/user-guide/getting-started/local-setup ===

# Local setup

In this section we will set up your local environment so that you can start building and deploying Flyte workflows from your local machine.

## Install `uv`

First, [install `uv`](https://docs.astral.sh/uv/#getting-started).

> [!NOTE] Using `uv` as best practice
> The `uv` tool is our [recommended package and project manager](https://docs.astral.sh/uv/).
> It replaces `pip`, `pip-tools`, `pipx`, `poetry`, `pyenv`, `twine`, `virtualenv`, and more.
>
> You can, of course, use other tools,
> but all discussion in these pages will use `uv`,
> so you will have to adapt the directions as appropriate.

## Ensure the correct version of Python is installed

Flytekit requires Python `>=3.9,<3.13`.
We recommend using `3.12`.
You can install it with:

```shell
$ uv python install 3.12
```

> [!NOTE] Uninstall higher versions of Python
> When installing Python packages "as tools" (as we do below with the `flytekit`),
> `uv` will default to the latest version of Python available on your system.
> If you have a version `>=3.13` installed, you will need to uninstall it since `flytekit` requires `>=3.9,<3.13`.

## Install the `pyflyte` CLI

Once `uv` is installed, use it to install the `pyflyte` CLI by installing the `flytekit` Python package:

```shell
$ uv tool install flytekit
```

This will make the `pyflyte` CLI globally available on your system.

> [!NOTE] Add the installation location to your PATH
> `uv` installs tools in `~/.local/bin` by default.
> Make sure this location is in your `PATH`, so you can run the `pyflyte` command from anywhere.
> `uv` provides a convenience command to do this: `uv tool update-shell`.
>
> Note that later in this guide we will be running the `pyflyte` CLI to run your workflows.
> In those cases you will be running `pyflyte` within the Python virtual environment of your workflow project.
> You will not be using this globally installed instance of `pyflyte`.
> This instance of `pyflyte` is only used during the configuration step, below, when no projects yet exist.

## Install Docker and get access to a container registry

Flyte tasks are run in containers. Every container requires a container image that defines its software environment.
When developing and running Flyte tasks and workflows, an important part of the process is building those images and pushing them to a container registry.
Your Flyte installation then pulls down these images when it spins up the containers that run your tasks.

To build and push the images you need to have Docker (or an equivalent container runtime) installed on your local machine.

Go to [the Docker website](https://docs.docker.com/get-docker/) for installation directions.

You will also need access to a container registry where you can push your images.
Furthermore, the pushed images will need to be accessible to the Flyte installation you are using
(The registry must be accessible and the images themselves must also have the appropriate permissions.
For example, a public registry like `ghcr.io` with the images set to public, would work).

## Install `flytectl` to set up a local cluster

For production use you will need to install Flyte in your cloud infrastructure (see [Deployment](https://www.union.ai/docs/v1/flyte/deployment)).
Here we are using a local cluster for experimentation and demonstration purposes.

To set up a local cluster you must first install the `flytectl` CLI.

> [!NOTE] Flytectl vs Pyflyte
> `flytectl` is different from the `pyflyte`.
>
> `pyflyte` is a Python program and part of the `flytekit` SDK
> It is the primary command-line tool used during Flyte development.
>
> `flytectl` is a compiled binary (written in Go) and used for performing certain administrative tasks.
> (see [Flytectl](https://www.union.ai/docs/v1/flyte/api-reference/uctl-cli) for details)

To install `flytectl`, follow these instructions:

### macOS

To install `flytectl` on a Mac, use [Homebrew](https://brew.sh/), `curl`, or download the binary manually.

**Homebrew**

```shell
$ brew tap flyteorg/homebrew-tap
$ brew install flytectl
```

**curl**

To use `curl`, set `BINDIR` to the install location (it defaults to `./bin`) and run the following command:

```shell
$ curl -sL https://ctl.flyte.org/install | sudo bash -s -- -b /usr/local/bin
```

**Manual download**

To download manually, see the [`flytectl` releases](https://github.com/flyteorg/flytectl/releases).

### Linux

To install `flytectl` on Linux, use `curl` or download the binary manually.

**curl**

To use `curl`, set `BINDIR` to the installation location (it defaults to `./bin`) and run the following command
(note that [jq](https://jqlang.org/) needs to be installed to run this script):

```shell
$ curl -sL https://ctl.flyte.org/install | sudo bash -s -- -b /usr/local/bin
```

**Manual download**

To download manually, see the [`flytectl` releases](https://github.com/flyteorg/flytectl/releases).

### Windows

To install `flytectl` on Windows, use `curl` , or download the binary manually.

**curl**

To use `curl`, in a Linux shell (such as [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)), set `BINDIR` to the install location (it defaults to `./bin`) and run the following command(note that [jq](https://jqlang.org/) needs to be installed to run this script):

```shell
$ curl -sL https://ctl.flyte.org/install | sudo bash -s -- -b /usr/local/bin
```

**Manual download**

To download manually, see the [`flytectl` releases](https://github.com/flyteorg/flytectl/releases).

## Start Docker and the local cluster

Once you have installed Docker and `flytectl`, do the following:

1. Start the Docker daemon.

2. Use `flytectl` to set up a local Flyte cluster by running:

```shell
$ flytectl demo start
```

This will start a local Flyte cluster on your machine and place a configuration file in `~/.flyte/config-sandbox.yaml`
that contains the connection information to connect `pyflyte` (and `flytectl`) to that cluster.

The local Flyte cluster will be available at `localhost:30080`.

> [!NOTE] Try Flyte technology through Flyte Serverless

## Configure the connection to your cluster

To configure the connection from `pyflyte` and `flytectl` to your Flyte instance, set the `FLYTECTL_CONFIG` environment variable to point to the configuration file that `flytectl` created:

```shell
$ export FLYTECTL_CONFIG=~/.flyte/config-sandbox.yaml
```

This will allow you to interact with your local Flyte cluster.

To interact with a Flyte cluster in the cloud you will need to adjust the configuration
and point the environment variable to the new configuration file.

Alternatively, you can always specify the configuration file on the command line when invoking `pyflyte` or `flytectl` by using the `--config` flag.
For example:

```shell
$ pyflyte --config ~/.my-config-location/my-config.yaml run my_script.py my_workflow
```

See [Running in a local cluster](https://www.union.ai/docs/v1/flyte/user-guide/development-cycle/running-in-a-local-cluster) for more details on the format of the `yaml` file.
<!-- TODO: Fix this target page to have a more generic title (it applies to all clusters) and fix its content -->

## Check your CLI configuration

To check your CLI configuration, run:

```shell
$ pyflyte info
```

You should get a response like this:

```shell
$ pyflyte info
╭────────────────────────────────────────────────────────── Flytekit CLI Info ──────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│ This CLI is meant to be used within a virtual environment that has Flytekit installed. Ideally it is used to iterate on your Flyte    │
│ workflows and tasks.                                                                                                                  │
│                                                                                                                                       │
│ Flytekit Version: 1.15.0                                                                                                              │
│ Flyte Backend Version: <flyte-backend-version>                                                                                        │
│ Flyte Backend Endpoint: <flyte-host-url>                                                                                              │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

=== PAGE: https://www.union.ai/docs/v1/flyte/user-guide/getting-started/first-project ===

# First project

In this section we will set up a new project.
This involves creating a local project directory holding your project code
and a corresponding Flyte project to which you will deploy that code using the `pyflyte` CLI.

## Create a new Flyte project

Create a new project on your local Flyte cluster:

```shell
$ flytectl create project \
      --id "my-project" \
      --labels "my-label=my-project" \
      --description "My Flyte project" \
      --name "My project"
```

You can see the project you just created by going to `http://localhost:30080` in your browser.

> [!NOTE] Default project
> Flyte provides a default project (called `flytesnacks`) where all your workflows will be
> registered unless you specify otherwise.
> In this section, however, we will be using the project we just created, not the default.

## Initialize a local project

We will use the `pyflyte init` command to initialize a new local project corresponding to the project created on your Flyte instance:

```shell
$ pyflyte init --template flyte-simple my-project
```

The resulting directory will look like this:

```shell
├── LICENSE
├── README.md
├── hello_world.py
├── pyproject.toml
└── uv.lock
```

> [!NOTE] Local project directory name same as Flyte project ID
> It is good practice to name your local project directory the same as your
> Flyte project ID, as we have done here.

Next, let's look at the contents of the local project directory.
Continue to [Understanding the code](./understanding-the-code).

=== PAGE: https://www.union.ai/docs/v1/flyte/user-guide/getting-started/understanding-the-code ===

# Understanding the code

This is a simple "Hello, world!" example consisting of flat directory:

```shell
├── LICENSE
├── README.md
├── hello_world.py
├── pyproject.toml
└── uv.lock
```

## Python code

The `hello_world.py` file illustrates the essential components of a Flyte workflow:

```python
# Hello World

import flytekit as fl
import os

image_spec = fl.ImageSpec(
    # The name of the image. This image will be used by the `say_hello`` task.
    name="say-hello-image",

    # Lock file with dependencies to be installed in the image.
    requirements="uv.lock",

    # Image registry to which this image will be pushed.
    # Set the Environment variable FLYTE_IMAGE_REGISTRY to the URL of your registry.
    # The image will be built on your local machine, so enure that your Docker is running.
    # Ensure that pushed image is accessible to your Flyte cluster, so that it can pull the image
    # when it spins up the task container.
    registry=os.environ['FLYTE_IMAGE_REGISTRY']
)

@fl.task(container_image=image_spec)
def say_hello(name: str) -> str:
    return f"Hello, {name}!"

@fl.workflow
def hello_world_wf(name: str = "world") -> str:
    greeting = say_hello(name=name)
    return greeting
```

### ImageSpec

The `ImageSpec` object is used to define the container image that will run the tasks in the workflow.

Here we have the simplest possible `ImageSpec` object, which specifies:

* The `name` of the image.
  * This name will be used to identify the image in the container registry.

* The `requirements` parameter.
  * We specify that the requirements should be read from the `uv.lock` file.

* The `registry` to which the image will be pushed.
  * Here we use the environment variable `FLYTE_IMAGE_REGISTRY` to hold the URL of the registry.
  * You must ensure that this environment variable is correctly set before you register the workflow.
  * You must also ensure that when the image is pushed to the registry, it will be accesible to your Flyte cluster, so that it can pull the image when it spins up the task container.

See [ImageSpec](https://www.union.ai/docs/v1/flyte/user-guide/development-cycle/image-spec) for more information.

### Tasks

The `@fl.task` decorator indicates a Python function that defines a [**task**](https://www.union.ai/docs/v1/flyte/user-guide/core-concepts/tasks).
A task tasks some input and produces an output.
When deployed to Flyte cluster, each task runs in its own Kubernetes pod.
For a full list of task parameters, see [Task parameters](https://www.union.ai/docs/v1/flyte/user-guide/core-concepts/tasks/task-parameters).

### Workflow

The `@fl.workflow` decorator indicates a function that defines a [workflow](https://www.union.ai/docs/v1/flyte/user-guide/core-concepts/workflows).
This function contains references to the tasks defined elsewhere in the code.

A workflow appears to be a Python function but is actually a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) that only supports a subset of Python syntax and semantics.

When deployed to Flyte, the workflow function is compiled to construct the directed acyclic graph (DAG) of tasks, defining the order of execution of task pods and the data flow dependencies between them.

> [!NOTE] `@fl.task` and `@fl.workflow` syntax
> * The `@fl.task` and `@fl.workflow` decorators will only work on functions at the top-level
>   scope of the module.
> * You can invoke tasks and workflows as regular Python functions and even import and use them in
>   other Python modules or scripts.
> * Task and workflow function signatures must be type-annotated with Python type hints.
> * Task and workflow functions must be invoked with keyword arguments.

## pyproject.toml

The `pyproject.toml` is the standard project configuration used by `uv`.
It specifies the project dependencies and the Python version to use.
The default `pyproject.toml` file created by `pyflyte init` from the `flyte-simple` template looks like this

```toml
[project]
name = "flyte-simple"
version = "0.1.0"
description = "A simple Flyte project"
readme = "README.md"
requires-python = ">=3.9,<3.13"
dependencies = ["flytekit"]
```

(You can update the `name` and `description` to match the actual name of your project, `my-project`, if you like).

The most important part of the file is the list of dependencies, in this case consisting of only one package, `flytekit`.
See [uv > Configuration > Configuration files](https://docs.astral.sh/uv/configuration/files/) for details.

## uv.lock

The `uv.lock` file is generated from `pyproject.toml` by `uv sync` command.
It contains the exact versions of the dependencies required by the project.

The `uv.lock` included in the `init` template may not reflect the latest version of the dependencies, so you should update it by doing a fresh `uv sync`.

See [uv > Concepts > Projects > Locking and syncing](https://docs.astral.sh/uv/concepts/projects/sync/) for details.

=== PAGE: https://www.union.ai/docs/v1/flyte/user-guide/getting-started/running-your-workflow ===

# Running your workflow

## Python virtual environment

The first step is to ensure that your `uv.lock` file is properly generated from your `pyproject.toml` file and that your local Python virtual environment is properly set up.

Using `uv`, you can install the dependencies with the command:

```shell
$ uv sync
```

You can then activate the virtual environment with:

```shell
$ source .venv/bin/activate
```

> [!NOTE] `activate` vs `uv run`
> When running the `pyflyte` CLI within your local project you must run it in the virtual
> environment _associated with_ that project.
> This differs from our earlier usage of the tool when
> [we installed `pyflyte` globally](./local-setup#install-the--cli--cli) in order to
> [set up its configuration](./local-setup#configure-the-connection-to-your--product_full--instance).
>
> To run `pyflyte` within your project's virtual environment using `uv`,
> you can prefix it use the `uv run` command. For example:
>
> `uv run pyflyte ...`
>
> Alternatively, you can activate the virtual environment with `source .venv/bin/activate` and then
> run the `pyflyte` command directly.
>
> In our examples we assume that you are doing the latter.

## Run the code locally

Because tasks and workflows are defined as regular Python functions, they can be executed in your local Python environment.

You can run the workflow locally with the command [`pyflyte run <FILE> <WORKFLOW>`](https://www.union.ai/docs/v1/flyte/api-reference/union-cli):

```shell
$ pyflyte run hello_world.py hello_world_wf
```

You should see output like this:

```shell
Running Execution on local.
Hello, world!
```

You can also pass in parameters to the workflow (assuming they declared in the workflow function):

```shell
$ pyflyte run hello_world.py hello_world_wf --name="everybody"
```

You should see output like this:

```shell
Running Execution on local.
Hello, everybody!
```

## Running remotely on Flyte in the cloud

Running you code in your local Python environment is useful for testing and debugging.

But to run them at scale, you will need to deploy them (or as we say, "register" them) on to your Flyte instance in the cloud.

When task and workflow code is registered:

* The `@fl.task` function is loaded into a container defined by the `ImageSpec` object specified in the `container_image` parameter of the decorator.
* The `@fl.workflow` function is compiled into a directed acyclic graph that controls the running of the tasks invoked within it.

To run the workflow on Flyte in the cloud, use the [`--remote` option](https://www.union.ai/docs/v1/flyte/api-reference/union-cli) and the

```shell
$ export FLYTE_IMAGE_REGISTRY=localhost:30000
$ pyflyte run --remote -env FLYTE_IMAGE_REGISTRY=${FLYTE_IMAGE_REGISTRY} --project my-project --domain development hello_world.py hello_world_wf
```

The output displays a URL that links to the workflow execution in the UI:

```shell
👍 Build submitted!
⏳ Waiting for build to finish at: https://<union-host-url>/org/...
✅ Build completed in 0:01:57!

[✔] Go to https://<union-host-url>/org/... to see execution in the UI.
```

Click the link to see the execution in the UI.

## Register the workflow without running

Above we used the `pyflyte run --remote` to register and immediately run a workflow on Flyte.

This is useful for quick testing, but for more complex workflows you may want to register the workflow first and then run it from the Flyte interface.

To do this, you can use the `pyflyte register` command to register the workflow code with Flyte.

The form of the command is:

```shell
$ pyflyte register [<options>] <path-to-source-directory>
```

in our case, from within the `getting-started` directory, you would do:

```shell
$ pyflyte register --project my-project --domain development .
```

This registers all code in the current directory to Flyte but does not immediately run anything.
You should see the following output (or similar) in your terminal:

```shell
Running pyflyte register from /Users/my-user/scratch/my-project with images ImageConfig(default*image=Image(name='default', fqn='cr.flyte.org/flyteorg/flytekit', tag='py3.12-1.14.6', digest=None), images=[Image(name='default', fqn='cr.flyte.org/flyteorg/flytekit', tag='py3.12-1.14.6', digest=None)]) and image destination folder /root on 1 package(s) ('/Users/my-user/scratch/my-project',)
Registering against demo.hosted.unionai.cloud
Detected Root /Users/my-user/my-project, using this to create deployable package...
Loading packages ['my-project'] under source root /Users/my-user/my-project
No output path provided, using a temporary directory at /var/folders/vn/72xlcb5d5jbbb3kk_q71sqww0000gn/T/tmphdu9wf6* instead
Computed version is sSFSdBXwUmM98sYv930bSQ
Image say-hello-image:lIpeqcBrlB8DlBq0NEMR3g found. Skip building.
Serializing and registering 3 flyte entities
[✔] Task: my-project.hello_world.say_hello
[✔] Workflow: my-project.hello_world.hello_world_wf
[✔] Launch Plan: my-project.hello_world.hello_world_wf
Successfully registered 3 entities
```

## Run the workflow from the Flyte interface

To run the workflow, you need to go to the Flyte interface:

1. Navigate to the Flyte dashboard.
2. In the left sidebar, click **Workflows**.
3. Search for your workflow, then select the workflow from the search results.
4. On the workflow page, click **Launch Workflow**.
5. In the "Create New Execution" dialog, you can change the workflow version, launch plan, and inputs (if present). Click "Advanced options" to change the security context, labels, annotations, max parallelism, override the interruptible flag, and overwrite cached inputs.
6. To execute the workflow, click **Launch**. You should see the workflow status change to "Running", then "Succeeded" as the execution progresses.

To view the workflow execution graph, click the **Graph** tab above the running workflow.

## View the workflow execution on Flyte

When you view the workflow execution graph, you will see the following:

![Graph](https://www.union.ai/docs/v1/flyte/_static/images/user-guide/getting-started/running-your-workflow/graph.png)

Above the graph, there is metadata that describes the workflow execution, such as the
duration and the workflow version. Next, click on the `evaluate_model` node to open up a
sidebar that contains additional information about the task:

![Sidebar](https://www.union.ai/docs/v1/flyte/_static/images/user-guide/getting-started/running-your-workflow/sidebar.png)

