Skip to content

Harness provider availability: install extras + harness doctor preflight + standardized missing-binary errors #685

Description

@santoshkumarradha

Summary

A harness provider needs an external coding-agent to be present at runtime (a CLI binary and/or a Python/JS SDK wrapper, plus auth). Today there is no first-class way to (a) install the providers you intend to use, or (b) verify they are actually installed and usable before you run a real workflow. Failures surface late, mid-run, as a subprocess error inside app.harness(...). This is especially painful in containers/CI where you want the image build to fail fast if a required harness is missing.

We want a clean, bloat-free DX for declaring and verifying harness provider availability, consistent across the Python, TypeScript, and Go SDKs.

Why "just add pip/npm extras" is not enough

The real dependency is usually a binary, not a pip/npm library:

Provider Python install TS/JS install Underlying binary
claude-code claude-agent-sdk (PyPI) @anthropic-ai/claude-agent-sdk (npm) bundles the Claude Code CLI
codex openai-codex (PyPI) or raw CLI @openai/codex-sdk (npm) codex (Rust binary, npm/brew)
gemini none (CLI only) none official (CLI only) gemini (npm @google/gemini-cli)
opencode opencode-ai (PyPI, alpha) or raw CLI @opencode-ai/sdk (npm) opencode (curl/npm)

So pip/npm extras can pin the Python/JS glue where an SDK exists, but they cannot install the actual agent binary (gemini, opencode, codex, the bundled claude node binary). An extra that installs nothing real (e.g. gemini) would be misleading. We need extras and a runtime preflight that checks ground truth (binary on PATH + version + auth).

Context: gemini-cli is being retired for consumer tiers on 2026-06-18 (superseded by Antigravity). Factor this into how aggressively we invest in a gemini extra.

Proposed DX (three layers)

1. Optional extras for the pip/npm-installable wrappers

  • Python: agentfield[harness-claude], [harness-codex], [harness-opencode], and [harness-all]. (Today only harness / harness-claude exist and both just pull claude-agent-sdk.)
  • TS: optional peerDependencies for @openai/codex-sdk and @opencode-ai/sdk (we already mark @anthropic-ai/claude-agent-sdk optional).
  • These pin versions and make import work; they do not claim to install binaries.

2. A harness doctor preflight (the real fix for "is it installed?")

A single command/function that, per provider, checks: binary on PATH (shutil.which), version (and min-version compatibility), and auth (required env vars present). Returns a structured report and a non-zero exit when a requested provider is unusable.

  • CLI: af harness doctor [--provider opencode,codex] [--json]
  • Library: await app.harness_doctor(providers=[...]) -> list[ProviderHealth]
  • This is the thing you run in a Dockerfile / CI step / container entrypoint to guarantee the harness is present before any real (paid) run. Same pattern as flutter doctor, gh auth status.

3. Standardized, actionable missing-dependency errors (fail fast, not mid-run)

  • Every provider does a shutil.which-style preflight before spawning the subprocess, and raises a typed HarnessProviderUnavailable naming the exact install command and the missing auth env var.
  • The CLI providers already do part of this on FileNotFoundError; make it proactive, typed, and uniform across all four providers and all three SDKs.

Acceptance criteria

  • Python extras: harness-claude, harness-codex, harness-opencode, harness-all.
  • TS optional peer deps for codex + opencode SDKs.
  • af harness doctor CLI + app.harness_doctor() library API returning structured per-provider health (installed / version / auth / usable), non-zero exit on any requested provider being unusable.
  • Typed HarnessProviderUnavailable raised before subprocess spawn, with exact install command + missing auth env var, uniform across providers.
  • Docs: per-provider install matrix + a "verify in your container" snippet.
  • Mirror the design in Python first, then port to TS and Go (Go is subprocess-only, so doctor + errors matter most there).

Open question

Should doctor optionally attempt a zero-cost liveness probe (e.g. --version / a no-op invocation) per provider, or only static PATH/env checks? Static is faster and offline-safe; a probe catches broken installs. Lean static by default, probe behind a --probe flag.


Spun out of the harness UX/DX review done alongside #684 (project_dir/cwd output placement fix).

Metadata

Metadata

Assignees

No one assigned

    Labels

    ai-friendlyWell-documented task suitable for AI-assisted developmentarea:harnessCoding agent harness integrationarea:sdkCross-SDK (Python + Go + TS) parity workdocumentationImprovements or additions to documentationenhancementNew feature or requesthelp wantedExtra attention is neededsdk:goGo SDK relatedsdk:pythonPython SDK relatedsdk:typescriptTypeScript SDK related

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions