Skip to main content
IBM Quantum Platform
Información sobre la traducción

Próximamente habrá traducciones a otros idiomas de esta página.

Run a managed workflow

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

    qiskit-serverless~=0.38.0
    

A managed workflow job works like a batch job that you submit to an HPC scheduler. run() submits the job and returns a Job object immediately. Use the Job object for the tasks that squeue, the job's output file, and scancel cover on a cluster. The job keeps running after you close your notebook.

The examples on this page use a small workflow that reads one angle, theta, and fails if the angle is out of range. Upload it as described in Deploy your first managed workflow.

./source_files/my_workflow.py
import math

from qiskit_serverless import get_arguments, save_result

arguments = get_arguments()
theta = arguments["theta"]
if not 0 <= theta <= math.pi:
    raise ValueError(f"theta must be between 0 and pi, got {theta}")

print(f"Computing the expectation value for theta={theta}", flush=True)
save_result({"theta": theta, "expectation_value": math.cos(theta)})

Start a job

Get the workflow by its title, and call run() with the arguments that the workflow reads:

run_workflow_remotely.ipynb
from qiskit_ibm_catalog import ManagedWorkflowClient

client = ManagedWorkflowClient()
my_workflow = client.load("my-workflow")

job = my_workflow.run(theta=0.5)
job_id = job.job_id

run() returns after the workflow queues the job. Save the job ID so that you can find the job from a new session.


Follow a job

Check the status

Immediately after you call run(), the status is usually QUEUED:

run_workflow_remotely.ipynb
job.status()

Output:

'QUEUED'
Status
Meaning
QUEUEDThe job waits for a compute slot.
INITIALIZINGThe workflow is starting an environment with the job's compute profile.
RUNNINGThe workflow's entrypoint is running.
RUNNING: <stage>The entrypoint reported a stage with update_status(), such as RUNNING: WAITING_FOR_QPU.
CANCELINGYou canceled the job, and the workflow is stopping it.
DONEThe entrypoint exited successfully.
ERRORThe entrypoint raised an error or exited with a nonzero code. See Find the cause of an error.
CANCELEDYou canceled the job, or it reached the 24-hour limit.

DONE, ERROR, and CANCELED are final, and job.in_terminal_state() returns True for them. A status loop that waits for another value, such as SUCCEEDED, never ends.

Wait for the job to end

To wait until the job ends, call wait_for_final_state(). It returns the final status, and with verbose=True it prints each status change. If you set timeout in seconds, wait_for_final_state() raises a TimeoutError when the time runs out before the job ends. The job keeps running:

run_workflow_remotely.ipynb
job.wait_for_final_state(timeout=600, verbose=True)
Waiting for job 3f2a1c0e-6b1d-4c0e-9a51-2f0c4d1e7a90
0:00:00  QUEUED
0:02:10  RUNNING
0:03:05  RUNNING: WAITING_FOR_QPU
0:41:44  DONE
'DONE'

wait_for_final_state() checks the status after 1, 2, 4, 8, 16, and 32 seconds, and then every 60 seconds, so it sees the end of a short job within seconds and makes few requests for a long job. To check at a fixed interval instead, pass poll_interval in seconds.

Read the logs

Anything that the workflow writes to standard output or standard error goes to the job's logs. You can read them with job.logs() while the job runs, before it has a result:

run_workflow_remotely.ipynb
print(job.logs())

Output:

Computing the expectation value for theta=0.5

  • The workflow uploads new log lines about every 15 seconds, and one last time when the job ends or is canceled. Immediately after a job starts, job.logs() returns No logs yet.
  • The workflow keeps the newest 50 MB of logs for each job, and adds a line at the top that says the logs were truncated.

To decide what your workflow logs, see Write logs. To show only the lines that match a regular expression, pass include to job.filtered_logs(). To hide lines, pass exclude.

Get the result

job.result() waits until the job ends, then returns the value that the workflow passed to save_result():

run_workflow_remotely.ipynb
job.result()

Output:

{'theta': 0.5, 'expectation_value': 0.8775825618903728}

By default, job.result() checks the status every 30 seconds and waits with no time limit. Pass maxwait to limit the number of checks. For example, job.result(maxwait=40) waits about 20 minutes. To check one time without waiting, pass wait=False. If job.result() stops waiting before the job ends, it returns {}.

Check how long each stage took

job.events() lists every status and stage change of a job with its time, so you can see how long the job waited for compute and how long each stage took:

run_workflow_remotely.ipynb
for event in reversed(job.events()):
    print(
        event.created,
        event.data.get("status") or event.data.get("sub_status"),
    )

Output:

2026-11-02T14:43:07.134377Z QUEUED
2026-11-02T14:43:24.474199Z PENDING
2026-11-02T14:46:07.309519Z RUNNING
2026-11-02T14:46:21.115038Z SUCCEEDED

The events use the stored status names. PENDING is INITIALIZING, and SUCCEEDED is DONE. For the QPU usage of a run, see Find the QPU jobs of a run.


Find the cause of an error

When the workflow raises an exception, the job ends with the ERROR status. For example, run the workflow with an angle that it rejects:

run_workflow_remotely.ipynb
failed_job = my_workflow.run(theta=-1.0)
run_workflow_remotely.ipynb
failed_job.status()

Output:

'ERROR'

The logs show the traceback:

run_workflow_remotely.ipynb
print(failed_job.logs())

Output:

Traceback (most recent call last):
  File "/function_user_data/my_workflow.py", line 8, in <module>
    raise ValueError(f"theta must be between 0 and pi, got {theta}")
ValueError: theta must be between 0 and pi, got -1.0

job.result() raises a QiskitServerlessException:

run_workflow_remotely.ipynb
from qiskit_serverless.exception import QiskitServerlessException

try:
    failed_job.result()
except QiskitServerlessException as error:
    print(error)

Output:

    raise ValueError(f"theta must be between 0 and pi, got {theta}")
ValueError: theta must be between 0 and pi, got -1.0

If the workflow reports errors with send_error(), read them with job.events(type="ERROR"), and read their messages with job.error_message(). For a job without reported errors, job.events(type="ERROR") returns an empty list, and job.error_message() returns {}.

run_workflow_remotely.ipynb
for event in job.events(type="ERROR"):
    print(event.created, event.data.get("code"), event.data.get("message"))

Manage jobs

Cancel a job

Cancel a job with job.cancel(). The status changes to CANCELING while the workflow stops the job, and then to CANCELED:

run_workflow_remotely.ipynb
job_to_cancel = my_workflow.run(theta=1.0)
job_to_cancel.cancel()

Output:

'Job has been stopped. No active runtime job ID associated with this serverless job ID.'

job.cancel() returns a message about the job and about its linked QPU jobs, which it also tries to cancel. For a running job, the workflow sends SIGTERM to your entrypoint. To save partial results, see Clean up when a job is canceled. If the job already ended, job.cancel() returns Job already in terminal state. and changes nothing.

Find a job from a new session

The Job object and the workflow exist only in your current Python session. After you restart a notebook kernel, pass the saved job ID to client.job(), or list your recent jobs with client.jobs():

run_workflow_remotely.ipynb
from qiskit_ibm_catalog import ManagedWorkflowClient

client = ManagedWorkflowClient()
job = client.job(job_id)
my_workflow = client.load("my-workflow")

client.jobs(function=my_workflow, status="ERROR", limit=5)

Output:

[<Job | e6b1ffa1-cd26-437d-bd53-b265dd4ba952>,
 <Job | 11308f2a-8d7a-40a0-a970-7fdeca2b171b>,
 <Job | af597785-3470-469a-9051-607e0185892e>,
 <Job | a9051931-3bc2-4b80-9ce6-c39d28ce260c>,
 <Job | e329e8e3-e955-4188-9bfd-8f3050ee2d39>]

client.jobs() returns your 10 most recent jobs, newest first. Filter it with function, status (from the status table), or created_after (an ISO 8601 timestamp), and page through it with limit and offset. To list the workflows that you uploaded, call client.list().

The Workloads table on IBM Quantum Platform also lists your jobs, with their status, compute profile, and run times.

Time limit

A managed workflow cancels a job that runs for more than 24 hours, and the job ends with the CANCELED status. During long runs, save checkpoints to file storage so that you do not lose work.


Troubleshoot jobs

Problem
Cause
run() fails with Code: 429 and Active job limit reached.You reached the active job limit. Wait for some jobs to end, or cancel jobs that you no longer need.
The job stays QUEUED, and run() warned that your account, plan or subscription is blocked.The job does not start until the block on your account, plan, or subscription is lifted. Contact your administrator.
job.logs() returns No logs yet.The job is queued or just started. Wait about 15 seconds.
job.result() returns {}The job has not ended, was canceled, or saved no result. See Save results.
job.error_message() returns {}The workflow raised an exception without reporting an error. Read the traceback with job.logs().
The job is CANCELED, but you did not cancel itThe job reached the 24-hour limit.

Next steps

Recommendations
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.