---
title: Write your first Qiskit Serverless program
description: How to create a parallel transpilation program and deploy it to IBM Quantum Platform to use as a reusable remote service.
source: https://eu-de.quantum.cloud.ibm.com/docs/en/guides/serverless-first-program
---

# Write your first Qiskit Serverless program

### Package versions

The code on this page was developed using the following requirements.
We recommend using these versions or newer.

```
qiskit[all]~=1.3.1
qiskit-ibm-runtime~=0.34.0
qiskit-aer~=0.15.1
qiskit-serverless~=0.18.1
qiskit-ibm-catalog~=0.2
qiskit-addon-sqd~=0.8.1
qiskit-addon-utils~=0.1.0
qiskit-addon-mpf~=0.2.0
qiskit-addon-aqc-tensor~=0.1.2
qiskit-addon-obp~=0.1.0
scipy~=1.15.0
pyscf~=2.8.0
```

> **Tip**
>
> **Qiskit Serverless is getting an upgrade, and its features are changing fast.** During this development phase, find release notes and the most recent documentation at the [Qiskit Serverless GitHub](https://qiskit.github.io/qiskit-serverless/index.html) page.

This example demonstrates how to use `qiskit-serverless` tools to create a parallel transpilation program, and then implement `qiskit-ibm-catalog` to upload your program to IBM Quantum Platform to use as a reusable remote service.

## Workflow overview

1. Create a local directory and empty program file (`./source_files/transpile_remote.py`)
2. Add code to your program that, when uploaded to Qiskit Serverless, will transpile a circuit
3. Use `qiskit-ibm-catalog` to authenticate to Qiskit Serverless
4. Upload the program to Qiskit Serverless

After uploading your program , you can run it to transpile the circuit by following the [Run your first Qiskit Serverless workload remotely](/docs/guides/serverless-run-first-workload) guide.

## Example: Remote transpilation with Qiskit Serverless

This example walks you through creating and adding to a program file that, when you upload it to Qiskit Serverless, will transpile a `circuit` against a given `backend` and target `optimization_level`.

> **Tip**
>
> Qiskit Serverless requires setting up your workload’s `.py` files into a dedicated directory. The following structure is an example of good practice:
>
> ```text
> serverless_program
> ├── program_uploader.ipynb
> └── source_files
>     ├── transpile_remote.py
>     └── *.py
> ```

Serverless uploads the contents of a specific directory (in this example, the `source_files` directory) to run remotely. After these are set up, you can adjust `transpile_remote.py` to fetch inputs and return outputs.

### Create the directory and an empty program file

First, create a directory named `source_files`, then create a program file in the directory, so that its path is `./source_files/transpile_remote.py`. This is the file you will upload to Qiskit Serverless.

### Add code to your program file

Populate your program file with the following code, then save it.

> **Caution**
>
> If you're reading the code cells locally in a notebook, you will see the `%%writefile` [magic command](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile). Executing cells with this magic command saves them to disk rather than executing them.

```python
# This cell is hidden from users, it creates a new folder
from pathlib import Path

Path("./source_files").mkdir(exist_ok=True)
```

```python
# If you include the preceding `%%writefile` command (visible only when you read this
# locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit.transpiler import generate_preset_pass_manager

def transpile_remote(circuit, optimization_level, backend):
    """Transpiles an abstract circuit into an ISA circuit for a given backend."""
    pass_manager = generate_preset_pass_manager(
        optimization_level=optimization_level,
		backend=backend
    )
    isa_circuit = pass_manager.run(circuit)
    return isa_circuit
```

### Add code to get program arguments

Now add the following code to your program file, which sets up program arguments.

Your initial `transpile_remote.py` has three inputs: `circuits`, `backend_name`, and `optimization_level`. Serverless is currently limited to only accept serializable inputs and outputs. For this reason, you cannot pass in `backend` directly, so use `backend_name` as a string instead.

```python
# If you include the preceding `%%writefile` command (visible only when you read this
# locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit_serverless import get_arguments, save_result, distribute_task, get

# Get program arguments
arguments = get_arguments()
circuits = arguments.get("circuits")
backend_name = arguments.get("backend_name")
optimization_level = arguments.get("optimization_level")
```

### Add code that calls the backend

Add the following code to your program file, which calls your backend with `QiskitRuntimeService`.

The following code assumes that you have already followed the process to save your credentials by using `QiskitRuntimeService.save_account`, and will load your default saved account unless you specify otherwise. See [Save your login credentials](/docs/guides/save-credentials) and [Initialize your IBM Quantum Compute Service account](/docs/guides/initialize-account) for more information.

```python
# If you include the preceding `%%writefile` command (visible only when you read this
# locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.backend(backend_name)
```

### Add code to transpile

Finally, add the following code to your program file. This code runs `transpile_remote()` across all `circuits` passed in, and returns the `transpiled_circuits` as a result:

```python
# If you include the preceding `%%writefile` command (visible only when you read this
# locally in a notebook), running this cell saves to disk rather than executing the code.

# Each circuit is being transpiled and will populate the array
results = [
    transpile_remote(circuit, 1, backend)
    for circuit in circuits
]

save_result({
    "transpiled_circuits": results
})
```

### Authenticate to Qiskit Serverless

Use `qiskit-ibm-catalog` to authenticate to `QiskitServerless` with your API key (you can use your `QiskitRuntimeService` API key, or create a new API key on the [IBM Quantum Platform dashboard]()).

```python
from qiskit_ibm_catalog import QiskitServerless, QiskitFunction

# Authenticate to the remote cluster and submit the pattern for remote execution
serverless = QiskitServerless()
```

### Run code to upload

Run the following code to upload the program. Qiskit Serverless compresses the contents of `working_dir` (in this case, `source_files`) into a `tar`, which is uploaded and then cleaned up. The `entrypoint` identifies the main program executable for Qiskit Serverless to run.

```python
transpile_remote_demo = QiskitFunction(
    title="transpile_remote_serverless",
    entrypoint="transpile_remote.py",
    working_dir="./source_files/",
)
```

```python
serverless.upload(transpile_remote_demo)
```

Output:

```
QiskitFunction(transpile_remote_serverless)
```

### Verify upload

To check if it successfully uploaded, use `serverless.list()`, as in the following code:

```python
# Get program from serverless.list() that matches the title of the one we uploaded
next(
    program
    for program in serverless.list()
    if program.title == "transpile_remote_serverless"
)
```

Output:

```
QiskitFunction(transpile_remote_serverless)
```

## Next steps

> **Recommendations**
>
> - Learn how to pass inputs and run your program remotely in the [Run your first Qiskit Serverless workload remotely](/docs/guides/serverless-run-first-workload) topic.
