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

=== PAGE: https://www.union.ai/docs/v1/union/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 Union.ai workflows.

## Gather your credentials

After your administrator has onboarded you to Union.ai (see [Deployment](https://www.union.ai/docs/v1/union/deployment/page.md)), you should have the following at hand:

- Your Union.ai credentials.
- The URL of your Union.ai instance. We will refer to this as `<union-host-url>` below.

## Log into Union.ai

Navigate to the UI at `<union-host-url>` and log in with your credentials.
Once you have logged in you should see the Union.ai UI.

To get started, try selecting the default project, called `flytesnacks`, from the list of projects.
This will take you to `flytesnacks` project dashboard:

![Union.ai UI](https://www.union.ai/docs/v1/union/_static/images/quick-start/byoc-dashboard.png)

This dashboard gives you an overview of the workflows and tasks in your project.
Since you are just starting out, it will be empty.
To build and deploy your first workflow, the first step is to **Getting started > Local setup**.

=== PAGE: https://www.union.ai/docs/v1/union/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 Union.ai 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

Union 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 `union`),
> `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 `union` requires `>=3.9,<3.13`.

## Install the `union` CLI

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

```shell
$ uv tool install union
```

This will make the `union` 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 `union` 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 `union` CLI to run your workflows.
> In those cases you will be running `union` within the Python virtual environment of your workflow project.
> You will not be using this globally installed instance of `union`.
> This instance of `union` is only used during the configuration step, below, when no projects yet exist.

## Configure the connection to your cluster

Next, you need to create a configuration file that contains your Union.ai connection information:

```shell
$ union create login --host <union-host-url>
```

`<union-host-url>` is the URL of your Union.ai instance, mentioned in **Getting started > Local setup**.

This will create the `~/.union/config.yaml` with the configuration information to connect to your Union.ai instance.

> [!NOTE]
> These directions apply to Union.ai BYOC and Self-managed, where you connect to your own dedicated Union.ai instance.

See [Running in a local cluster](https://www.union.ai/docs/v1/union/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 -->

By default, the Union CLI will look for a configuration file at `~/.union/config.yaml`. (See [Union CLI](https://www.union.ai/docs/v1/union/api-reference/union-cli) for more details.)
You can override this behavior to specify a different configuration file by setting the `UNION_CONFIG` environment variable:

```shell
$ export UNION_CONFIG=~/.my-config-location/my-config.yaml
```

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

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

> [!WARNING]
> If you have previously used Union.ai, you may have configuration files left over that will interfere with
> access to Union.ai Serverless through the Union CLI tool.
> Make sure to remove any files in `~/.unionai/` or `~/.union/` and unset the environment
> variables `UNIONAI_CONFIG` and `UNION_CONFIG` to avoid conflicts.

See [Running in a local cluster](https://www.union.ai/docs/v1/union/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
$ union info
```

You should get a response like this:

```shell
$ union info
╭────────────────────────────────────────────────────────── Union.ai CLI Info ─────────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│ union is the CLI to interact with Union.ai. Use the CLI to register, create and track task and workflow executions locally and remotely. │
│                                                                                                                                       │
│ Union.ai Version    : 0.1.132                                                                                                            │
│ Flytekit Version : 1.14.3                                                                                                             │
│ Union.ai Endpoint   : <union-host-url>                                                                                                   │
│ Config Source    : <path-to-config> file                                                                                              │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

For more details on connection configuration see [Authentication](https://www.union.ai/docs/v1/union/user-guide/development-cycle/authentication).

=== PAGE: https://www.union.ai/docs/v1/union/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 Union.ai project to which you will deploy that code using the `union` CLI.

## Create a new Union.ai project

Create a new project in the Union.ai UI by clicking on the project breadcrumb at the top left and selecting **All projects**:

![Select all projects](https://www.union.ai/docs/v1/union/_static/images/user-guide/getting-started/first-project/select-all-projects.png)

This will take you to the **Projects list**:

![Projects list](https://www.union.ai/docs/v1/union/_static/images/user-guide/getting-started/first-project/projects-list.png)

Click on the **New Project** button and fill in the details for your new project.
For this example, let's create a project called **My project**:

![Create new project](https://www.union.ai/docs/v1/union/user-guide/_static/images/user-guide/getting-started/first-project/create-new-project.png "small")

You now have a project on Union.ai named "My Project" (and with project ID `my-project`) into which you can register your workflows.

> [!NOTE] Default project
> Union.ai 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 `union init` command to initialize a new local project corresponding to the project created on your Union.ai instance:

```shell
$ union init --template union-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 Union.ai project ID
> It is good practice to name your local project directory the same as your
> Union.ai 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/union/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 Union.ai workflow:

```python
# Hello World

import union

image_spec = union.ImageSpec(
    # The name of the image. This image will be used byt he say_hello task
    name="say-hello-image",

    # Lock file with dependencies to install in image
    requirements="uv.lock",

    # Build the image using Union's built-in cloud builder (not locally on your machine)
    builder="union",
)

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

@union.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 `builder` to use to build the image.
  * We specify `union` to indicate that the image is built using Union.ai's cloud image builder.

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

### Tasks

The `@union.task` decorator indicates a Python function that defines a [**task**](https://www.union.ai/docs/v1/union/user-guide/core-concepts/tasks).
A task tasks some input and produces an output.
When deployed to Union.ai 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/union/user-guide/core-concepts/tasks/task-parameters).

### Workflow

The `@union.workflow` decorator indicates a function that defines a [workflow](https://www.union.ai/docs/v1/union/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 Union.ai, 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] `@union.task` and `@union.workflow` syntax
> * The `@union.task` and `@union.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 `union init` from the `union-simple` template looks like this

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

(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, `union`.
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/union/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 `union` 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 `union` 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 `union` within your project's virtual environment using `uv`,
> you can prefix it use the `uv run` command. For example:
>
> `uv run union ...`
>
> Alternatively, you can activate the virtual environment with `source .venv/bin/activate` and then
> run the `union` 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 [`union run <FILE> <WORKFLOW>`](https://www.union.ai/docs/v1/union/api-reference/union-cli):

```shell
$ union 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
$ union 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 Union.ai 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 Union.ai instance in the cloud.

When task and workflow code is registered:

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

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

```shell
$ union run --remote --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 `union run --remote` to register and immediately run a workflow on Union.ai.

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 Union.ai interface.

To do this, you can use the `union register` command to register the workflow code with Union.ai.

The form of the command is:

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

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

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

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

```shell
Running union 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 Union.ai interface

To run the workflow, you need to go to the Union.ai interface:

1. Navigate to the Union.ai 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 Union.ai

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

![Graph](https://www.union.ai/docs/v1/union/_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/union/_static/images/user-guide/getting-started/running-your-workflow/sidebar.png)

