Verification (verify.yml)

Otto automatically verifies generated code — running lint, build, and test commands — before opening a pull request. You can customize this behavior with a .otto/verify.yml file in your repository root.

Quick Start

In most cases, you don't need a verify.yml file at all. Otto auto-detects your project type and runs the appropriate commands. Add one only when you need to customize the defaults.

# .otto/verify.yml
max_retries: 3
runtime:
  node: '20'
verify:
  - pnpm run lint
  - pnpm run build

Configuration Reference

FieldTypeDefaultDescription
enabledbooleantrueSet to false to skip verification entirely
max_retriesnumber2How many times the fix agent retries on failure (0–5)
runtimemap(auto-detected)Runtime tool versions to install (e.g., node: "20")
installstring(auto-detected)Dependency install commands
verifystring(auto-detected)Verification commands (lint, build, test, etc.)
timeout.install_secondsnumber300Timeout per install command (seconds)
timeout.verify_secondsnumber180Timeout per verify command (seconds)

Full Example

# .otto/verify.yml

# Disable verification entirely (not recommended)
# enabled: false

# Number of times the fix agent will retry on failure (0–5)
max_retries: 3

# Runtime versions (installed via mise)
runtime:
  node: '20'
  python: '3.12'

# Dependency installation (run sequentially, fail-fast)
install:
  - pnpm install --frozen-lockfile
  - pip install -e .

# Verification commands (run sequentially, all results collected)
verify:
  - pnpm run lint
  - pnpm run build
  - pnpm run test
  - pytest

# Per-command timeouts
timeout:
  install_seconds: 600
  verify_seconds: 300

Auto-Detection

When install and verify are omitted, Otto detects your project type and generates commands automatically.

Project TypeDetected ByInstall CommandVerify Commands
Node.js (pnpm)pnpm-lock.yamlpnpm install --frozen-lockfilepnpm run lint, pnpm run build, pnpm run test
Node.js (yarn)yarn.lockyarn install --frozen-lockfileyarn run lint, yarn run build, yarn run test
Node.js (npm)package-lock.jsonnpm cinpm run lint, npm run build, npm run test
.NET*.csproj or *.slndotnet restoredotnet build --no-restore, dotnet test --no-build
Gogo.modgo mod downloadgo vet ./..., go build ./...
Pythonpyproject.tomlpip install -e .ruff check ., pytest
RustCargo.toml(none)cargo check, cargo clippy
MakefileMakefile(none)make lint, make build, make test

For Node.js projects, only scripts that exist in your package.json are included. If your package.json has no test script, pnpm run test won't be added.

For Makefile projects, only targets that exist in your Makefile are included.

Runtime Version Detection

Otto also auto-detects runtime versions when the runtime field is omitted:

Node.js — checked in order:

  1. .node-version file
  2. .nvmrc file
  3. .tool-versions file (nodejs entry)
  4. package.json engines.node field (extracts major version)

.NET — reads global.json sdk.version field

Other runtimes (Go, Python, Rust) — defaults to latest when auto-detected

Runtimes are installed via mise, so any tool mise supports can be specified in the runtime map (e.g., java: "21", ruby: "3.3").

Partial Configuration

You can override specific fields while relying on auto-detection for the rest. If you provide runtime, max_retries, or timeout but omit install and verify, Otto will auto-detect the commands and merge your overrides.

# Auto-detects everything else
max_retries: 4

How Verification Works

After the code agent finishes making changes, Otto runs verification before opening a PR:

  1. Install runtimes — Installs each tool version from runtime via mise
  2. Run install commands — Runs install commands sequentially; stops immediately if any fail
  3. Run verify commands — Runs verify commands sequentially; collects all results (does not stop on first failure)
  4. Retry on failure — If any verify command fails, a fix agent receives the errors and attempts to correct the code, then verification re-runs (up to max_retries times)
  5. Report in PR — Results are included in the pull request body

PR Result Examples

When all checks pass:

### Verification

✅ All checks passed (3 commands, 1 attempt)

When checks fail after retries:

### Verification

> **Warning**: Verification failed after 3 attempts

- `pnpm run lint` (exit code 1)
- `pnpm run build` (exit code 1)

Best Practices

Start with auto-detection. Otto's defaults work well for most projects. Only create a verify.yml when you need to customize behavior.

Keep verify commands fast. Verification runs on every agent task. Long-running test suites slow down the feedback loop. Consider running only fast checks (lint, build, unit tests) and leaving integration tests to your CI pipeline.

Use enabled: false sparingly. Disabling verification means the agent's code won't be checked before a PR is opened. Use this only for repositories where verification isn't applicable.

Set appropriate timeouts. The defaults (5 minutes for install, 3 minutes per verify command) work for most projects. Increase them for large monorepos or slow build steps.

Increase retries for complex projects. If your codebase has strict linting or complex build requirements, bumping max_retries to 3–4 gives the fix agent more chances to correct issues.