Metadata-Version: 2.4
Name: adaptorch
Version: 0.1.1
Summary: Task-adaptive multi-agent orchestration reference implementation
Author: Geunbin Yu
License-Expression: Apache-2.0
Project-URL: Homepage, https://adaptorch.com
Project-URL: Documentation, https://adaptorch.com/mcp-docs
Project-URL: Repository, https://github.com/dmae97/Adaptorch-MCP
Project-URL: Issues, https://github.com/dmae97/Adaptorch-MCP/issues
Project-URL: Paper, https://arxiv.org/abs/2602.16873
Project-URL: Security, https://adaptorch.com/trust
Project-URL: Changelog, https://github.com/dmae97/adaptorch/blob/main/docs/CHANGELOG.md
Project-URL: Reproducibility, https://github.com/dmae97/adaptorch/blob/main/docs/REPRODUCIBILITY.md
Keywords: multi-agent,agent orchestration,ai agents,llm orchestration,dag orchestration,task routing,adaptive synthesis,ai workflow,coding agents,benchmarking,research
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: <3.13,>=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: httpx>=0.27
Requires-Dist: Pillow>=10.0
Requires-Dist: pydantic>=2.5
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: pytest>=8.2; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: matplotlib>=3.10; extra == "dev"
Requires-Dist: numpy<2.5; extra == "dev"
Provides-Extra: api
Requires-Dist: fastapi>=0.112; extra == "api"
Requires-Dist: uvicorn[standard]>=0.30; extra == "api"
Requires-Dist: pydantic-settings>=2.4; extra == "api"
Requires-Dist: orjson>=3.10; extra == "api"
Provides-Extra: worker
Requires-Dist: rq>=1.16; extra == "worker"
Requires-Dist: redis>=5.0; extra == "worker"
Requires-Dist: sqlalchemy>=2.0; extra == "worker"
Requires-Dist: alembic>=1.13; extra == "worker"
Requires-Dist: psycopg[binary]>=3.2; extra == "worker"
Provides-Extra: obs
Requires-Dist: opentelemetry-sdk>=1.27; extra == "obs"
Requires-Dist: opentelemetry-exporter-otlp>=1.27; extra == "obs"
Requires-Dist: prometheus-client>=0.20; extra == "obs"
Requires-Dist: structlog>=24.1; extra == "obs"
Provides-Extra: auth
Requires-Dist: python-jose[cryptography]>=3.3; extra == "auth"
Requires-Dist: cryptography>=42; extra == "auth"
Provides-Extra: gmail
Requires-Dist: nodriver>=0.38; extra == "gmail"
Provides-Extra: test-api
Requires-Dist: pytest-asyncio>=0.23; extra == "test-api"
Requires-Dist: respx>=0.21; extra == "test-api"
Requires-Dist: schemathesis>=3.30; extra == "test-api"
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == "mcp"
Provides-Extra: a2a
Requires-Dist: a2a-sdk>=1.1.0; extra == "a2a"
Dynamic: license-file

<div align="center">

# AdaptOrch

**Reliability Kernel for Agent Stacks**

[![CI](https://github.com/dmae97/adaptorch/actions/workflows/ci.yml/badge.svg)](https://github.com/dmae97/adaptorch/actions/workflows/ci.yml)
[![Python 3.11–3.12](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue.svg)](https://www.python.org/downloads/)
[![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
[![Version](https://img.shields.io/badge/version-0.1.1-green.svg)](https://github.com/dmae97/adaptorch/releases)

AdaptOrch is a reliability add-on layer for `completion`, `recovery`,
`diagnostics`, and `reproducibility` (beta) without replacing your current stack.
Measured effects depend on the workload, provider, and configured evidence path.

It acts as a **Reliability Kernel** in front of existing agents and SDKs:
task-adaptive routing with disclosed fallbacks, conflict-signaling synthesis
with a disclosed adversarial gap, and reroute decisions designed for
operational trust in production pipelines.

Adaptive runtime control (`CSE-lite` + `NCMH`) lives inside that kernel as an
internal reliability engine for policy shifts, runtime evidence, and operator
visibility. The feature-gated VERA v2/CSE-NCMH implementation remains a
prototype and shadow foundation; it has no calibration, canary, or production
promotion claim.

Paper-aware reference implementation of **Topology Routing (Alg. 1)** and
**Adaptive Synthesis (Alg. 2)**, with a practical `robust` mode for noisy
real-world agent outputs.

[Paper (PDF)](사업계획서/AdaptOrch_final_v3.pdf) · [Current Algorithm & Benchmark State (2026-08-29)](docs/algorithms/2026-08-29-current-algorithm-and-benchmark-state.md) · [Docs Guide](docs/README.md) · [SaaS Readiness Decision (2026-03-27)](docs/saas_readiness_decision_2026-03-27.md) · [Architecture](docs/Architecture.md) · [Historical SaaS Connection Snapshot](docs/SaaS_connection.md) · [Library API](docs/library_api.md) · [SDK Compatibility](docs/sdk_compatibility.md) · [Request-Scoped BYOK Ensemble Spec](specs/012-request-scoped-byok-ensembles/spec.md) · [Reproducibility](docs/REPRODUCIBILITY.md) · [Native Backend Policy](docs/native_backend_policy.md) · [AI Indexing (`llms.txt`)](llms.txt) · [Contributing](docs/CONTRIBUTING.md) · [Support](docs/SUPPORT.md) · [Security](SECURITY.md)

> Release note: package metadata (`pyproject.toml`, `adaptorch.__version__`) and the badge track `0.1.1`. [`docs/CHANGELOG.md`](docs/CHANGELOG.md) remains the authoritative release history.

</div>

---

## Search-Friendly Summary

AdaptOrch is a Python reliability layer for **multi-agent orchestration** and
**LLM workflow routing**. It plugs into existing stacks, selects from the six
engine topologies (`parallel`, `sequential`, `hierarchical`, `hybrid`,
`multi_model_ensemble`, `multi_turn_debate`), and synthesizes outputs with a
paper-parity baseline (`paper`) or conflict-signaling mode (`robust`).

If you are searching for terms like **AI agent orchestration framework**, **LLM DAG orchestration**, **adaptive synthesis**, or **OpenCode/Claude/Codex multi-agent routing**, this repository is the canonical implementation.

## Table of Contents

- [Why AdaptOrch](#why-adaptorch)
- [Trust Signals](#trust-signals)
- [Benchmark Results](#benchmark-results)
- [Visual Snapshot](#visual-snapshot)
- [Quick Start](#quick-start)
- [Supported Entry Points](#supported-entry-points)
- [CLI Usage](#cli-usage)
- [Python Library Usage](#python-library-usage)
- [Input JSON Contract](#input-json-contract)
- [Native Backend (Optional)](#native-backend-optional)
- [Benchmark Output Contract](#benchmark-output-contract)
- [Vibe Coding Share Loop](#vibe-coding-share-loop)
- [Open Source Growth Plan](#open-source-growth-plan)
- [Enterprise / B2B Technical Readiness](#enterprise--b2b-technical-readiness)
- [Control Plane](#control-plane)
- [Pilot Sprint Templates](#pilot-sprint-templates)
- [Project Structure](#project-structure)
- [Reproducibility Scope](#reproducibility-scope)
- [AI Search FAQ](#ai-search-faq)
- [Development](#development)
- [License](#license)
- [Citation](#citation)

## Why AdaptOrch

- DAG-based orchestration for multi-step coding/research tasks
- Automatic structural topology selection: `parallel`, `sequential`, `hierarchical`, `hybrid`
- Extended topology paths: `multi_model_ensemble`, `multi_turn_debate`
- Direct-REST BYOK ensemble configuration: 2–5 same-provider members; current auto-fan-out is single-node and backend gaps are tracked in spec 012
- Consistency-aware synthesis with reroute recommendations
- Synthesis modes: `paper` (baseline parity), `robust` (conflict signaling), `robust_lite` (capability-gated), `stable_hybrid` (stability-margin); `fourier_aggressive` is accepted as a request value but always downshifts to `stable_hybrid`
- Python library first, CLI included

## Trust Signals

- Reliability-first CLI identity: `AdaptOrch Reliability Kernel`
- Conflict-signaling `robust` synthesis with anchor-level negation penalties and a
  disclosed adversarial gap (measured in `tests/test_algorithm_eval_synthesis_corpus.py`)
- Explicit run lifecycle (`QUEUED`/`RUNNING`/`SUCCEEDED`/`FAILED`/`CANCELLED`),
  result status (`OK`/`DEGRADED`/`FAILED`), and diagnostics
- Local-first control-plane dispatch: `auto` defaults to in-process background work;
  Redis/RQ is queue transport, not authoritative run-state or artifact durability
- BYOK provider keys are not persisted and are rejected under RQ; pre-execution cancel/dispatch cleanup remains an explicit gap
- Benchmark wall-clock budget enforcement via `budget_policy.max_total_time_seconds`
- Internal adaptive runtime control (`CSE-lite` + `NCMH`) surfaced through diagnostics and control-plane evidence
- Reproducibility beta: the Full50 sidecar artifact is canonical (byte-deterministic);
  other artifacts (`manifest.json`, `raw_results.jsonl`, `report.md`, tables) are
  wall-clock-anchored and not yet byte-reproducible
- Release hygiene gates: `ruff`, `mypy`, `pytest`, `uv build`

## Benchmark Results

Current results are local, seeded measurements—not official submissions or
release inputs.

| Evidence | Measured result | Boundary |
| --- | --- | --- |
| ModelStudio mixed-3, MATH-500 + GPQA slice | 0.00pp vs two stronger members; +2.00pp vs the weakest; all McNemar `p=1.0` | No gain over the best single member and no significant comparison; 6.1× tokens and 8.7× median latency, with fewer observed liveness losses (3/60 vs 4/8/10) |
| Six-model coverage probe on the same 60 units | pooled oracle ceiling 53/60 vs best single 52/60 | +1.7pp is a diagnostic upper bound, not delivered performance |
| SWE-bench Pro Python single-model baseline | 19/30 patches applied; 3/30 resolved | AdaptOrch was not in this loop; its contribution was not measured |
| SWE-bench Pro 3-model coverage ceiling | `C3=5/30` (16.7%, Wilson 95% CI 7.3–33.6%); `A3=22/30` | Oracle ceiling only; the preregistered accuracy gate did not open, and no AdaptOrch selector ran |

See the [2026-08-29 current-state ledger](docs/algorithms/2026-08-29-current-algorithm-and-benchmark-state.md)
for artifacts, confidence intervals, corrected scorer history, and exact claim
boundaries. `full50_go=NO_GO` is unchanged.

> The first four figures below are legacy paper-derived illustrations, not current
> local benchmark results. Their source values and historical boundary are in
> [`docs/Architecture.md` §2](docs/Architecture.md#2-source-artifacts-and-parsed-paper-data).

## Visual Snapshot

| Main Results | Topology Distribution |
|:---:|:---:|
| ![Main Results](docs/figures/main_results_accuracy.png) | ![Topology Heatmap](docs/figures/topology_distribution_heatmap.png) |

| Ablation Study | Convergence |
|:---:|:---:|
| ![Ablation](docs/figures/ablation_study.png) | ![Convergence](docs/figures/model_epsilon_convergence.png) |

### FULL50 PRE-RUN Evidence Alignment

![FULL50 PRE-RUN Evidence Alignment](docs/figures/adaptorch_full50_benchmark.png)

FULL50 PRE-RUN evidence alignment table binds BENCH-7.10 matrix evidence, BENCH-7.11 selector outcomes, and the BENCH-8.5c evidence manifest in the AdaptTorch / AdaptOrch release-evidence branding tone. Boundary: `PreRunEvidenceAligned=PASS`, `Full50GO=NO_GO`, `DecisionRoots=PENDING`, `SubmissionDecision=NONE`, `OfficialResolve=NOT_EVALUATED`, `CorrectnessClaim=0`, and output digest sidecar-only. Verify with `adaptorch full50 verify-alignment --figure docs/figures/adaptorch_full50_benchmark.png --sidecar docs/figures/adaptorch_full50_benchmark.sidecar.json --manifest docs/figures/adaptorch_full50_benchmark.manifest.json`; this does not claim correctness, submission readiness, official resolve, release GO, or benchmark solved.

Regenerate figures with `python scripts/generate_readme_figures.py`.

## Quick Start

```bash
# 1) Install
pip install -e ".[dev,api]"

# 2) Review the environment template (optional)
cp .env.example .env
# Direct uvicorn does not load this file.

# 3) Run a sample task
python -m adaptorch examples/sample_task.json --json

# 4) Use robust synthesis mode
python -m adaptorch examples/sample_task.json --json --synthesis-mode robust

# 5) Run benchmark pipeline
python -m adaptorch benchmark run --config examples/benchmark_paper_parity.json --json

# 6) Start Control Plane (optional)
# Direct uvicorn reads the process environment; it does not load .env.
export ADAPTORCH_CONTROL_PLANE_TOKEN="<local-token>"
uvicorn "adaptorch.control_plane:create_control_plane_app" \
  --factory --host 0.0.0.0 --port 8000
# Verify: curl http://127.0.0.1:8000/health

# 7) Connect MCP server to coding agents
# Claude Desktop / Claude Code — copy .mcp.example.json to .mcp.json for local use
# OpenCode/Codex/Gemini — use the same relative launcher:
#   command = "bash"
#   args = ["scripts/run_adaptorch_mcp.sh"]
```

> **Tip**: `.env.example` covers the primary local-mode `ADAPTORCH_*`
> settings. Experimental shared-mode variable names are listed in the
> [Control Plane API contract](docs/control_plane_api_contract.md); keep their
> values out of documentation and client-side configuration.

## Supported Entry Points

- CLI: `adaptorch` or `python -m adaptorch`
- Benchmark pipeline: `python -m adaptorch benchmark ...`
- MCP server: `adaptorch-mcp`, `uv run adaptorch-mcp`, or `bash scripts/run_adaptorch_mcp.sh`
- Local control plane: `uvicorn "adaptorch.control_plane:create_control_plane_app" --factory`; repository checkout helper: `bash scripts/run_local_control_plane.sh` (not installed by `[api]`)
- Hosted control plane bootstrap: `bash scripts/start_control_plane_service.sh`

If you want a map of the current docs and example payloads, start with `docs/README.md`.

## CLI Usage

### Single Task Orchestration

```bash
python -m adaptorch examples/sample_task.json --json
python -m adaptorch examples/sample_task.json --json --debug

# Paper-aligned routing thresholds
python -m adaptorch examples/sample_task.json --json \
  --theta-omega 0.50 --theta-gamma 0.60 --theta-delta 5

# Exact width (offline analysis)
python -m adaptorch examples/sample_task.json --json --exact-width
```

### Synthesis Modes

```bash
# Paper baseline
python -m adaptorch examples/sample_task.json --json --synthesis-mode paper

# Robust mode
python -m adaptorch examples/sample_task.json --json --synthesis-mode robust

# Capability-gated robust mode for constrained models
python -m adaptorch examples/sample_task.json --json --synthesis-mode robust_lite

# Stability-margin hybrid selection/merge path
python -m adaptorch examples/sample_task.json --json --synthesis-mode stable_hybrid

# Note: `--synthesis-mode fourier_aggressive` is still accepted but is a
# deprecated alias that always executes as `stable_hybrid`. Results report
# mode_requested vs mode_used so the downshift is never silent.
```

### Benchmark Pipeline

```bash
# Run
python -m adaptorch benchmark run --config examples/benchmark_paper_parity.json --json

# Supported first-class harness IDs include:
# swe_bench_verified, swe_pro, gpqa_diamond, hotpotqa, gsm8k, math_500,
# humaneval, mmlu, arc_agi, mbpp, ifeval

# Summarize (Table 2/3/4)
python -m adaptorch benchmark summarize --run-id <RUN_ID> --json

# Report
python -m adaptorch benchmark report --run-id <RUN_ID> --json

# Deferred official evaluation (when supported by the harness/run)
python -m adaptorch benchmark evaluate --run-id <RUN_ID> --json

# Fixed public result bundle (JSON + publication images + onepager)
python -m adaptorch benchmark bundle --run-id <RUN_ID> --json

# Windows wrapper with live progress + ETA for run + bundle
scripts\\run_benchmark_bundle_with_progress.bat --config examples\\benchmark_paper_parity.json --json
scripts\\run_benchmark_bundle_with_progress.bat --profile subscriptions --json
scripts\\run_benchmark_bundle_with_progress.bat --profile full --json
scripts\\run_benchmark_bundle_with_progress.bat --profile showcase --json
scripts\\run_benchmark_bundle_with_progress.bat --full --json
# Double-click / no-args default: official-dataset live CLI trio profile (`--profile full --json`)

# Required for --profile full / subscriptions:
export ADAPTORCH_SWE_BENCH_VERIFIED_DATASET=/abs/path/to/swe_bench_verified.jsonl
export ADAPTORCH_SWE_PRO_DATASET=/abs/path/to/swe_pro.jsonl
export ADAPTORCH_GPQA_DIAMOND_DATASET=/abs/path/to/gpqa_diamond.csv

# Optional dataset caps for quota-safe subscription runs:
export ADAPTORCH_SWE_BENCH_VERIFIED_LIMIT=3
export ADAPTORCH_SWE_PRO_LIMIT=3
export ADAPTORCH_GPQA_DIAMOND_LIMIT=8

# Optional evaluator overrides:
# SWE-bench Verified uses the official swebench harness by default.
# SWE-Pro requires an explicit evaluator command if you want container-backed resolve-rate.
export ADAPTORCH_SWE_PRO_EVALUATOR_CMD='docker run --rm -v {eval_root}:{eval_root} your-swe-pro-evaluator --predictions {predictions_path} --dataset {dataset_path}'

# The wrapper now runs Codex / Claude Code / Gemini CLI health-checks automatically
# before starting the live trio benchmark.

# One-page operations summary
python scripts/generate_benchmark_onepager.py --run-id <RUN_ID> --json

# Compare baseline vs policy-applied run
python scripts/compare_benchmark_runs.py \
  --baseline-run-id <BASELINE_RUN_ID> \
  --candidate-run-id <CANDIDATE_RUN_ID> \
  --json

# Community showcase draft (GitHub/Reddit)
python scripts/generate_community_showcase.py --run-id <RUN_ID> --channel both --json

# Provider detection
python -m adaptorch benchmark detect --provider auto --model gpt-4o-mini --json
```

#### Benchmark preset config example

```json
{
  "schema_version": 1,
  "run_name": "groq-low-call-robust",
  "benchmark_preset": "low-call",
  "provider": "groq",
  "model": "llama-3.1-8b-instant",
  "api": {
    "api_key_env": "GROQ_API_KEY",
    "base_url": "https://api.groq.com/openai/v1/chat/completions",
    "system_prompt": "You are a concise software engineering assistant."
  },
  "synthesis_mode": "robust",
  "benchmarks": [
    {
      "name": "sample",
      "dataset": "sample",
      "units": [
        {"id": "sample-1", "task_json": "examples/sample_task.json", "seed": 1}
      ]
    }
  ]
}
```

`benchmark_preset` supports `low-call`, `stable-run`, and `stress-run`.
Per-unit outputs in `raw_results.jsonl` include reliability metadata such as
`result_status` (`OK`/`DEGRADED`/`FAILED`), `error_class`, `diagnostics`, and `model_id`.
`table2.csv` separates strict accuracy from consistency fallback: scores from
`score_source in {override, extraction}` are aggregated as accuracy, while
consistency-derived rows are counted as `unscored` via
`accuracy_sample_count`, `unscored_count`, and `accuracy_coverage_pct`.
Use `budget_policy` in benchmark config to unify runtime constraints:

```json
{
  "budget_policy": {
    "max_cost_usd": 3.0,
    "max_total_time_seconds": 600.0,
    "p95_latency_target_seconds": 8.0,
    "max_retries": 3,
    "max_workers": 2,
    "requests_per_minute": 12,
    "provider_allowlist": ["groq", "openai"]
  }
}
```

#### External judge config example (optional)

```json
{
  "external_judge": {
    "enabled": true,
    "provider": "openrouter",
    "model": "gpt-4.1-mini",
    "max_context_chars": 4096,
    "api": {
      "api_key_env": "OPENROUTER_API_KEY",
      "base_url": "https://openrouter.ai/api/v1/chat/completions",
      "timeout_seconds": 30,
      "temperature": 0.0,
      "max_tokens": 64,
      "retry": {
        "max_attempts": 2,
        "initial_backoff_seconds": 0.5,
        "max_backoff_seconds": 4.0,
        "multiplier": 2.0,
        "jitter_ratio": 0.2
      }
    }
  }
}
```

When judge routing is triggered (`judge_recommended=true`), run records
`judge_model`, `judge_score`, `judge_cost_usd`, and `judge_latency_ms` in
`raw_results.jsonl`, and aggregates call/token/cost stats in
`manifest.json` under `external_judge`.
Judge is auto-disabled in replay mode (`disabled_reason: replay_mode`) to
keep deterministic replay behavior.

`scripts/compare_benchmark_runs.py` writes `policy_comparison.md` with
completion/score/latency/cost deltas in one format.
For robust runs, `report.md` automatically appends a `Robust Diversity Comparison`
section (proxy vs vendi coherence/latency aggregates).
For external sharing, `benchmark bundle` fixes a public artifact schema and generates
`public_bundle/result_bundle.json`, `public_bundle/onepager.md`,
`public_bundle/overview.png`, and `public_bundle/benchmark_scorecard.png` in one pass.
`scripts/generate_benchmark_onepager.py` remains available when only the markdown
onepager is needed.
Use `scripts/generate_community_showcase.py` to generate `showcase_post.md`
with copy-paste drafts for GitHub and Reddit.

### Provider/Model Experiments

```bash
# OpenRouter free-model sweep
python scripts/run_openrouter_free_benchmarks.py

# Groq paper vs robust sweep
python scripts/run_groq_meaningful_benchmark.py
```

## Python Library Usage

### Core API

- `run_task`, `run_task_file`, `load_task_payload`
- `run_benchmark`, `summarize_benchmark`, `report_benchmark`
- `bundle_benchmark`, `onepager_benchmark`
- `close_all_provider_clients`
- `detect_provider`
- `native_backend_available`

### 1) Run a task

```python
from pathlib import Path

from adaptorch import run_task, run_task_file

payload = {
    "subtasks": [
        {"id": "v1", "description": "Analyze issue", "estimated_tokens": 120},
        {"id": "v2", "description": "Draft fix", "estimated_tokens": 150},
    ],
    "dependencies": [{"from": "v1", "to": "v2", "coupling": "strong"}],
}

result = run_task(payload)
print(result.decision.topology)
print(result.synthesis.final_output)

result_from_file = run_task_file(Path("examples/sample_task.json"))
print(result_from_file.synthesis.consistency)
```

### 2) Robust config tuning

```python
from adaptorch import run_task
from adaptorch.synthesis import RobustSynthesisConfig

config = RobustSynthesisConfig(
    lexical_weight=0.55,
    structural_weight=0.25,
    numeric_weight=0.20,
    diversity_weight=0.15,
)

result = run_task(
    payload={
        "subtasks": [{"id": "v1", "description": "Investigate error", "estimated_tokens": 120}],
        "dependencies": [],
    },
    synthesis_mode="robust",
    robust_synthesis_config=config,
)

print(result.synthesis.consistency)
```

If you run many provider-backed library calls inside a long-lived process,
close the shared HTTP client pool before shutdown:

```python
from adaptorch import close_all_provider_clients

await close_all_provider_clients()
```

### 3) Attach coding agents and SDKs (OpenCode/Cline/Cursor/Windsurf/Lovable/LangChain/RAG)

```python
from adaptorch import run_task
from adaptorch.agent_adapters import (
    build_cline_cli_agent,
    build_cursor_cli_agent,
    build_gemini_cli_agent,
    build_langchain_runnable_agent,
    build_rag_agent,
    build_windsurf_cli_agent,
    build_lovable_cli_agent,
    build_claude_code_cli_agent,
    build_codex_cli_agent,
    build_opencode_cli_agent,
    build_roocode_cli_agent,
)

payload = {
    "subtasks": [{"id": "v1", "description": "Summarize root cause", "estimated_tokens": 120}],
    "dependencies": [],
}

# Tune command tuple per local CLI version if needed.
agent = build_codex_cli_agent()

result = run_task(payload, agent=agent, synthesis_mode="robust")
print(result.synthesis.final_output)

# Runnable bridge (e.g., LangChain/LangGraph)
# agent = build_langchain_runnable_agent(runnable=my_runnable)

# Retrieval-augmented bridge (RAG)
# agent = build_rag_agent(retriever=my_retriever, generator=my_generator)
```

Compatibility matrix and integration patterns:
`docs/sdk_compatibility.md`

### 4) Wire Claude Code, Codex, and Gemini CLI to this repo

AdaptOrch ships repo-local memory and MCP wiring for coding-agent CLIs:

- `AGENTS.md`: shared repository contract (Codex-compatible)
- `CLAUDE.md`: Claude Code project memory
- `GEMINI.md`: Gemini CLI project memory
- `.mcp.example.json`: copy to ignored `.mcp.json` for local Claude Code MCP registration
- `scripts/run_adaptorch_mcp.sh`: shared stdio launcher for AdaptOrch MCP

Required environment:

```bash
export ADAPTORCH_CONTROL_PLANE_TOKEN="replace-me"
export ADAPTORCH_CONTROL_PLANE_BASE_URL="http://127.0.0.1:8000"  # optional
```

Claude Code picks up `.mcp.json` in this repository; copy `.mcp.example.json` to `.mcp.json` and keep local paths/secrets out of git.

Codex example (`~/.codex/config.toml`):

```toml
[mcp_servers.adaptorch]
command = "bash"
args = ["scripts/run_adaptorch_mcp.sh"]
env = { ADAPTORCH_CONTROL_PLANE_BASE_URL = "http://127.0.0.1:8000" }
```

Gemini CLI example (`~/.gemini/settings.json`):

```json
{
  "mcpServers": {
    "adaptorch": {
      "command": "bash",
      "args": ["scripts/run_adaptorch_mcp.sh"],
      "env": {
        "ADAPTORCH_CONTROL_PLANE_BASE_URL": "http://127.0.0.1:8000"
      }
    }
  }
}
```

For runtime provider detection, `detect_provider_configuration(...)` now reports CLI
availability metadata (`cli_executable`, `cli_available`, `cli_path`) based on the
current filesystem `PATH`.

Before running a benchmark through subscription-auth CLIs, use the smoke test:

```bash
.venv/bin/python scripts/smoke_test_cli_subscriptions.py
```

Useful variants:

```bash
# Detect only, without making a model call
.venv/bin/python scripts/smoke_test_cli_subscriptions.py --skip-invoke

# Work around Codex session-directory ownership issues
.venv/bin/python scripts/smoke_test_cli_subscriptions.py --provider codex --codex-home /tmp/codex-home

# Ensure local Gemini wrapper is visible
PATH="$HOME/.local/bin:$PATH" .venv/bin/python scripts/smoke_test_cli_subscriptions.py --provider gemini-cli
```

### 5) Tune retry jitter and latency-aware backoff

`build_runtime_agent`, `build_runtime_agent_with_logprobs`, and
`build_streaming_agent` expose the full retry-backoff surface as keyword
arguments. The jitter strategy and latency-aware ceiling are **public, opt-in,
and backward compatible** — defaults reproduce the legacy additive jitter with a
static `retry_max_backoff_seconds` ceiling.

```python
from adaptorch.providers import build_runtime_agent

agent, metadata = build_runtime_agent(
    provider="openai",
    model="gpt-4o-mini",
    # classic backoff knobs
    retry_max_attempts=4,
    retry_initial_backoff_seconds=0.5,
    retry_max_backoff_seconds=8.0,
    retry_multiplier=2.0,
    retry_jitter_ratio=0.2,
    # P2 additions (opt-in):
    retry_jitter_strategy="full",          # "additive" | "full" | "decorrelated"
    retry_latency_aware_max_backoff=True,  # cap backoff at observed_latency * factor
    retry_latency_aware_factor=3.0,
)
```

- `retry_jitter_strategy`: `"additive"` (default, legacy) keeps `bounded + jitter`;
  `"full"` and `"decorrelated"` follow the AWS jitter recipes to reduce
  thundering-herd retries across parallel workers.
- `retry_latency_aware_max_backoff` / `retry_latency_aware_factor`: when enabled,
  the per-attempt ceiling is lowered to `observed_latency * factor`, so fast
  providers are retried sooner than the static ceiling allows. `build_streaming_agent`
  measures the latency of the failed connect/first-byte attempt, keeping
  streaming and non-streaming retry behavior consistent.

> The single-task routing CLI (`adaptorch <task.json>`) runs against the
> reference mock agent and never issues provider HTTP calls, so it intentionally
> exposes **no** retry flags. Benchmark provider retries are configured through
> the benchmark config `api.retry` block (`max_attempts`, `initial_backoff_seconds`,
> `max_backoff_seconds`, `multiplier`, `jitter_ratio`); the jitter-strategy and
> latency-aware knobs are currently Python-API only.

### 6) Prompt boundary and guardrail registry (opt-in)

Remote-agent and handoff outputs can be wrapped in provenance-tagged,
defanged delimiters before they are merged into downstream context:

```python
from adaptorch import AdaptOrchEngine

engine = AdaptOrchEngine(prompt_boundary_default=True)
result = engine.run(dag, agent=agent, prompt_boundary=True)  # per-call override
```

- `prompt_boundary_default` on the engine and `prompt_boundary` on `run` / `run_async`
  accept `bool | None`; `None` falls back to the engine default.
- The default remains `False` for backward compatibility.
- Recommended when consuming outputs from remote agents or handoffs.

DAGs restored from payloads can declare `guardrail_input`, `guardrail_output`,
or `handoff` nodes without a live callable. Register the callables globally and
rebind before execution:

```python
from adaptorch.guardrails import (
    GuardrailResult,
    rebind_guardrails,
    register_guardrail,
    register_handoff,
)

def pii_check(text: str) -> GuardrailResult:
    return GuardrailResult(
        passed=True, tripwire_triggered=False, output_info={}, reasoning="ok"
    )

register_guardrail("pii", pii_check, kind="input")
register_handoff("review", "reviewer-agent")

dag = rebind_guardrails(dag)  # or AdaptOrchEngine(auto_rebind_guardrails=True)
```

By default, unbound guardrail/handoff nodes fail closed with
`GuardrailUnboundError` (`error_class=guardrail_unbound`). To temporarily allow
legacy warning-only behavior, set `ADAPTORCH_ALLOW_UNBOUND_GUARDRAILS=1` or pass
`allow_unbound_guardrails=True`.

#### Runtime environment quick reference

| Environment variable | Default | Effect |
| --- | --- | --- |
| `ADAPTORCH_SSRF_PIN_IP` | unset (disabled) | Set to `1` to enable connection-time IP pinning for provider and A2A outbound URLs. |
| `ADAPTORCH_HTTP_MAX_RESPONSE_BYTES` | `33554432` (32 MiB) | Hard cap for non-streaming provider HTTP response bodies; set `0` to disable. |
| `ADAPTORCH_ALLOW_UNBOUND_GUARDRAILS` | unset (disabled) | Set to `1` to restore legacy warning-only behavior for unbound guardrail/handoff nodes. |
| `ADAPTORCH_HOSTED` | unset (`False`) | Set to `1` to signal hosted/multi-tenant control-plane mode. |
| `ADAPTORCH_HOSTED_STRICT` | unset (`False`) | Set to `1` to fail-closed (`RuntimeError`) when hosted mode is active but `local_admin_bootstrap` is not explicitly disabled. |
| `ADAPTORCH_EXECUTION_PROVIDER` | unset | Provider the control plane executes runs with (`openai`, `anthropic`, `groq`, `openrouter`, `google`, `codex`, `claude_code`, `gemini_cli`, `auto`). Unset means the `default_agent` echo stub, which a hosted process refuses to run on. |
| `ADAPTORCH_EXECUTION_MODEL` | unset | Default model when a run does not pin one. |
| `ADAPTORCH_EXECUTION_API_KEY_ENV` | provider default | Variable to read the provider key from. |
| `ADAPTORCH_EXECUTION_BASE_URL` | provider default | Optional custom OpenAI-compatible endpoint override (e.g. a self-hosted routing gateway); replaces the provider's default base URL. |
| `ADAPTORCH_EXECUTION_ENSEMBLE` | unset | `provider:model` members, comma separated. Two or more enable the ensemble fan-out `robust` synthesis needs; a single member or a missing key is refused, not downgraded. |
| `ADAPTORCH_EXECUTION_ENSEMBLE_TIMEOUT_SECONDS` | `60` | Ensemble fan-out wall clock. |
| `ADAPTORCH_EXECUTION_JUDGE` | unset | `provider:model` for the judge arbiter, which re-selects among ensemble candidates when agreement is low. |
| `ADAPTORCH_EXECUTION_JUDGE_AGREEMENT_THRESHOLD` | `0.5` | Arbitrate below this agreement rate. |
| `ADAPTORCH_ALLOW_STUB_EXECUTION` | unset (`False`) | Explicit opt-in to keep the echo stub in a hosted process. Every run it completes is fabricated; demo use only. |

> Hosted deployments fail closed: without an execution provider, `POST /v1/runs`
> returns `503` with a stable reason (e.g. `execution_provider_api_key_missing:OPENAI_API_KEY`)
> instead of completing the run with stub output. `GET /health` reports the same
> state under `execution` and `ensemble`.

## Input JSON Contract

```json
{
  "subtasks": [
    {"id": "v1", "description": "localize bug", "estimated_tokens": 200}
  ],
  "dependencies": [
    {"from": "v1", "to": "v2", "coupling": "strong"}
  ]
}
```

- `coupling`: `none` | `weak` | `strong` | `critical`, or float `0.0`-`1.0`
- If `dependencies` is omitted, edges are inferred from each subtask's `depends_on` and `coupling`

## Native Backend (Optional)

```bash
# Build native lexical kernel
bash scripts/build_native.sh

# Benchmark ON/OFF speed delta
python scripts/benchmark_native_backend.py --repeats 5 --iterations 2000
```

- Disable at runtime: `ADAPTORCH_DISABLE_NATIVE=1`
- Native kernels accelerate lexical pairwise consistency and robust eigensolver paths.
- Optional override: `ADAPTORCH_SYNTHESIS_WORKERS=<N>` (default keeps small workloads single-threaded)
- Policy guide: `docs/native_backend_policy.md`

## Benchmark Output Contract

```text
artifacts/benchmarks/<RUN_ID>/
├── manifest.json
├── raw_results.jsonl
├── summary.json
├── report.md
├── onepager.md
├── public_bundle/
│   ├── result_bundle.json
│   ├── onepager.md
│   ├── overview.png
│   └── benchmark_scorecard.png
└── tables/
    ├── table2.csv
    ├── table3.csv
    └── table4.csv
```

## Vibe Coding Share Loop

For coding-agent and vibe-coding communities, use this repeatable loop:

```bash
# 1) run benchmark
python -m adaptorch benchmark run --config <CONFIG> --json

# 2) produce fixed public evidence bundle
python -m adaptorch benchmark bundle --run-id <RUN_ID> --json

# 3) produce channel-ready post drafts
python scripts/generate_community_showcase.py --run-id <RUN_ID> --channel both --json
```

Generated files:

- `artifacts/benchmarks/<RUN_ID>/public_bundle/result_bundle.json`
- `artifacts/benchmarks/<RUN_ID>/public_bundle/onepager.md`
- `artifacts/benchmarks/<RUN_ID>/public_bundle/overview.png`
- `artifacts/benchmarks/<RUN_ID>/public_bundle/benchmark_scorecard.png`
- `artifacts/benchmarks/<RUN_ID>/showcase_post.md`

## Open Source Growth Plan

AdaptOrch is OSS-first and targets sustained public adoption.

- Target: `100+` GitHub stars with reproducible benchmark credibility.
- Plan: `docs/open_source_growth_plan.md`
- Support policy: `SUPPORT.md`

Execution priorities:

- Keep first-run experience below 5 minutes (install + sample task + benchmark report).
- Maintain release cadence with visible changelog updates.
- Curate contributor-friendly backlog (`good first issue`, docs-first tasks, benchmark tasks).
- Publish repeatable benchmark artifacts for every meaningful release.

## Enterprise / B2B Technical Readiness

AdaptOrch keeps OSS as the core while preparing enterprise-grade technical due diligence.

- Technical contract checklist: `docs/b2b_technical_contract_checklist.md`
- Security disclosure and response targets: `SECURITY.md`
- Versioning and compatibility policy: `docs/semver_policy.md`
- Commercial packaging guide (KR): `sales.md`
- Pilot proposal template: `docs/pilot_sprint_proposal_template.md`
- Pilot result report template: `docs/pilot_sprint_result_template.md`
- Language strategy: `docs/language_strategy.md`
- SaaS readiness decision (2026-03-27): `docs/saas_readiness_decision_2026-03-27.md`
- SaaS remediation roadmap (2026-03-27): `docs/plans/2026-03-27-saas-readiness-remediation-roadmap.md`
- SaaS page connection algorithm report: `SaaS_connection.md`
- Control-plane API contract (local v1 + experimental shared mode): `docs/control_plane_api_contract.md`
- n8n connector minimum spec (draft): `docs/n8n_connector_min_spec.md`
- GUI control-plane IA (implemented surface + follow-up work): `docs/gui_control_plane_ia.md`
- Policies surface draft: `docs/policies_surface_draft.md`
- SDK compatibility guide: `docs/sdk_compatibility.md`

Enterprise-facing expectations:

- Explicit API/output contract stability and change-control windows.
- Evidence package for pilot/procurement (build logs, test gates, benchmark report).
- Security and operations baseline (vulnerability reporting, release hygiene, rollback path).

## Control Plane

See the [Control Plane API contract](docs/control_plane_api_contract.md) for the
mode boundaries and complete configuration-name reference.

```bash
# 1) Install the local API dependencies
pip install -e ".[api]"

# 2) Configure authentication for direct uvicorn
# Direct uvicorn does not load .env; export the token in this shell.
export ADAPTORCH_CONTROL_PLANE_TOKEN="<local-token>"

# 3) Start the API server directly
uvicorn "adaptorch.control_plane:create_control_plane_app" \
  --factory --host 0.0.0.0 --port 8000

# Repository checkout helper only; [api] does not install this script or load .env
bash scripts/run_local_control_plane.sh

# 4) Inspect local dispatch configuration and Redis evidence
curl http://127.0.0.1:8000/health
```

A local/in-process **direct REST, single-subtask** run can supply an optional
request-scoped ensemble. All members must use the credential provider; the key
stays in headers and memory, not in JSON or persisted artifacts:

```bash
curl -X POST http://127.0.0.1:8000/v1/runs \
  -H "Authorization: Bearer <control-plane-token>" \
  -H "X-Provider: groq" \
  -H "X-Provider-Model: openai/gpt-oss-120b" \
  -H "X-Provider-Key: <provider-key>" \
  -H "Content-Type: application/json" \
  -d '{"payload":{"subtasks":[{"id":"v1","description":"Analyze the issue"}]},"synthesis_mode":"auto","ensemble_members":["groq:qwen/qwen3.8-27b","groq:openai/gpt-oss-120b"]}'
```

The list contains 2–5 members. When routing selects `multi_model_ensemble`, the
provider bills every member's tokens; supplying the list alone does not force a
multi-node DAG to fan out. The intended policy is one plan-quota debit per valid
run, but direct control-plane validation currently occurs after quota increment.
Request credentials cannot cross an RQ process boundary. Embedded hosted
`POST /mcp` currently ignores the member list, while in-process MCP rejects it;
use direct REST until those gaps close. See
[spec 012](specs/012-request-scoped-byok-ensembles/spec.md).

Local filesystem mode remains the default. It stores run state and artifacts
under `ADAPTORCH_CONTROL_PLANE_ROOT`, and `auto` dispatch remains in-process
unless local RQ auto-selection is explicitly enabled. Local RQ can move a job
through Redis, but identical filesystem visibility is necessary, not sufficient.
Process-local locks and whole-snapshot writes do not provide safe, durable
cross-process coordination. Redis cannot make local state or artifacts shared or
recoverable.

The source tree also contains an **experimental shared mode** selected through
`ADAPTORCH_CONTROL_PLANE_BACKEND` and configured with
`ADAPTORCH_SUPABASE_URL`, `ADAPTORCH_SUPABASE_SERVICE_ROLE_KEY`, and
`ADAPTORCH_CONTROL_PLANE_ARTIFACT_BUCKET`. These are variable names only; keep
all values server-side. Shared RQ jobs carry only an opaque `dispatch_id` and
load canonical data through the shared adapters. Shared mode rejects replay in
every dispatch mode and does not support benchmark operations.

> **Release NO-GO:** Do not deploy a separate shared RQ worker. Worker queues
> are not release-ready until every gate in
> [spec-008](specs/008-shared-control-plane-rq-worker/spec.md) passes, including
> migration reconciliation, disposable policy/concurrency rehearsal, shared
> artifact retrieval, independent restart recovery, and rollback approval. The
> current source and unit tests do not prove those gates.

`GET /health` reports dispatch state and a bounded Redis configuration/ping
probe (plus legacy filesystem diagnostics). It does not probe shared run or
artifact storage, confirm that a worker consumes jobs, or prove migration,
policy, rehearsal, or restart readiness.

Operational filesystem layout for the default local mode:

```text
artifacts/control_plane/
├── runs/<run_id>/{manifest.json,raw_results.jsonl,report.md,onepager.md}
└── state/runs.json
```

## Pilot Sprint Templates

Use the templates below to run 2-4 week pilots with a consistent KPI and
decision format.

- Proposal template: `docs/pilot_sprint_proposal_template.md`
- Result report template: `docs/pilot_sprint_result_template.md`

## Repository Structure

> **Note**: This repository now includes the recovered control-plane UI in
> `frontend/` and Railway deployment assets for the FastAPI + SPA surface.
> Older references to a separate deployment repository may be stale.

## Project Structure

```text
.
├── src/adaptorch/
│   ├── cli.py
│   ├── mcp_server.py
│   ├── control_plane/
│   ├── middleware_connectors.py
│   ├── n8n_connector.py
│   ├── synthesis.py
│   ├── verification.py
│   └── ...
├── docs/
│   ├── README.md
│   ├── library_api.md
│   ├── sdk_compatibility.md
│   ├── control_plane_api_contract.md
│   └── gui_control_plane_ia.md
├── examples/
│   ├── sample_task.json
│   ├── benchmark_paper_parity.json
│   ├── benchmark_cli_subscriptions_live.json
│   └── middleware payload examples
├── scripts/
│   ├── run_local_control_plane.sh
│   ├── run_adaptorch_mcp.sh
│   ├── start_control_plane_service.sh
│   └── benchmark/report helpers
├── frontend/
├── benchmarks/
├── specs/
└── tests/
```

## Reproducibility Scope

Included:

- Topology routing + adaptive synthesis core algorithms
- Robust synthesis mode
- Benchmark run/summarize/report pipeline
- Provider adapters with retry/rate-limit controls

Not included:

- Production-grade distributed quota arbitration
- Full official evaluator integration for all public benchmarks
- Byte-identical artifact replay outside the Full50 sidecar (standard benchmark
  artifacts are wall-clock-anchored; reproducibility is beta)

See full details in [REPRODUCIBILITY.md](docs/REPRODUCIBILITY.md).

## AI Search FAQ

### What is AdaptOrch?

AdaptOrch is a task-adaptive multi-agent orchestration library that routes DAG-shaped workloads and synthesizes model outputs with consistency-aware rerouting.

### Is AdaptOrch similar to LangGraph or agent workflow engines?

It overlaps in orchestration goals, but AdaptOrch focuses on explicit topology routing and synthesis diagnostics aligned with paper-style reproducibility (currently in beta).

### Can I use AdaptOrch with LangChain, n8n, OpenCode, Cline, Cursor, Windsurf, Lovable, and RAG stacks?

Yes. Use `adaptorch.agent_adapters` for CLI/SDK/RAG bridges and use the
control-plane API contract for n8n workflows. See `docs/sdk_compatibility.md`.

### Does AdaptOrch support robust output merging for noisy/free models?

Yes. `--synthesis-mode robust` adds conflict-signaling scoring and reroute behavior intended for unstable model outputs. Known adversarial gaps (e.g. semantic paraphrase false agreement) are disclosed in `tests/test_algorithm_eval_synthesis_corpus.py`.

### Is this project benchmark-friendly for research and reports?

Yes. It includes `benchmark run`, `benchmark summarize`, and `benchmark report` commands plus structured output artifacts.

### Is this README optimized for AI search engines like Perplexity?

Yes. It includes intent-focused summaries, FAQ-style Q/A, explicit keyword coverage, and a machine-readable `llms.txt` index entry.

### Which keywords best describe this project?

Multi-agent orchestration, LLM orchestration, DAG workflow routing, adaptive synthesis, robust synthesis, coding-agent integration, AI benchmark pipeline.

## Development

```bash
ruff check .
mypy
pytest -q
python -m build
```

CI runs equivalent quality gates on Python 3.11 and 3.12.

If you are building in an offline environment where the virtualenv is missing
`setuptools`/`wheel`, use:

```bash
bash scripts/build_offline.sh
```

## License

Apache-2.0. See [LICENSE](LICENSE).

## Citation

```bibtex
@article{yu2026adaptorch,
  title   = {AdaptOrch: Task-Adaptive Multi-Agent Orchestration in the Era of LLM Performance Convergence},
  author  = {Yu, Geunbin},
  journal = {arXiv preprint},
  year    = {2026}
}
```

Also available in [`CITATION.cff`](CITATION.cff).
