# Search and verify a transition state

Submit a TS search strategy, run strict Hessian/IRC verification and publish the result.

Submit a transition-state (TS) search strategy for a proposed reaction. Each submission runs a 3-stage pipeline—**search** (`ts-search@1`), **verify** (`ts-verify@1`), and **save** (`ts-save@1`)—so candidate saddle points are independently checked by Hessian and IRC calculations before being saved.

## 1. Check prerequisites

Before submitting a TS search, make sure you have:

1. **A saved reaction proposal UUID** in your project with balanced atoms, charge, and a single elementary step.
2. **Published TS Programs** in your project. Check that `ts-search@1` is registered:

```bash
ct-cli program list
ct-cli program show ts-search@1
```

## 2. Submit a TS search from the CLI or Python

From the CLI, pass a reaction proposal UUID, your strategy script (see `compute/ts/examples/strategy.py`) and the spin multiplicity:

```bash
ct-cli ts submit PROPOSAL_UUID \
  --strategy compute/ts/examples/strategy.py \
  --multiplicity 1 \
  --wait
```

Or submit directly from Python for a reaction proposal UUID:

```python
from pathlib import Path
from uuid import UUID
from chemistry_compute import Client
from chemistry_ts.submission import submit

client = Client.from_login()
assert client.project_id is not None, "Run ct-cli login --project PROJECT_UUID first"

run = submit(
    client,
    client.project_id,
    proposal_id=UUID("00000000-0000-7000-8000-000000000001"),
    source=Path("compute/ts/examples/strategy.py").read_text(),
    multiplicity=1,
)
print(run.id, run.search.id, run.verify.id, run.save.id)
saved = run.result(timeout=3600)
print(saved)
```

Key parameters:

- **`proposal_id`** — UUID of the stored elementary reaction proposal.
- **`source`** — Python source code of your search strategy, which defines `find_ts(reactant_smiles, product_smiles, charge, multiplicity, calculator)`.
- **`multiplicity`** — Spin multiplicity (`1` = singlet, `2` = doublet, `3` = triplet).

## 3. Understand how verification works

Optimizer convergence alone never marks a transition state as verified. The 3-stage pipeline separates proposing a geometry from proving it:

| Stage                | What it runs                                                                   | Output                                     |
| -------------------- | ------------------------------------------------------------------------------ | ------------------------------------------ |
| **1. `ts-search@1`** | Runs your `strategy.py` to propose a candidate TS geometry                     | `results/candidate.json`                   |
| **2. `ts-verify@1`** | Computes the Hessian (1 imaginary frequency) and forward/reverse IRC endpoints | `results/result.json` with Hessian and IRC |
| **3. `ts-save@1`**   | Publishes the verified TS and IRC endpoints to your project                    | Saved calculation record                   |

> **Note:** If a reaction step is barrierless or the IRC connects to different species, `ts-verify@1` records a **scientific negative**. That is a valid scientific result, not an infrastructure crash.

## 4. Check status and retry failed stages

Inspect all three stages of a TS run with `ct-cli ts status`:

```bash
ct-cli ts status RUN_UUID
```

If `verify` or `save` fails due to a transient worker error, retry from the failed stage without re-running the upstream search:

```bash
ct-cli ts retry RUN_UUID
```

`ct-cli ts retry` reuses the completed upstream artifacts and prints the new `RUN_UUID` for the retried chain. See [Inspect and recover a run](/operate/recovery/) for details, [Test parsers and TS strategies](/test/algorithms/) to benchmark a new search strategy, or [Evaluate DFT energies](/science/dft/) to compute single-point DFT barriers on verified geometries.
